litep2p/crypto/noise/
x25519_spec.rs

1// Copyright 2019 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use rand::Rng;
22use x25519_dalek::{x25519, X25519_BASEPOINT_BYTES};
23use zeroize::Zeroize;
24
25use crate::crypto::noise::protocol::{Keypair, PublicKey, SecretKey};
26
27/// A X25519 key.
28#[derive(Clone)]
29pub struct X25519Spec([u8; 32]);
30
31impl AsRef<[u8]> for X25519Spec {
32    fn as_ref(&self) -> &[u8] {
33        self.0.as_ref()
34    }
35}
36
37impl Zeroize for X25519Spec {
38    fn zeroize(&mut self) {
39        self.0.zeroize()
40    }
41}
42
43impl Keypair<X25519Spec> {
44    /// An "empty" keypair as a starting state for DH computations in `snow`,
45    /// which get manipulated through the `snow::types::Dh` interface.
46    pub(super) fn default() -> Self {
47        Keypair {
48            secret: SecretKey(X25519Spec([0u8; 32])),
49            public: PublicKey(X25519Spec([0u8; 32])),
50        }
51    }
52
53    /// Create a new X25519 keypair.
54    pub fn new() -> Keypair<X25519Spec> {
55        let mut sk_bytes = [0u8; 32];
56        rand::thread_rng().fill(&mut sk_bytes);
57        let sk = SecretKey(X25519Spec(sk_bytes)); // Copy
58        sk_bytes.zeroize();
59        Self::from(sk)
60    }
61}
62
63impl Default for Keypair<X25519Spec> {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69/// Promote a X25519 secret key into a keypair.
70impl From<SecretKey<X25519Spec>> for Keypair<X25519Spec> {
71    fn from(secret: SecretKey<X25519Spec>) -> Keypair<X25519Spec> {
72        let public = PublicKey(X25519Spec(x25519((secret.0).0, X25519_BASEPOINT_BYTES)));
73        Keypair { secret, public }
74    }
75}
76
77impl snow::types::Dh for Keypair<X25519Spec> {
78    fn name(&self) -> &'static str {
79        "25519"
80    }
81    fn pub_len(&self) -> usize {
82        32
83    }
84    fn priv_len(&self) -> usize {
85        32
86    }
87    fn pubkey(&self) -> &[u8] {
88        self.public.as_ref()
89    }
90    fn privkey(&self) -> &[u8] {
91        self.secret.as_ref()
92    }
93
94    fn set(&mut self, sk: &[u8]) {
95        let mut secret = [0u8; 32];
96        secret.copy_from_slice(sk);
97        self.secret = SecretKey(X25519Spec(secret));
98        self.public = PublicKey(X25519Spec(x25519(secret, X25519_BASEPOINT_BYTES)));
99        secret.zeroize();
100    }
101
102    fn generate(&mut self, rng: &mut dyn snow::types::Random) {
103        let mut secret = [0u8; 32];
104        rng.fill_bytes(&mut secret);
105        self.secret = SecretKey(X25519Spec(secret));
106        self.public = PublicKey(X25519Spec(x25519(secret, X25519_BASEPOINT_BYTES)));
107        secret.zeroize();
108    }
109
110    fn dh(&self, pk: &[u8], shared_secret: &mut [u8]) -> Result<(), snow::Error> {
111        let mut p = [0; 32];
112        p.copy_from_slice(&pk[..32]);
113        let ss = x25519((self.secret.0).0, p);
114        shared_secret[..32].copy_from_slice(&ss[..]);
115        Ok(())
116    }
117}