1use core::ops::{Deref, DerefMut};
2
3use super::common::*;
4use super::error::Error;
5use super::field25519::*;
6
7const POINT_BYTES: usize = 32;
8
9#[derive(Clone, Debug, Eq, PartialEq, Hash)]
13pub struct DHOutput([u8; DHOutput::BYTES]);
14
15impl DHOutput {
16 pub const BYTES: usize = 32;
17}
18
19impl Deref for DHOutput {
20 type Target = [u8; DHOutput::BYTES];
21
22 fn deref(&self) -> &Self::Target {
25 &self.0
26 }
27}
28
29impl DerefMut for DHOutput {
30 fn deref_mut(&mut self) -> &mut Self::Target {
33 &mut self.0
34 }
35}
36
37impl From<DHOutput> for PublicKey {
38 fn from(dh: DHOutput) -> Self {
39 PublicKey(dh.0)
40 }
41}
42
43impl From<DHOutput> for SecretKey {
44 fn from(dh: DHOutput) -> Self {
45 SecretKey(dh.0)
46 }
47}
48
49impl Drop for DHOutput {
50 fn drop(&mut self) {
51 Mem::wipe(self.0)
52 }
53}
54
55#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
57pub struct PublicKey([u8; POINT_BYTES]);
58
59impl PublicKey {
60 pub const BYTES: usize = POINT_BYTES;
62
63 pub fn new(pk: [u8; PublicKey::BYTES]) -> Self {
65 PublicKey(pk)
66 }
67
68 pub fn from_slice(pk: &[u8]) -> Result<Self, Error> {
70 let mut pk_ = [0u8; PublicKey::BYTES];
71 if pk.len() != pk_.len() {
72 return Err(Error::InvalidPublicKey);
73 }
74 Fe::reject_noncanonical(pk)?;
75 pk_.copy_from_slice(pk);
76 Ok(PublicKey::new(pk_))
77 }
78
79 pub fn clear_cofactor(&self) -> Result<[u8; PublicKey::BYTES], Error> {
82 let cofactor = [
83 8u8, 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,
84 0, 0, 0, 0,
85 ];
86 self.ladder(&cofactor, 4)
87 }
88
89 pub fn dh(&self, sk: &SecretKey) -> Result<DHOutput, Error> {
92 let sk = sk.clamped();
93 Ok(DHOutput(self.ladder(&sk.0, 255)?))
94 }
95
96 pub fn unclamped_mul(&self, sk: &SecretKey) -> Result<DHOutput, Error> {
99 self.clear_cofactor()?;
100 Ok(DHOutput(self.ladder(&sk.0, 256)?))
101 }
102
103 fn ladder(&self, s: &[u8], bits: usize) -> Result<[u8; POINT_BYTES], Error> {
104 let x1 = Fe::from_bytes(&self.0);
105 let mut x2 = FE_ONE;
106 let mut z2 = FE_ZERO;
107 let mut x3 = x1;
108 let mut z3 = FE_ONE;
109 let mut swap: u8 = 0;
110 let mut pos = bits - 1;
111 loop {
112 let bit = (s[pos >> 3] >> (pos & 7)) & 1;
113 swap ^= bit;
114 Fe::cswap2(&mut x2, &mut x3, &mut z2, &mut z3, swap);
115 swap = bit;
116 let a = x2 + z2;
117 let b = x2 - z2;
118 let aa = a.square();
119 let bb = b.square();
120 x2 = aa * bb;
121 let e = aa - bb;
122 let da = (x3 - z3) * a;
123 let cb = (x3 + z3) * b;
124 x3 = (da + cb).square();
125 z3 = x1 * ((da - cb).square());
126 z2 = e * (bb + (e.mul32(121666)));
127 if pos == 0 {
128 break;
129 }
130 pos -= 1;
131 }
132 Fe::cswap2(&mut x2, &mut x3, &mut z2, &mut z3, swap);
133 z2 = z2.invert();
134 x2 = x2 * z2;
135 if x2.is_zero() {
136 return Err(Error::WeakPublicKey);
137 }
138 Ok(x2.to_bytes())
139 }
140
141 #[inline]
143 pub fn base_point() -> PublicKey {
144 PublicKey(FE_CURVE25519_BASEPOINT.to_bytes())
145 }
146}
147
148impl Deref for PublicKey {
149 type Target = [u8; PublicKey::BYTES];
150
151 fn deref(&self) -> &Self::Target {
153 &self.0
154 }
155}
156
157impl DerefMut for PublicKey {
158 fn deref_mut(&mut self) -> &mut Self::Target {
160 &mut self.0
161 }
162}
163
164#[derive(Clone, Debug, Eq, PartialEq, Hash)]
166pub struct SecretKey([u8; SecretKey::BYTES]);
167
168impl SecretKey {
169 pub const BYTES: usize = 32;
171
172 pub fn new(sk: [u8; SecretKey::BYTES]) -> Self {
174 SecretKey(sk)
175 }
176
177 pub fn from_slice(sk: &[u8]) -> Result<Self, Error> {
179 let mut sk_ = [0u8; SecretKey::BYTES];
180 if sk.len() != sk_.len() {
181 return Err(Error::InvalidSecretKey);
182 }
183 sk_.copy_from_slice(sk);
184 Ok(SecretKey::new(sk_))
185 }
186
187 pub fn clamped(&self) -> SecretKey {
189 let mut clamped = self.clone();
190 clamped[0] &= 248;
191 clamped[31] &= 63;
192 clamped[31] |= 64;
193 clamped
194 }
195
196 pub fn recover_public_key(&self) -> Result<PublicKey, Error> {
198 let sk = self.clamped();
199 Ok(PublicKey(PublicKey::base_point().ladder(&sk.0, 255)?))
200 }
201
202 pub fn validate_public_key(&self, pk: &PublicKey) -> Result<(), Error> {
206 let recovered_pk = self.recover_public_key()?;
207 if recovered_pk != *pk {
208 return Err(Error::InvalidPublicKey);
209 }
210 Ok(())
211 }
212}
213
214impl Drop for SecretKey {
215 fn drop(&mut self) {
216 Mem::wipe(self.0)
217 }
218}
219
220impl Deref for SecretKey {
221 type Target = [u8; SecretKey::BYTES];
222
223 fn deref(&self) -> &Self::Target {
225 &self.0
226 }
227}
228
229impl DerefMut for SecretKey {
230 fn deref_mut(&mut self) -> &mut Self::Target {
232 &mut self.0
233 }
234}
235
236#[derive(Clone, Debug, Eq, PartialEq, Hash)]
238pub struct KeyPair {
239 pub pk: PublicKey,
241 pub sk: SecretKey,
243}
244
245impl KeyPair {
246 #[cfg(feature = "random")]
248 pub fn generate() -> KeyPair {
249 let mut sk = [0u8; SecretKey::BYTES];
250 getrandom::getrandom(&mut sk).expect("getrandom");
251 if Fe::from_bytes(&sk).is_zero() {
252 panic!("All-zero secret key");
253 }
254 let sk = SecretKey(sk);
255 let pk = sk
256 .recover_public_key()
257 .expect("generated public key is weak");
258 KeyPair { pk, sk }
259 }
260
261 pub fn validate(&self) -> Result<(), Error> {
263 self.sk.validate_public_key(&self.pk)
264 }
265}
266
267#[cfg(not(feature = "disable-signatures"))]
268mod from_ed25519 {
269 use super::super::{
270 edwards25519, sha512, KeyPair as EdKeyPair, PublicKey as EdPublicKey,
271 SecretKey as EdSecretKey,
272 };
273 use super::*;
274
275 impl SecretKey {
276 pub fn from_ed25519(edsk: &EdSecretKey) -> Result<SecretKey, Error> {
278 let seed = edsk.seed();
279 let az: [u8; 64] = {
280 let mut hash_output = sha512::Hash::hash(*seed);
281 hash_output[0] &= 248;
282 hash_output[31] &= 63;
283 hash_output[31] |= 64;
284 hash_output
285 };
286 SecretKey::from_slice(&az[..32])
287 }
288 }
289
290 impl PublicKey {
291 pub fn from_ed25519(edpk: &EdPublicKey) -> Result<PublicKey, Error> {
293 let pk = PublicKey::from_slice(
294 &edwards25519::ge_to_x25519_vartime(edpk).ok_or(Error::InvalidPublicKey)?,
295 )?;
296 pk.clear_cofactor()?;
297 Ok(pk)
298 }
299 }
300
301 impl KeyPair {
302 pub fn from_ed25519(edkp: &EdKeyPair) -> Result<KeyPair, Error> {
304 let pk = PublicKey::from_ed25519(&edkp.pk)?;
305 let sk = SecretKey::from_ed25519(&edkp.sk)?;
306 Ok(KeyPair { pk, sk })
307 }
308 }
309}
310
311#[cfg(not(feature = "disable-signatures"))]
312pub use from_ed25519::*;
313
314#[test]
315fn test_x25519() {
316 let sk_1 = SecretKey::from_slice(&[
317 1u8, 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,
318 0, 0,
319 ])
320 .unwrap();
321 let output = PublicKey::base_point().unclamped_mul(&sk_1).unwrap();
322 assert_eq!(PublicKey::from(output), PublicKey::base_point());
323 let kp_a = KeyPair::generate();
324 let kp_b = KeyPair::generate();
325 let output_a = kp_b.pk.dh(&kp_a.sk).unwrap();
326 let output_b = kp_a.pk.dh(&kp_b.sk).unwrap();
327 assert_eq!(output_a, output_b);
328}
329
330#[cfg(not(feature = "disable-signatures"))]
331#[test]
332fn test_x25519_map() {
333 use super::KeyPair as EdKeyPair;
334 let edkp_a = EdKeyPair::generate();
335 let edkp_b = EdKeyPair::generate();
336 let kp_a = KeyPair::from_ed25519(&edkp_a).unwrap();
337 let kp_b = KeyPair::from_ed25519(&edkp_b).unwrap();
338 let output_a = kp_b.pk.dh(&kp_a.sk).unwrap();
339 let output_b = kp_a.pk.dh(&kp_b.sk).unwrap();
340 assert_eq!(output_a, output_b);
341}
342
343#[test]
344#[cfg(all(not(feature = "disable-signatures"), feature = "random"))]
345fn test_x25519_invalid_keypair() {
346 let kp1 = KeyPair::generate();
347 let kp2 = KeyPair::generate();
348
349 assert_eq!(
350 kp1.sk.validate_public_key(&kp2.pk).unwrap_err(),
351 Error::InvalidPublicKey
352 );
353 assert_eq!(
354 kp2.sk.validate_public_key(&kp1.pk).unwrap_err(),
355 Error::InvalidPublicKey
356 );
357 assert!(kp1.sk.validate_public_key(&kp1.pk).is_ok());
358 assert!(kp2.sk.validate_public_key(&kp2.pk).is_ok());
359 assert!(kp1.validate().is_ok());
360}