1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
/*! # Keynesis Keys This module defines some kind of keys that can be used for signing, for deriving a shared secret between 2 keys or building a hierarchical deterministic keys (see below). # Key Derivation The key defined there can be derived. Just like with BIP32 but instead of using integer for the derivation the derivation's path is a slice of bytes, allowing the users to build any kind of hierarchy without limiting themselves to 2^32 options. It is then possible to define a root master key and to derive specific purpose keys from this root key. ``` use keynesis::key::ed25519_hd::SecretKey; # use rand::thread_rng; # let bob_root_key = SecretKey::new(&mut thread_rng()); # let bob_root_pk = bob_root_key.public_key(); let alice_root_key = SecretKey::new(&mut thread_rng()); # let alice_root_pk = alice_root_key.public_key(); let alice_key_exchange_with_bob = alice_root_key.derive(b"encryption:bob"); # let bob_key_exchange_with_alice = bob_root_key.derive(b"encryption:alice"); // alice retrieves the public key from bob's root public key // and uses it for the key exchange let shared_secret_with_bob = alice_key_exchange_with_bob.exchange( &bob_root_pk.derive(b"encryption:alice").unwrap() ); // bob can compute the shared secret with alice's root public key let shared_secret_with_alice = bob_key_exchange_with_alice.exchange( &alice_root_pk.derive(b"encryption:bob").unwrap() ); // the shared secret is the same for both alice and bob assert_eq!(shared_secret_with_bob, shared_secret_with_alice); ``` # SharedSecret for encryption Once a shared secret has been established it is possible to use it to seed a stream Cipher (authenticated or not, ChaCha20 with (or without) Poly1307). ``` # use keynesis::key::ed25519_hd::SecretKey; # use rand::thread_rng; use cryptoxide::{chacha20::ChaCha20, symmetriccipher::SynchronousStreamCipher as _}; # let bob_root_key = SecretKey::new(&mut thread_rng()); # let bob_root_pk = bob_root_key.public_key(); # let alice_root_key = SecretKey::new(&mut thread_rng()); # # let alice_key_exchange_with_bob = alice_root_key.derive(b"encryption:bob"); # let shared_secret_with_bob = alice_key_exchange_with_bob.exchange( # &bob_root_pk.derive(b"encryption:alice").unwrap() # ); # const NONCE: &[u8] = b"0123456789ab"; let mut encryption_context = ChaCha20::new(shared_secret_with_bob.as_ref(), &NONCE); # let mut decryption_context = ChaCha20::new(shared_secret_with_bob.as_ref(), &NONCE); let message: &[u8] = b"Secret Message between alice and bob"; let mut encrypted = vec![0; message.len()]; # let mut decrypted = vec![0; message.len()]; encryption_context.process(message, &mut encrypted); # decryption_context.process(&encrypted, &mut decrypted); # assert_eq!(message, decrypted.as_slice()); ``` */ pub mod ed25519; pub mod ed25519_extended; pub mod ed25519_hd; pub mod curve25519; mod shared_secret; pub use self::shared_secret::SharedSecret; use rand_core::{CryptoRng, RngCore}; pub trait Dh { fn name() -> &'static str; fn generate<RNG>(rng: &mut RNG) -> Self where RNG: RngCore + CryptoRng; fn public(&self) -> ed25519::PublicKey; fn dh(&self, public: &ed25519::PublicKey) -> SharedSecret; } impl Dh for curve25519::SecretKey { fn name() -> &'static str { "25519" } fn generate<RNG>(rng: &mut RNG) -> Self where RNG: RngCore + CryptoRng, { Self::new(rng) } #[inline] fn public(&self) -> ed25519::PublicKey { self.public_key() } #[inline] fn dh(&self, public: &ed25519::PublicKey) -> SharedSecret { self.exchange(public) } } impl Dh for ed25519::SecretKey { fn name() -> &'static str { "ed25519" } fn generate<RNG>(rng: &mut RNG) -> Self where RNG: RngCore + CryptoRng, { Self::new(rng) } #[inline] fn public(&self) -> ed25519::PublicKey { self.public_key() } #[inline] fn dh(&self, public: &ed25519::PublicKey) -> SharedSecret { self.exchange(public) } } impl Dh for ed25519_extended::SecretKey { fn name() -> &'static str { "ed25519" } fn generate<RNG>(rng: &mut RNG) -> Self where RNG: RngCore + CryptoRng, { Self::new(rng) } #[inline] fn public(&self) -> ed25519::PublicKey { self.public_key() } #[inline] fn dh(&self, public: &ed25519::PublicKey) -> SharedSecret { self.exchange(public) } } impl Dh for ed25519_hd::SecretKey { fn name() -> &'static str { "ed25519" } fn generate<RNG>(rng: &mut RNG) -> Self where RNG: RngCore + CryptoRng, { Self::new(rng) } #[inline] fn public(&self) -> ed25519::PublicKey { self.key().public_key() } #[inline] fn dh(&self, public: &ed25519::PublicKey) -> SharedSecret { self.key().exchange(public) } }