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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use curve25519_dalek::{
constants::ED25519_BASEPOINT_TABLE, montgomery::MontgomeryPoint, scalar::Scalar,
};
use rand::{rngs::OsRng, CryptoRng, RngCore};
pub const PRIVATE_KEY_SIZE: usize = 32;
pub const PUBLIC_KEY_SIZE: usize = 32;
pub const SHARED_SECRET_SIZE: usize = PUBLIC_KEY_SIZE;
pub fn clamp_scalar_bytes(mut scalar_bytes: [u8; PRIVATE_KEY_SIZE]) -> Scalar {
scalar_bytes[0] &= 248;
scalar_bytes[31] &= 127;
scalar_bytes[31] |= 64;
Scalar::from_bits(scalar_bytes)
}
pub struct PrivateKey(Scalar);
#[allow(renamed_and_removed_lints)] #[allow(clippy::derive_hash_xor_eq)] #[derive(Copy, Clone, Debug, Hash)]
pub struct PublicKey(MontgomeryPoint);
pub type EphemeralSecret = PrivateKey;
pub type SharedSecret = PublicKey;
impl PrivateKey {
pub fn diffie_hellman(&self, remote_public_key: &PublicKey) -> SharedSecret {
PublicKey(self.0 * remote_public_key.0)
}
pub(crate) fn clone(&self) -> Self {
PrivateKey(self.0)
}
pub fn new() -> Self {
let mut rng = OsRng;
Self::new_with_rng(&mut rng)
}
pub fn new_with_rng<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let mut bytes = [0u8; PRIVATE_KEY_SIZE];
rng.fill_bytes(&mut bytes);
PrivateKey(clamp_scalar_bytes(bytes))
}
pub fn to_bytes(&self) -> [u8; PRIVATE_KEY_SIZE] {
self.0.to_bytes()
}
}
impl Default for PrivateKey {
fn default() -> Self {
PrivateKey::new()
}
}
impl<'a, 'b> std::ops::Mul<&'b Scalar> for &'a EphemeralSecret {
type Output = EphemeralSecret;
fn mul(self, rhs: &'b Scalar) -> EphemeralSecret {
PrivateKey(self.0 * rhs)
}
}
impl<'b> std::ops::MulAssign<&'b Scalar> for EphemeralSecret {
fn mul_assign(&mut self, _rhs: &'b Scalar) {
self.0.mul_assign(_rhs)
}
}
impl From<Scalar> for EphemeralSecret {
fn from(scalar: Scalar) -> EphemeralSecret {
PrivateKey(scalar)
}
}
impl From<[u8; PRIVATE_KEY_SIZE]> for PrivateKey {
fn from(bytes: [u8; 32]) -> PrivateKey {
PrivateKey(clamp_scalar_bytes(bytes))
}
}
impl PublicKey {
pub fn as_bytes(&self) -> &[u8; PUBLIC_KEY_SIZE] {
self.0.as_bytes()
}
}
impl<'a> From<&'a PrivateKey> for PublicKey {
fn from(private_key: &'a PrivateKey) -> PublicKey {
PublicKey((&ED25519_BASEPOINT_TABLE * &private_key.0).to_montgomery())
}
}
impl From<[u8; PUBLIC_KEY_SIZE]> for PublicKey {
fn from(bytes: [u8; PUBLIC_KEY_SIZE]) -> PublicKey {
PublicKey(MontgomeryPoint(bytes))
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl Eq for PublicKey {}
pub fn keygen() -> (PrivateKey, PublicKey) {
let private_key = PrivateKey::new();
let public_key = PublicKey::from(&private_key);
(private_key, public_key)
}