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