diff --git a/Cargo.toml b/Cargo.toml index 9ff51ff..86e030e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multikey" -version = "1.0.7" +version = "1.1.0" edition = "2021" authors = ["Dave Grantham "] description = "Multikey self-describing cryptographic key data" @@ -13,7 +13,7 @@ default = ["serde"] [dependencies] bcrypt-pbkdf = "0.10" -blsful = { version = "2.5", git = "https://github.com/mikelodder7/blsful.git" } +blsful = { version = "2.5" } ed25519-dalek = { version = "2.1", features = ["rand_core"] } elliptic-curve = "0.13" hex = "0.4" diff --git a/src/attrid.rs b/src/attrid.rs index 89a5835..b22d20a 100644 --- a/src/attrid.rs +++ b/src/attrid.rs @@ -33,6 +33,10 @@ pub enum AttrId { ShareIdentifier, /// codec-specific threshold key data ThresholdData, + /// an algorithm string name for non-standard keys (optional) + AlgorithmName, + /// an arbitrary key type for non-standard keys (optional) + KeyType, } impl AttrId { @@ -56,6 +60,8 @@ impl AttrId { AttrId::Limit => "limit", AttrId::ShareIdentifier => "share-identifier", AttrId::ThresholdData => "threshold-data", + AttrId::AlgorithmName => "algorithm-name", + AttrId::KeyType => "key-type", } } } @@ -83,6 +89,8 @@ impl TryFrom for AttrId { 9 => Ok(AttrId::Limit), 10 => Ok(AttrId::ShareIdentifier), 11 => Ok(AttrId::ThresholdData), + 12 => Ok(AttrId::AlgorithmName), + 13 => Ok(AttrId::KeyType), _ => Err(AttributesError::InvalidAttributeValue(c).into()), } } @@ -130,6 +138,8 @@ impl TryFrom<&str> for AttrId { "limit" => Ok(AttrId::Limit), "share-identifier" => Ok(AttrId::ShareIdentifier), "threshold-data" => Ok(AttrId::ThresholdData), + "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 630f1e2..cb90bbb 100644 --- a/src/cipher.rs +++ b/src/cipher.rs @@ -1,5 +1,5 @@ // SPDX-License-Idnetifier: Apache-2.0 -use crate::{mk::Attributes, AttrId, Error, Multikey}; +use crate::{error::CipherError, mk::Attributes, AttrId, Error, Multikey}; use multicodec::Codec; use rand::{CryptoRng, RngCore}; 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 d9daab5..e62b23c 100644 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -1,5 +1,5 @@ // SPDX-License-Idnetifier: Apache-2.0 -use crate::{mk::Attributes, AttrId, Error, Multikey}; +use crate::{error::KdfError, mk::Attributes, AttrId, Error, Multikey}; use multicodec::Codec; use multiutil::Varuint; use rand::{CryptoRng, RngCore}; @@ -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 b2421e6..a8b4fe6 100644 --- a/src/mk.rs +++ b/src/mk.rs @@ -20,7 +20,8 @@ use std::{collections::BTreeMap, fmt}; use zeroize::Zeroizing; /// the list of key codecs supported for key generation -pub const KEY_CODECS: [Codec; 4] = [ +pub const KEY_CODECS: [Codec; 5] = [ + Codec::Identity, // used for non-standard key types Codec::Ed25519Priv, /* Codec::LamportSha3256Priv, @@ -32,20 +33,20 @@ pub const KEY_CODECS: [Codec; 4] = [ */ Codec::Secp256K1Priv, Codec::Bls12381G1Priv, - Codec::Bls12381G2Priv + Codec::Bls12381G2Priv, ]; /// the list of key share codecs supported pub const KEY_SHARE_CODECS: [Codec; 4] = [ - Codec::Bls12381G1PubShare, - Codec::Bls12381G1PrivShare, - Codec::Bls12381G2PubShare, - Codec::Bls12381G2PrivShare /* Codec::LamportSha3256PrivShare, Codec::LamportSha3384PrivShare, Codec::LamportSha3512PrivShare, */ + Codec::Bls12381G1PubShare, + Codec::Bls12381G1PrivShare, + Codec::Bls12381G2PubShare, + Codec::Bls12381G2PrivShare, ]; /// the multicodec sigil for multikey @@ -913,8 +914,16 @@ mod tests { }; println!("encoded pubkey: {}: {}", codec, epk); println!("encoded pubkey v: {}: {}", codec, hex::encode(vpk)); - println!("encoded privkey: {}: {}", codec, EncodedMultikey::from(mk.clone())); - println!("encoded privkey v: {}: {}", codec, hex::encode(Into::>::into(mk.clone()))); + println!( + "encoded privkey: {}: {}", + codec, + EncodedMultikey::from(mk.clone()) + ); + println!( + "encoded privkey v: {}: {}", + codec, + hex::encode(Into::>::into(mk.clone())) + ); let _v: Vec = mk.into(); } } @@ -1148,8 +1157,9 @@ mod tests { assert!(kd.key_bytes().is_ok()); assert!(kd.secret_bytes().is_ok()); - let msg = hex::decode("8bb78be51ac7cc98f44e38947ff8a128764ec039b89687a790dfa8444ba97682") - .unwrap(); + let msg = + hex::decode("8bb78be51ac7cc98f44e38947ff8a128764ec039b89687a790dfa8444ba97682") + .unwrap(); let signmk = mk.sign_view().unwrap(); let signature = if codec == Codec::Bls12381G1Priv || codec == Codec::Bls12381G2Priv { @@ -1245,9 +1255,7 @@ mod tests { #[test] fn test_from_ssh_pubkey() { let mut rng = rand::rngs::OsRng::default(); - let kp = KeypairData::Ed25519(Ed25519Keypair::random( - &mut rng, - )); + let kp = KeypairData::Ed25519(Ed25519Keypair::random(&mut rng)); let sk = PrivateKey::new(kp, "test key").unwrap(); // build a multikey from the public key @@ -1270,9 +1278,7 @@ mod tests { #[test] fn test_from_ssh_privkey() { let mut rng = rand::rngs::OsRng::default(); - let kp = KeypairData::Ed25519(Ed25519Keypair::random( - &mut rng, - )); + let kp = KeypairData::Ed25519(Ed25519Keypair::random(&mut rng)); let sk = PrivateKey::new(kp, "test key").unwrap(); let mk = Builder::new_from_ssh_private_key(&sk) diff --git a/src/serde/de.rs b/src/serde/de.rs index f66d307..b18c456 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)?) } } }