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)
    }
}