embedded_td/crypto/
ed25519.rs

1use curve25519_dalek_ng::{constants, scalar::Scalar};
2use rand_core::{CryptoRng, RngCore};
3use sha2::{Digest, Sha512};
4
5use super::define_as_ref_u8_array;
6
7#[derive(Debug, Clone)]
8pub struct SecretKey(pub [u8; 64]);
9define_as_ref_u8_array!(SecretKey);
10
11#[derive(Debug, Clone)]
12pub struct PublicKey(pub [u8; 32]);
13define_as_ref_u8_array!(PublicKey);
14
15impl SecretKey {
16    pub fn generate(rng: impl RngCore + CryptoRng) -> Self {
17        let mut rng = rng;
18
19        let mut sk = [0u8; 64];
20
21        rng.fill_bytes(&mut sk[..32]);
22
23        // sk to pk
24
25        let mut h = Sha512::new();
26        let mut hash: [u8; 64] = [0u8; 64];
27        let mut digest: [u8; 32] = [0u8; 32];
28
29        h.update(&sk[..32]);
30        hash.copy_from_slice(&h.finalize());
31
32        digest.copy_from_slice(&hash[..32]);
33
34        // mangle_scalar_bits_and_multiply_by_basepoint_to_produce_public_key
35        {
36            let mut bits = digest;
37
38            bits[0] &= 248;
39            bits[31] &= 127;
40            bits[31] |= 64;
41
42            let point = &Scalar::from_bits(bits) * &constants::ED25519_BASEPOINT_TABLE;
43            let compressed = point.compress();
44
45            let pk = &mut sk[32..];
46
47            pk.copy_from_slice(&compressed.0);
48        }
49
50        Self(sk)
51    }
52
53    pub fn public_key(&self) -> PublicKey {
54        let mut pk = [0u8; 32];
55
56        pk.copy_from_slice(&self.0[32..]);
57        PublicKey(pk)
58    }
59}