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
use anyhow::{bail, Result};
#[allow(unused_imports)]
use ed25519_dalek::{
ed25519::signature::Signature, PublicKey as Ed25519PublicKey, Signature as Ed25519Signature,
PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
};
use sha2::{Digest, Sha256};
use sha3::Sha3_256;
use std::cmp::Ordering;
const L: [u8; 32] = [
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
];
pub fn sha2_256_of(bytes: &[u8]) -> Vec<u8> {
Sha256::digest(bytes).to_vec()
}
pub fn sha3_256_of(bytes: &[u8]) -> Vec<u8> {
Sha3_256::digest(bytes).to_vec()
}
fn validate_public_key(bytes: &[u8]) -> bool {
if bytes.len() != ED25519_PUBLIC_KEY_LENGTH {
return false;
}
let mut bits = [0u8; ED25519_PUBLIC_KEY_LENGTH];
bits.copy_from_slice(&bytes[..ED25519_PUBLIC_KEY_LENGTH]);
let compressed = curve25519_dalek::edwards::CompressedEdwardsY(bits);
let point = match compressed.decompress() {
None => return false,
Some(point) => point,
};
!point.is_small_order()
}
pub fn ed25519_deserialize_public_key(bytes: &[u8]) -> Result<Ed25519PublicKey> {
if !validate_public_key(bytes) {
bail!("Invalid public key bytes");
}
Ok(Ed25519PublicKey::from_bytes(bytes)?)
}
fn validate_signature(bytes: &[u8]) -> bool {
if bytes.len() != ED25519_SIGNATURE_LENGTH {
return false;
}
for i in (0..32).rev() {
match bytes[32 + i].cmp(&L[i]) {
Ordering::Less => return true,
Ordering::Greater => return false,
_ => (),
}
}
false
}
pub fn ed25519_deserialize_signature(bytes: &[u8]) -> Result<Ed25519Signature> {
if !validate_signature(bytes) {
bail!("Invalid signature bytes");
}
Ok(Ed25519Signature::from_bytes(bytes)?)
}
pub fn ed25519_verify_signature(
key: &Ed25519PublicKey,
sig: &Ed25519Signature,
msg: &[u8],
) -> Result<()> {
if !validate_public_key(&key.to_bytes()) {
bail!("Malleable public key");
}
if !validate_signature(&sig.to_bytes()) {
bail!("Malleable signature");
}
Ok(key.verify_strict(msg, sig)?)
}