1use rns_crypto::identity::Identity;
2
3use crate::constants;
4
5#[derive(Debug, PartialEq, Eq)]
7pub enum ProofResult {
8 Valid,
9 InvalidHash,
10 InvalidSignature,
11 InvalidLength,
12}
13
14pub fn validate_proof(
22 proof: &[u8],
23 packet_hash: &[u8; 32],
24 identity: &Identity,
25) -> ProofResult {
26 if proof.len() == constants::EXPL_LENGTH {
27 let proof_hash = &proof[..constants::HASHLENGTH / 8];
29 if proof_hash != packet_hash.as_slice() {
30 return ProofResult::InvalidHash;
31 }
32
33 let signature: &[u8; 64] = proof[constants::HASHLENGTH / 8..constants::HASHLENGTH / 8 + constants::SIGLENGTH / 8]
34 .try_into()
35 .unwrap();
36
37 if identity.verify(signature, packet_hash) {
38 ProofResult::Valid
39 } else {
40 ProofResult::InvalidSignature
41 }
42 } else if proof.len() == constants::IMPL_LENGTH {
43 let signature: &[u8; 64] = proof[..constants::SIGLENGTH / 8]
45 .try_into()
46 .unwrap();
47
48 if identity.verify(signature, packet_hash) {
49 ProofResult::Valid
50 } else {
51 ProofResult::InvalidSignature
52 }
53 } else {
54 ProofResult::InvalidLength
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 fn make_test_identity() -> Identity {
63 Identity::from_private_key(&[0x42; 64])
64 }
65
66 #[test]
67 fn test_explicit_proof_valid() {
68 let identity = make_test_identity();
69 let packet_hash = crate::hash::full_hash(b"test packet data");
70
71 let signature = identity.sign(&packet_hash).unwrap();
72
73 let mut proof = Vec::new();
74 proof.extend_from_slice(&packet_hash);
75 proof.extend_from_slice(&signature);
76
77 assert_eq!(proof.len(), constants::EXPL_LENGTH);
78 assert_eq!(validate_proof(&proof, &packet_hash, &identity), ProofResult::Valid);
79 }
80
81 #[test]
82 fn test_explicit_proof_wrong_hash() {
83 let identity = make_test_identity();
84 let packet_hash = crate::hash::full_hash(b"test packet data");
85 let wrong_hash = crate::hash::full_hash(b"wrong data");
86
87 let signature = identity.sign(&packet_hash).unwrap();
88
89 let mut proof = Vec::new();
90 proof.extend_from_slice(&wrong_hash); proof.extend_from_slice(&signature);
92
93 assert_eq!(validate_proof(&proof, &packet_hash, &identity), ProofResult::InvalidHash);
94 }
95
96 #[test]
97 fn test_explicit_proof_bad_signature() {
98 let identity = make_test_identity();
99 let packet_hash = crate::hash::full_hash(b"test packet data");
100
101 let mut bad_sig = [0u8; 64];
102 bad_sig[0] = 0xFF;
103
104 let mut proof = Vec::new();
105 proof.extend_from_slice(&packet_hash);
106 proof.extend_from_slice(&bad_sig);
107
108 assert_eq!(validate_proof(&proof, &packet_hash, &identity), ProofResult::InvalidSignature);
109 }
110
111 #[test]
112 fn test_implicit_proof_valid() {
113 let identity = make_test_identity();
114 let packet_hash = crate::hash::full_hash(b"test packet data");
115
116 let signature = identity.sign(&packet_hash).unwrap();
117
118 assert_eq!(signature.len(), constants::IMPL_LENGTH);
119 assert_eq!(validate_proof(&signature, &packet_hash, &identity), ProofResult::Valid);
120 }
121
122 #[test]
123 fn test_implicit_proof_bad_signature() {
124 let identity = make_test_identity();
125 let packet_hash = crate::hash::full_hash(b"test packet data");
126
127 let bad_sig = [0u8; 64];
128 assert_eq!(validate_proof(&bad_sig, &packet_hash, &identity), ProofResult::InvalidSignature);
129 }
130
131 #[test]
132 fn test_wrong_length_proof() {
133 let identity = make_test_identity();
134 let packet_hash = crate::hash::full_hash(b"test packet data");
135
136 let proof = [0u8; 50]; assert_eq!(validate_proof(&proof, &packet_hash, &identity), ProofResult::InvalidLength);
138 }
139}