Skip to content
Snippets Groups Projects
Commit e6e4788d authored by nanocryk's avatar nanocryk
Browse files

Merge branch '13-add-keypair-type' into 'dev'

Resolve "Add keyPair type"

Closes #13

See merge request !9
parents 1417b5dc 924220bc
Branches
Tags keys/v0.3.0
1 merge request!9Resolve "Add keyPair type"
...@@ -33,7 +33,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" ...@@ -33,7 +33,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "duniter-keys" name = "duniter-keys"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
......
[package] [package]
name = "duniter-keys" name = "duniter-keys"
version = "0.2.0" version = "0.3.0"
authors = ["nanocryk <nanocryk@duniter.org>"] authors = ["nanocryk <nanocryk@duniter.org>"]
description = "Manage cryptographic keys for the Duniter project." description = "Manage cryptographic keys for the Duniter project."
repository = "https://git.duniter.org/nodes/rust/duniter-rs" repository = "https://git.duniter.org/nodes/rust/duniter-rs"
......
...@@ -29,7 +29,7 @@ use base64; ...@@ -29,7 +29,7 @@ use base64;
use base64::DecodeError; use base64::DecodeError;
use crypto; use crypto;
use super::BaseConvertionError; use super::{BaseConvertionError, PrivateKey as PrivateKeyMethods, PublicKey as PublicKeyMethods};
/// Store a ed25519 signature. /// Store a ed25519 signature.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
...@@ -211,9 +211,54 @@ impl super::PrivateKey for PrivateKey { ...@@ -211,9 +211,54 @@ 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.
pub privkey: PrivateKey,
}
impl Display for KeyPair {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "({}, hidden)", 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;
type PublicKey = PublicKey;
type PrivateKey = PrivateKey;
fn public_key(&self) -> PublicKey {
self.pubkey
}
fn private_key(&self) -> PrivateKey {
self.privkey
}
fn sign(&self, message: &[u8]) -> Signature {
self.private_key().sign(message)
}
fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool {
self.public_key().verify(message, signature)
}
}
/// Keypair generator with given parameters for `scrypt` keypair function. /// Keypair generator with given parameters for `scrypt` keypair function.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct KeyPairGenerator { pub struct KeyPairFromSaltedPasswordGenerator {
/// The log2 of the Scrypt parameter `N`. /// The log2 of the Scrypt parameter `N`.
log_n: u8, log_n: u8,
/// The Scrypt parameter `r` /// The Scrypt parameter `r`
...@@ -222,32 +267,32 @@ pub struct KeyPairGenerator { ...@@ -222,32 +267,32 @@ pub struct KeyPairGenerator {
p: u32, p: u32,
} }
impl KeyPairGenerator { impl KeyPairFromSaltedPasswordGenerator {
/// Create a `KeyPairGenerator` with default arguments `(log_n: 12, r: 16, p: 1)` /// Create a `KeyPairGenerator` with default arguments `(log_n: 12, r: 16, p: 1)`
pub fn with_default_parameters() -> KeyPairGenerator { pub fn with_default_parameters() -> KeyPairFromSaltedPasswordGenerator {
KeyPairGenerator { KeyPairFromSaltedPasswordGenerator {
log_n: 12, log_n: 12,
r: 16, r: 16,
p: 1, p: 1,
} }
} }
/// Create a `KeyPairGenerator` with given arguments. /// Create a `KeyPairFromSaltedPasswordGenerator` with given arguments.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - log_n - The log2 of the Scrypt parameter N /// - log_n - The log2 of the Scrypt parameter N
/// - r - The Scrypt parameter r /// - r - The Scrypt parameter r
/// - p - The Scrypt parameter p /// - p - The Scrypt parameter p
pub fn with_parameters(log_n: u8, r: u32, p: u32) -> KeyPairGenerator { pub fn with_parameters(log_n: u8, r: u32, p: u32) -> KeyPairFromSaltedPasswordGenerator {
KeyPairGenerator { log_n, r, p } KeyPairFromSaltedPasswordGenerator { log_n, r, p }
} }
/// Create a keypair based on a given password and salt. /// Create a keypair based on a given password and salt.
/// ///
/// The [`PublicKey`](struct.PublicKey.html) will be able to verify messaged signed with /// The [`PublicKey`](struct.PublicKey.html) will be able to verify messaged signed with
/// the [`PrivateKey`](struct.PrivateKey.html). /// the [`PrivateKey`](struct.PrivateKey.html).
pub fn generate(&self, password: &[u8], salt: &[u8]) -> (PrivateKey, PublicKey) { pub fn generate(&self, password: &[u8], salt: &[u8]) -> KeyPair {
let mut seed = [0u8; 32]; let mut seed = [0u8; 32];
crypto::scrypt::scrypt( crypto::scrypt::scrypt(
password, password,
...@@ -257,14 +302,17 @@ impl KeyPairGenerator { ...@@ -257,14 +302,17 @@ impl KeyPairGenerator {
); );
let (private, public) = crypto::ed25519::keypair(&seed); let (private, public) = crypto::ed25519::keypair(&seed);
(PrivateKey(private), PublicKey(public)) KeyPair {
pubkey: PublicKey(public),
privkey: PrivateKey(private),
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use {PrivateKey, PublicKey, Signature}; use {KeyPair, Signature};
#[test] #[test]
fn base58_private_key() { fn base58_private_key() {
...@@ -394,4 +442,21 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 ...@@ -394,4 +442,21 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
assert_eq!(sig, expected_signature); assert_eq!(sig, expected_signature);
assert!(pubkey.verify(message.as_bytes(), &sig)); assert!(pubkey.verify(message.as_bytes(), &sig));
} }
#[test]
fn keypair_generate_sign_and_verify() {
let keypair = KeyPairFromSaltedPasswordGenerator::with_default_parameters()
.generate("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.verify(message.as_bytes(), &sig));
}
} }
...@@ -21,21 +21,21 @@ ...@@ -21,21 +21,21 @@
//! # Usage //! # Usage
//! //!
//! ``` //! ```
//! use duniter_keys::{Signature, PublicKey, PrivateKey}; //! use duniter_keys::{Signature, PublicKey, PrivateKey, KeyPair};
//! use duniter_keys::ed25519::KeyPairGenerator; //! use duniter_keys::ed25519::KeyPairFromSaltedPasswordGenerator;
//! //!
//! let generator = KeyPairGenerator::with_default_parameters(); //! let generator = KeyPairFromSaltedPasswordGenerator::with_default_parameters();
//! //!
//! let (private_key, public_key) = generator.generate( //! let keypair = generator.generate(
//! b"password", //! b"password",
//! b"salt" //! b"salt"
//! ); //! );
//! //!
//! let message = "Hello, world!"; //! let message = "Hello, world!";
//! //!
//! let signature = private_key.sign(&message.as_bytes()); //! let signature = keypair.sign(&message.as_bytes());
//! //!
//! assert!(public_key.verify(&message.as_bytes(), &signature)); //! assert!(keypair.pubkey.verify(&message.as_bytes(), &signature));
//! ``` //! ```
//! //!
//! # Format //! # Format
...@@ -147,3 +147,25 @@ pub trait PrivateKey: Clone + Display + Debug + PartialEq + Eq + ToBase58 { ...@@ -147,3 +147,25 @@ pub trait PrivateKey: Clone + Display + Debug + PartialEq + Eq + ToBase58 {
/// Sign a message with this private key. /// Sign a message with this private key.
fn sign(&self, message: &[u8]) -> Self::Signature; 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;
/// PublicKey type of associated cryptosystem.
type PublicKey: PublicKey;
/// PrivateKey type of associated cryptosystem.
type PrivateKey: PrivateKey;
/// Get `PublicKey`
fn public_key(&self) -> Self::PublicKey;
/// Get `PrivateKey`
fn private_key(&self) -> Self::PrivateKey;
/// Sign a message with private key.
fn sign(&self, message: &[u8]) -> Self::Signature;
/// Verify a signature with public key.
fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment