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
use libsodium_sys::{crypto_sign_ed25519_pk_to_curve25519, crypto_sign_ed25519_sk_to_curve25519};
pub use scalarmult::GroupElement as SharedSecret;
use sodiumoxide::crypto::scalarmult::{self, scalarmult, Scalar};
use crate::*;
pub use box_::{PublicKey as EphPublicKey, SecretKey as EphSecretKey};
use sodiumoxide::crypto::box_;
pub struct HandshakeKeys {
pub read_key: secretbox::Key,
pub read_noncegen: NonceGen,
pub write_key: secretbox::Key,
pub write_noncegen: NonceGen,
}
pub fn generate_ephemeral_keypair() -> (EphPublicKey, EphSecretKey) {
box_::gen_keypair()
}
pub fn derive_shared_secret(
our_sec: &EphSecretKey,
their_pub: &EphPublicKey,
) -> Option<SharedSecret> {
let n = Scalar::from_slice(&our_sec[..])?;
let p = SharedSecret::from_slice(&their_pub[..])?;
scalarmult(&n, &p).ok()
}
pub fn derive_shared_secret_pk(sk: &EphSecretKey, pk: &PublicKey) -> Option<SharedSecret> {
pk_to_curve(&pk).and_then(|c| derive_shared_secret(&sk, &c))
}
pub fn derive_shared_secret_sk(sk: &SecretKey, pk: &EphPublicKey) -> Option<SharedSecret> {
sk_to_curve(&sk).and_then(|c| derive_shared_secret(&c, &pk))
}
fn pk_to_curve(k: &PublicKey) -> Option<EphPublicKey> {
let mut buf = [0; size_of::<EphPublicKey>()];
let ok = unsafe { crypto_sign_ed25519_pk_to_curve25519(buf.as_mut_ptr(), k.0.as_ptr()) == 0 };
if ok {
EphPublicKey::from_slice(&buf)
} else {
None
}
}
fn sk_to_curve(k: &SecretKey) -> Option<EphSecretKey> {
let mut buf = [0; size_of::<EphSecretKey>()];
let ok = unsafe { crypto_sign_ed25519_sk_to_curve25519(buf.as_mut_ptr(), k.0.as_ptr()) == 0 };
if ok {
EphSecretKey::from_slice(&buf)
} else {
None
}
}