minisign/crypto/
ed25519.rs1use super::curve25519::{ge_scalarmult_base, is_identity, sc_muladd, sc_reduce, GeP2, GeP3};
2use super::sha512;
3
4static L: [u8; 32] = [
5 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde,
6 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7 0x00, 0x10,
8];
9
10fn check_s_lt_l(s: &[u8]) -> bool {
11 let mut c: u8 = 0;
12 let mut n: u8 = 1;
13 let mut i: usize = 32;
14
15 loop {
16 i -= 1;
17 c |= ((((s[i] as i32) - (L[i] as i32)) >> 8) as u8) & n;
18 n &= ((((s[i] ^ L[i]) as i32) - 1) >> 8) as u8;
19 if i == 0 {
20 break;
21 }
22 }
23
24 c != 0
25}
26
27pub fn verify(message: &[u8], public_key: &[u8], signature: &[u8]) -> bool {
28 if !check_s_lt_l(&signature[32..64]) || is_identity(public_key) {
29 return false;
30 }
31 let a = match GeP3::from_bytes_negate_vartime(public_key) {
32 Some(g) => g,
33 None => {
34 return false;
35 }
36 };
37 if public_key.iter().fold(0, |acc, x| acc | x) == 0 {
38 return false;
39 }
40
41 let mut hasher = sha512::Hash::new();
42 hasher.update(&signature[0..32]);
43 hasher.update(public_key);
44 hasher.update(message);
45 let mut hash = hasher.finalize();
46 sc_reduce(&mut hash);
47
48 let r = GeP2::double_scalarmult_vartime(hash.as_ref(), a, &signature[32..64]);
49 r.to_bytes()
50 .as_ref()
51 .iter()
52 .zip(signature.iter())
53 .fold(0, |acc, (x, y)| acc | (x ^ y))
54 == 0
55}
56
57pub fn keypair(seed: &[u8]) -> ([u8; 64], [u8; 32]) {
58 let mut secret: [u8; 64] = {
59 let mut hash_output = sha512::Hash::hash(seed);
60 hash_output[0] &= 248;
61 hash_output[31] &= 63;
62 hash_output[31] |= 64;
63 hash_output
64 };
65 let a = ge_scalarmult_base(&secret[0..32]);
66 let public_key = a.to_bytes();
67 for (dest, src) in secret[32..64].iter_mut().zip(public_key.iter()) {
68 *dest = *src;
69 }
70 for (dest, src) in secret[0..32].iter_mut().zip(seed.iter()) {
71 *dest = *src;
72 }
73 (secret, public_key)
74}
75
76pub fn signature(message: &[u8], secret_key: &[u8], z: Option<&[u8]>) -> [u8; 64] {
77 let seed = &secret_key[0..32];
78 let public_key = &secret_key[32..64];
79 let az: [u8; 64] = {
80 let mut hash_output = sha512::Hash::hash(seed);
81 hash_output[0] &= 248;
82 hash_output[31] &= 63;
83 hash_output[31] |= 64;
84 hash_output
85 };
86 let nonce = {
87 let mut hasher = sha512::Hash::new();
88 if let Some(z) = z {
89 hasher.update(z);
90 hasher.update(&az[..]);
91 } else {
92 hasher.update(&az[32..64]);
93 }
94 hasher.update(message);
95 let mut hash_output = hasher.finalize();
96 sc_reduce(&mut hash_output[0..64]);
97 hash_output
98 };
99 let mut signature: [u8; 64] = [0; 64];
100 let r: GeP3 = ge_scalarmult_base(&nonce[0..32]);
101 for (result_byte, source_byte) in signature[0..32].iter_mut().zip(r.to_bytes().iter()) {
102 *result_byte = *source_byte;
103 }
104 for (result_byte, source_byte) in signature[32..64].iter_mut().zip(public_key.iter()) {
105 *result_byte = *source_byte;
106 }
107 {
108 let mut hasher = sha512::Hash::new();
109 hasher.update(signature.as_ref());
110 hasher.update(message);
111 let mut hram = hasher.finalize();
112 sc_reduce(&mut hram);
113 sc_muladd(
114 &mut signature[32..64],
115 &hram[0..32],
116 &az[0..32],
117 &nonce[0..32],
118 );
119 }
120 signature
121}