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(&mut 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 #[cfg_attr(feature = "opt_size", inline(never))]
104 #[cfg_attr(not(feature = "opt_size"), inline(always))]
105 fn ladder(&self, s: &[u8], bits: usize) -> Result<[u8; POINT_BYTES], Error> {
106 let x1 = Fe::from_bytes(&self.0);
107 let mut x2 = FE_ONE;
108 let mut z2 = FE_ZERO;
109 let mut x3 = x1;
110 let mut z3 = FE_ONE;
111 let mut swap: u8 = 0;
112 let mut pos = bits - 1;
113 loop {
114 let bit = (s[pos >> 3] >> (pos & 7)) & 1;
115 swap ^= bit;
116 Fe::cswap2(&mut x2, &mut x3, &mut z2, &mut z3, swap);
117 swap = bit;
118 let a = x2 + z2;
119 let b = x2 - z2;
120 let aa = a.square();
121 let bb = b.square();
122 x2 = aa * bb;
123 let e = aa - bb;
124 let da = (x3 - z3) * a;
125 let cb = (x3 + z3) * b;
126 x3 = (da + cb).square();
127 z3 = x1 * ((da - cb).square());
128 z2 = e * (bb + (e.mul32(121666)));
129 if pos == 0 {
130 break;
131 }
132 pos -= 1;
133 }
134 Fe::cswap2(&mut x2, &mut x3, &mut z2, &mut z3, swap);
135 z2 = z2.invert();
136 x2 = x2 * z2;
137 if x2.is_zero() {
138 return Err(Error::WeakPublicKey);
139 }
140 Ok(x2.to_bytes())
141 }
142
143 #[inline]
145 pub fn base_point() -> PublicKey {
146 let mut pk = [0u8; POINT_BYTES];
147 pk[0] = 9;
148 PublicKey(pk)
149 }
150}
151
152impl Deref for PublicKey {
153 type Target = [u8; PublicKey::BYTES];
154
155 fn deref(&self) -> &Self::Target {
157 &self.0
158 }
159}
160
161impl DerefMut for PublicKey {
162 fn deref_mut(&mut self) -> &mut Self::Target {
164 &mut self.0
165 }
166}
167
168#[derive(Clone, Debug, Eq, PartialEq, Hash)]
170pub struct SecretKey([u8; SecretKey::BYTES]);
171
172impl SecretKey {
173 pub const BYTES: usize = 32;
175
176 pub fn new(sk: [u8; SecretKey::BYTES]) -> Self {
178 SecretKey(sk)
179 }
180
181 pub fn from_slice(sk: &[u8]) -> Result<Self, Error> {
183 let mut sk_ = [0u8; SecretKey::BYTES];
184 if sk.len() != sk_.len() {
185 return Err(Error::InvalidSecretKey);
186 }
187 sk_.copy_from_slice(sk);
188 Ok(SecretKey::new(sk_))
189 }
190
191 pub fn clamped(&self) -> SecretKey {
193 let mut clamped = self.clone();
194 clamped[0] &= 248;
195 clamped[31] &= 63;
196 clamped[31] |= 64;
197 clamped
198 }
199
200 pub fn recover_public_key(&self) -> Result<PublicKey, Error> {
202 let sk = self.clamped();
203 Ok(PublicKey(PublicKey::base_point().ladder(&sk.0, 255)?))
204 }
205
206 pub fn validate_public_key(&self, pk: &PublicKey) -> Result<(), Error> {
210 let recovered_pk = self.recover_public_key()?;
211 if recovered_pk != *pk {
212 return Err(Error::InvalidPublicKey);
213 }
214 Ok(())
215 }
216}
217
218impl Drop for SecretKey {
219 fn drop(&mut self) {
220 Mem::wipe(&mut self.0)
221 }
222}
223
224impl Deref for SecretKey {
225 type Target = [u8; SecretKey::BYTES];
226
227 fn deref(&self) -> &Self::Target {
229 &self.0
230 }
231}
232
233impl DerefMut for SecretKey {
234 fn deref_mut(&mut self) -> &mut Self::Target {
236 &mut self.0
237 }
238}
239
240#[derive(Clone, Debug, Eq, PartialEq, Hash)]
242pub struct KeyPair {
243 pub pk: PublicKey,
245 pub sk: SecretKey,
247}
248
249impl KeyPair {
250 #[cfg(feature = "random")]
252 pub fn generate() -> KeyPair {
253 let mut sk = [0u8; SecretKey::BYTES];
254 getrandom::fill(&mut sk).expect("getrandom");
255 if Fe::from_bytes(&sk).is_zero() {
256 panic!("All-zero secret key");
257 }
258 let sk = SecretKey(sk);
259 let pk = sk
260 .recover_public_key()
261 .expect("generated public key is weak");
262 KeyPair { pk, sk }
263 }
264
265 pub fn validate(&self) -> Result<(), Error> {
267 self.sk.validate_public_key(&self.pk)
268 }
269}
270
271#[cfg(not(feature = "disable-signatures"))]
272mod from_ed25519 {
273 use super::super::{
274 edwards25519, sha512, KeyPair as EdKeyPair, PublicKey as EdPublicKey,
275 SecretKey as EdSecretKey,
276 };
277 use super::*;
278
279 impl SecretKey {
280 pub fn from_ed25519(edsk: &EdSecretKey) -> Result<SecretKey, Error> {
282 let seed = edsk.seed();
283 let az: [u8; 64] = {
284 let mut hash_output = sha512::Hash::hash(*seed);
285 hash_output[0] &= 248;
286 hash_output[31] &= 63;
287 hash_output[31] |= 64;
288 hash_output
289 };
290 SecretKey::from_slice(&az[..32])
291 }
292 }
293
294 impl PublicKey {
295 pub fn from_ed25519(edpk: &EdPublicKey) -> Result<PublicKey, Error> {
297 let pk = PublicKey::from_slice(
298 &edwards25519::ge_to_x25519_vartime(edpk).ok_or(Error::InvalidPublicKey)?,
299 )?;
300 pk.clear_cofactor()?;
301 Ok(pk)
302 }
303 }
304
305 impl KeyPair {
306 pub fn from_ed25519(edkp: &EdKeyPair) -> Result<KeyPair, Error> {
308 let pk = PublicKey::from_ed25519(&edkp.pk)?;
309 let sk = SecretKey::from_ed25519(&edkp.sk)?;
310 Ok(KeyPair { pk, sk })
311 }
312 }
313}
314
315#[cfg(not(feature = "disable-signatures"))]
316#[allow(unused)]
317pub use from_ed25519::*;
318
319#[test]
320fn test_x25519() {
321 let sk_1 = SecretKey::from_slice(&[
322 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,
323 0, 0,
324 ])
325 .unwrap();
326 let output = PublicKey::base_point().unclamped_mul(&sk_1).unwrap();
327 assert_eq!(PublicKey::from(output), PublicKey::base_point());
328 let kp_a = KeyPair::generate();
329 let kp_b = KeyPair::generate();
330 let output_a = kp_b.pk.dh(&kp_a.sk).unwrap();
331 let output_b = kp_a.pk.dh(&kp_b.sk).unwrap();
332 assert_eq!(output_a, output_b);
333}
334
335#[test]
336fn test_x25519_rfc7748() {
337 use core::convert::TryInto;
338 use ct_codecs::{Decoder, Hex};
339
340 fn decode32(hex: &str) -> [u8; 32] {
341 Hex::decode_to_vec(hex, None).unwrap().try_into().unwrap()
342 }
343
344 let alice_sk = SecretKey::new(decode32(
345 "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
346 ));
347 let alice_pk = alice_sk.recover_public_key().unwrap();
348 assert_eq!(
349 &alice_pk[..],
350 &decode32("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a")
351 );
352
353 let bob_sk = SecretKey::new(decode32(
354 "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
355 ));
356 let bob_pk = PublicKey::from_slice(&decode32(
357 "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
358 ))
359 .unwrap();
360 assert_eq!(bob_sk.recover_public_key().unwrap(), bob_pk);
361
362 let shared_a = bob_pk.dh(&alice_sk).unwrap();
363 let shared_b = alice_pk.dh(&bob_sk).unwrap();
364 let expected = decode32("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
365 assert_eq!(&shared_a[..], &expected);
366 assert_eq!(shared_a, shared_b);
367}
368
369#[cfg(not(feature = "disable-signatures"))]
370#[test]
371fn test_x25519_map() {
372 use super::KeyPair as EdKeyPair;
373 let edkp_a = EdKeyPair::generate();
374 let edkp_b = EdKeyPair::generate();
375 let kp_a = KeyPair::from_ed25519(&edkp_a).unwrap();
376 let kp_b = KeyPair::from_ed25519(&edkp_b).unwrap();
377 let output_a = kp_b.pk.dh(&kp_a.sk).unwrap();
378 let output_b = kp_a.pk.dh(&kp_b.sk).unwrap();
379 assert_eq!(output_a, output_b);
380}
381
382#[test]
383#[cfg(all(not(feature = "disable-signatures"), feature = "random"))]
384fn test_x25519_invalid_keypair() {
385 let kp1 = KeyPair::generate();
386 let kp2 = KeyPair::generate();
387
388 assert_eq!(
389 kp1.sk.validate_public_key(&kp2.pk).unwrap_err(),
390 Error::InvalidPublicKey
391 );
392 assert_eq!(
393 kp2.sk.validate_public_key(&kp1.pk).unwrap_err(),
394 Error::InvalidPublicKey
395 );
396 assert!(kp1.sk.validate_public_key(&kp1.pk).is_ok());
397 assert!(kp2.sk.validate_public_key(&kp2.pk).is_ok());
398 assert!(kp1.validate().is_ok());
399}