diff --git a/keys/ed25519.rs b/keys/ed25519.rs index 8bb13a9108dcc9a44544c50a8b522ca3fc5c2b78..cbf63730d19b174946661c6a5e90e3fb0d7afa00 100644 --- a/keys/ed25519.rs +++ b/keys/ed25519.rs @@ -211,6 +211,45 @@ impl super::PrivateKey for PrivateKey { } } +/// Store a ed25519 cryptographic key pair (`PublicKey` + `PrivateKey`) +#[derive(Debug, Copy, Clone)] +pub struct KeyPair { + /// Store a Ed25519 public key. + pub pubkey:PublicKey, + /// Store a Ed25519 private key. + privkey:PrivateKey, +} + +impl Display for KeyPair { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "{}", self.pubkey.to_base58()) + } +} + +impl PartialEq<KeyPair> for KeyPair { + fn eq(&self, other: &KeyPair) -> bool { + self.pubkey.eq(&other.pubkey) && self.privkey.eq(&other.privkey) + } +} + +impl Eq for KeyPair {} + +impl super::KeyPair for KeyPair { + type Signature = Signature; + + fn new(password: &[u8], salt: &[u8]) -> KeyPair { + let generator = self::KeyPairGenerator::with_default_parameters(); + let (privkey, pubkey) = generator.generate(password, salt); + KeyPair { + pubkey, + privkey + } + } + fn sign(&self, message: &[u8]) -> Signature { + Signature(crypto::ed25519::signature(message, &self.privkey.0)) + } +} + /// Keypair generator with given parameters for `scrypt` keypair function. #[derive(Debug, Copy, Clone)] pub struct KeyPairGenerator { @@ -264,7 +303,7 @@ impl KeyPairGenerator { #[cfg(test)] mod tests { use super::*; - use {PrivateKey, PublicKey, Signature}; + use {PrivateKey, PublicKey, Signature, KeyPair}; #[test] fn base58_private_key() { @@ -284,12 +323,12 @@ mod tests { super::PrivateKey::from_base58(private58).unwrap() ); - assert_eq!( - super::PrivateKey::from_base58( - "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iA\ - fZACm7djh", - ).unwrap_err(), - BaseConvertionError::InvalidKeyLendth(67, 64) + assert_eq!( + super::PrivateKey::from_base58( + "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iA\ + fZACm7djh", + ).unwrap_err(), + BaseConvertionError::InvalidKeyLendth(67, 64) ); assert_eq!( super::PrivateKey::from_base58( @@ -381,12 +420,12 @@ mod tests { MMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", ).unwrap(); - let message = "Version: 10 -Type: Identity -Currency: duniter_unit_test_currency -Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV -UniqueID: tic -Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 + let message = "Version: 10 +Type: Identity +Currency: duniter_unit_test_currency +Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV +UniqueID: tic +Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 "; let sig = prikey.sign(message.as_bytes()); @@ -394,4 +433,20 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 assert_eq!(sig, expected_signature); assert!(pubkey.verify(message.as_bytes(), &sig)); } + + #[test] + fn keypair_generate_sign_and_verify () { + let keypair = super::KeyPair::new("password".as_bytes(), "salt".as_bytes()); + + let message = "Version: 10 +Type: Identity +Currency: duniter_unit_test_currency +Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV +UniqueID: tic +Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 +"; + + let sig = keypair.sign(message.as_bytes()); + assert!(keypair.pubkey.verify(message.as_bytes(), &sig)); + } } diff --git a/keys/lib.rs b/keys/lib.rs index 49842a68658245ab861addd34c659bd00596a0ab..f765bc5795e02bfa3940a931e89e1abc92ab86ff 100644 --- a/keys/lib.rs +++ b/keys/lib.rs @@ -147,3 +147,15 @@ pub trait PrivateKey: Clone + Display + Debug + PartialEq + Eq + ToBase58 { /// Sign a message with this private key. fn sign(&self, message: &[u8]) -> Self::Signature; } + +/// Store a cryptographic key pair (`PublicKey` + `PrivateKey`) +pub trait KeyPair: Clone + Display + Debug + PartialEq + Eq { + /// Signature type of associated cryptosystem. + type Signature: Signature; + + /// Create a new KeyPair + fn new(password: &[u8], salt: &[u8]) -> Self; + + /// Sign a message with privkey. + fn sign(&self, message: &[u8]) -> Self::Signature; +}