diff --git a/Cargo.toml b/Cargo.toml index 5d0b51b..79c816d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-key" -version = "1.0.3" +version = "1.0.5" edition = "2021" authors = ["Dave Grantham "] description = "Multikey self-describing cryptographic key data" diff --git a/src/attrid.rs b/src/attrid.rs index 15a23f6..cbe87f0 100644 --- a/src/attrid.rs +++ b/src/attrid.rs @@ -78,6 +78,10 @@ pub enum AttrId { /// CBOR-encoded `ThresholdMetaCipher` (cipher codec + nonce) for decrypting /// `EncryptedThresholdMeta`. ThresholdMetaCipher, + /// An algorithm string name for non-standard keys (optional) + AlgorithmName, + /// An arbitrary key type for non-standard keys (optional) + KeyType, } impl AttrId { @@ -116,6 +120,8 @@ impl AttrId { AttrId::ThresholdDisclosure => "threshold-disclosure", AttrId::EncryptedThresholdMeta => "encrypted-threshold-meta", AttrId::ThresholdMetaCipher => "threshold-meta-cipher", + AttrId::AlgorithmName => "algorithm-name", + AttrId::KeyType => "key-type", } } } @@ -158,6 +164,8 @@ impl TryFrom for AttrId { 24 => Ok(AttrId::ThresholdDisclosure), 25 => Ok(AttrId::EncryptedThresholdMeta), 26 => Ok(AttrId::ThresholdMetaCipher), + 27 => Ok(AttrId::AlgorithmName), + 28 => Ok(AttrId::KeyType), _ => Err(AttributesError::InvalidAttributeValue(c).into()), } } @@ -220,6 +228,8 @@ impl TryFrom<&str> for AttrId { "threshold-disclosure" => Ok(AttrId::ThresholdDisclosure), "encrypted-threshold-meta" => Ok(AttrId::EncryptedThresholdMeta), "threshold-meta-cipher" => Ok(AttrId::ThresholdMetaCipher), + "algorithm-name" => Ok(AttrId::AlgorithmName), + "key-type" => Ok(AttrId::KeyType), _ => Err(AttributesError::InvalidAttributeName(s.to_string()).into()), } } diff --git a/src/cipher.rs b/src/cipher.rs index 463aea6..28d02cd 100644 --- a/src/cipher.rs +++ b/src/cipher.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -use crate::{mk::Attributes, AttrId, Error, Multikey}; +use crate::{error::CipherError, mk::Attributes, AttrId, Error, Multikey}; use multi_codec::Codec; use rand_core::CryptoRng; use zeroize::Zeroizing; @@ -24,12 +24,13 @@ impl Builder { /// initialize from a multikey with cipher attributes in it pub fn try_from_multikey(mut self, mk: &Multikey) -> Result { - // try to look up the cipher codec in the multikey attributes - if let Some(v) = mk.attributes.get(&AttrId::CipherCodec) { - if let Ok(codec) = Codec::try_from(v.as_slice()) { - self.codec = codec; - } - } + // look up the cipher codec in the multikey attributes + let v = mk + .attributes + .get(&AttrId::CipherCodec) + .ok_or(CipherError::MissingCodec)?; + self.codec = Codec::try_from(v.as_slice())?; + // try to look up the key_length in the multikey attributes if let Some(v) = mk.attributes.get(&AttrId::CipherKeyLen) { self.key_length = Some(v.clone()); diff --git a/src/kdf.rs b/src/kdf.rs index eea760c..6896f63 100644 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -use crate::{mk::Attributes, AttrId, Error, Multikey}; +use crate::{error::KdfError, mk::Attributes, AttrId, Error, Multikey}; use multi_codec::Codec; use multi_util::Varuint; use rand_core::CryptoRng; @@ -24,12 +24,13 @@ impl Builder { /// initialize from a multikey with kdf attributes in it pub fn try_from_multikey(mut self, mk: &Multikey) -> Result { - // try to look up the kdf codec in the multikey attributes - if let Some(v) = mk.attributes.get(&AttrId::KdfCodec) { - if let Ok(codec) = Codec::try_from(v.as_slice()) { - self.codec = codec; - } - } + // look up the kdf codec in the multikey attributes + let v = mk + .attributes + .get(&AttrId::KdfCodec) + .ok_or(KdfError::MissingCodec)?; + self.codec = Codec::try_from(v.as_slice())?; + // try to look up the salt in the multikey attributes if let Some(v) = mk.attributes.get(&AttrId::KdfSalt) { self.salt = Some(v.clone()); diff --git a/src/mk.rs b/src/mk.rs index e2b15b1..5ac1881 100644 --- a/src/mk.rs +++ b/src/mk.rs @@ -33,7 +33,8 @@ use std::{collections::BTreeMap, fmt}; use zeroize::Zeroizing; /// the list of key codecs supported for key generation -pub const KEY_CODECS: [Codec; 7] = [ +pub const KEY_CODECS: [Codec; 8] = [ + Codec::Identity, // used for non-standard key types Codec::Ed25519Priv, Codec::Secp256K1Priv, Codec::Bls12381G1Priv, diff --git a/src/serde/de.rs b/src/serde/de.rs index ea0858a..37f4cdf 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -60,7 +60,7 @@ impl<'de> Deserialize<'de> for Nonce { deserializer.deserialize_struct(nonce::SIGIL.as_str(), FIELDS, NonceVisitor) } else { let b: &'de [u8] = Deserialize::deserialize(deserializer)?; - Ok(Self::try_from(b).map_err(|e| Error::custom(e.to_string()))?) + Ok(Self::try_from(b).map_err(D::Error::custom)?) } } } @@ -84,28 +84,28 @@ impl<'de> Deserialize<'de> for AttrId { where E: Error, { - AttrId::try_from(c).map_err(|e| Error::custom(e.to_string())) + AttrId::try_from(c).map_err(E::custom) } fn visit_str(self, s: &str) -> Result where E: Error, { - AttrId::try_from(s).map_err(|e| Error::custom(e.to_string())) + AttrId::try_from(s).map_err(E::custom) } fn visit_borrowed_str(self, s: &'de str) -> Result where E: Error, { - AttrId::try_from(s).map_err(|e| Error::custom(e.to_string())) + AttrId::try_from(s).map_err(E::custom) } fn visit_string(self, s: String) -> Result where E: Error, { - AttrId::try_from(s.as_str()).map_err(|e| Error::custom(e.to_string())) + AttrId::try_from(s.as_str()).map_err(E::custom) } } @@ -198,7 +198,7 @@ impl<'de> Deserialize<'de> for Multikey { deserializer.deserialize_struct(mk::SIGIL.as_str(), FIELDS, MultikeyVisitor) } else { let b: &'de [u8] = Deserialize::deserialize(deserializer)?; - Ok(Self::try_from(b).map_err(|e| Error::custom(e.to_string()))?) + Ok(Self::try_from(b).map_err(D::Error::custom)?) } } }