bytecode_interpreter_crypto/
lib.rs1use anyhow::{bail, Result};
16use ed25519_dalek::{
17 ed25519::signature::Signature, PublicKey as Ed25519PublicKey, Signature as Ed25519Signature,
18 PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
19};
20use sha2::{Digest, Sha256};
21use sha3::Sha3_256;
22use std::cmp::Ordering;
23
24const L: [u8; 32] = [
26 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
27 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
28];
29
30pub fn sha2_256_of(bytes: &[u8]) -> Vec<u8> {
32 Sha256::digest(bytes).to_vec()
33}
34
35pub fn sha3_256_of(bytes: &[u8]) -> Vec<u8> {
36 Sha3_256::digest(bytes).to_vec()
37}
38
39fn validate_public_key(bytes: &[u8]) -> bool {
41 if bytes.len() != ED25519_PUBLIC_KEY_LENGTH {
44 return false;
45 }
46
47 let mut bits = [0u8; ED25519_PUBLIC_KEY_LENGTH];
48 bits.copy_from_slice(&bytes[..ED25519_PUBLIC_KEY_LENGTH]);
49
50 let compressed = curve25519_dalek::edwards::CompressedEdwardsY(bits);
51 let point = match compressed.decompress() {
52 None => return false,
53 Some(point) => point,
54 };
55
56 !point.is_small_order()
59}
60
61pub fn ed25519_deserialize_public_key(bytes: &[u8]) -> Result<Ed25519PublicKey> {
62 if !validate_public_key(bytes) {
63 bail!("Invalid public key bytes");
64 }
65 Ok(Ed25519PublicKey::from_bytes(bytes)?)
66}
67
68fn validate_signature(bytes: &[u8]) -> bool {
69 if bytes.len() != ED25519_SIGNATURE_LENGTH {
70 return false;
71 }
72 for i in (0..32).rev() {
73 match bytes[32 + i].cmp(&L[i]) {
74 Ordering::Less => return true,
75 Ordering::Greater => return false,
76 _ => (),
77 }
78 }
79 false
81}
82
83pub fn ed25519_deserialize_signature(bytes: &[u8]) -> Result<Ed25519Signature> {
84 if !validate_signature(bytes) {
85 bail!("Invalid signature bytes");
86 }
87 Ok(Ed25519Signature::from_bytes(bytes)?)
88}
89
90pub fn ed25519_verify_signature(
91 key: &Ed25519PublicKey,
92 sig: &Ed25519Signature,
93 msg: &[u8],
94) -> Result<()> {
95 if !validate_public_key(&key.to_bytes()) {
96 bail!("Malleable public key");
97 }
98 if !validate_signature(&sig.to_bytes()) {
99 bail!("Malleable signature");
100 }
101 Ok(key.verify_strict(msg, sig)?)
102}