embedded_td/crypto/
sr25519.rs1use curve25519_dalek_ng::{constants, scalar::Scalar};
2use rand_core::{CryptoRng, RngCore};
3use sha2::{digest::FixedOutput, Digest, Sha512};
4
5use super::define_as_ref_u8_array;
6
7#[derive(Debug, Clone)]
8pub struct SecretKey(pub [u8; 32]);
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; 32];
20
21 rng.fill_bytes(&mut sk);
22
23 SecretKey(sk)
24 }
25
26 pub fn public_key(&self) -> PublicKey {
27 let mut h = Sha512::default();
28 h.update(self.0);
29 let r = h.finalize_fixed();
30
31 let mut key = [0u8; 32];
32 key.copy_from_slice(&r.as_slice()[0..32]);
33 key[0] &= 248;
34 key[31] &= 63;
35 key[31] |= 64;
36
37 divide_scalar_bytes_by_cofactor(&mut key);
38 let key = Scalar::from_bits(key);
39
40 let point = &key * &constants::RISTRETTO_BASEPOINT_TABLE;
41
42 let compressed = point.compress();
43
44 PublicKey(compressed.to_bytes())
45 }
46}
47
48fn divide_scalar_bytes_by_cofactor(scalar: &mut [u8; 32]) {
49 let mut low = 0u8;
50 for i in scalar.iter_mut().rev() {
51 let r = *i & 0b00000111; *i >>= 3; *i += low;
54 low = r << 5;
55 }
56}