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
use rand_core::{ RngCore, CryptoRng };
use hacl_star_sys as ffi;


const BASEPOINT: [u8; 32] = [9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

pub const PUBLIC_LENGTH: usize = 32;
pub const SECRET_LENGTH: usize = 32;

define!{
    pub struct SecretKey/secretkey(pub [u8; SECRET_LENGTH]);
    pub struct PublicKey/publickey(pub [u8; SECRET_LENGTH]);
}

#[inline]
pub fn keypair<R: RngCore + CryptoRng>(mut rng: R) -> (SecretKey, PublicKey) {
    let mut sk = [0; SECRET_LENGTH];
    let mut pk = [0; SECRET_LENGTH];

    rng.fill_bytes(&mut sk);
    scalarmult(&mut pk, &sk, &BASEPOINT);

    (SecretKey(sk), PublicKey(pk))
}

impl SecretKey {
    #[inline]
    pub fn get_public(&self) -> PublicKey {
        let SecretKey(sk) = self;
        let mut pk = [0; 32];

        scalarmult(&mut pk, sk, &BASEPOINT);

        PublicKey(pk)
    }

    pub fn exchange(&self, &PublicKey(ref pk): &PublicKey, output: &mut [u8; 32]) {
        let SecretKey(sk) = self;

        scalarmult(output, sk, pk);
    }
}


pub fn scalarmult(mypublic: &mut [u8; 32], secret: &[u8; 32], basepoint: &[u8; 32]) {
    unsafe {
        ffi::curve25519::Hacl_Curve25519_crypto_scalarmult(
            mypublic.as_mut_ptr(),
            secret.as_ptr() as _,
            basepoint.as_ptr() as _
        );
    }
}