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