rns_core/link/
identify.rs1use alloc::vec::Vec;
2
3use rns_crypto::identity::Identity;
4use rns_crypto::ed25519::Ed25519PublicKey;
5
6use crate::constants::{KEYSIZE, SIGLENGTH};
7use super::types::{LinkError, LinkId};
8
9pub fn build_identify_data(identity: &Identity, link_id: &LinkId) -> Result<Vec<u8>, LinkError> {
13 let public_key = identity.get_public_key()
14 .ok_or(LinkError::CryptoError)?;
15
16 let mut signed_data = Vec::with_capacity(16 + 64);
17 signed_data.extend_from_slice(link_id);
18 signed_data.extend_from_slice(&public_key);
19
20 let signature = identity.sign(&signed_data)
21 .map_err(|_| LinkError::CryptoError)?;
22
23 let mut data = Vec::with_capacity(128);
24 data.extend_from_slice(&public_key);
25 data.extend_from_slice(&signature);
26
27 Ok(data)
28}
29
30pub fn validate_identify_data(
34 plaintext: &[u8],
35 link_id: &LinkId,
36) -> Result<([u8; 16], [u8; 64]), LinkError> {
37 let expected_len = KEYSIZE / 8 + SIGLENGTH / 8; if plaintext.len() != expected_len {
39 return Err(LinkError::InvalidData);
40 }
41
42 let mut public_key = [0u8; 64];
43 public_key.copy_from_slice(&plaintext[..64]);
44
45 let mut signature = [0u8; 64];
46 signature.copy_from_slice(&plaintext[64..128]);
47
48 let mut signed_data = Vec::with_capacity(16 + 64);
49 signed_data.extend_from_slice(link_id);
50 signed_data.extend_from_slice(&public_key);
51
52 let sig_pub = Ed25519PublicKey::from_bytes(&{
54 let mut b = [0u8; 32];
55 b.copy_from_slice(&public_key[32..64]);
56 b
57 });
58
59 if sig_pub.verify(&signature, &signed_data) {
60 let identity = Identity::from_public_key(&public_key);
62 let identity_hash = *identity.hash();
63 Ok((identity_hash, public_key))
64 } else {
65 Err(LinkError::InvalidSignature)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use rns_crypto::FixedRng;
73
74 #[test]
75 fn test_identify_roundtrip() {
76 let mut rng = FixedRng::new(&[0x42; 128]);
77 let identity = Identity::new(&mut rng);
78 let link_id: LinkId = [0xAA; 16];
79
80 let data = build_identify_data(&identity, &link_id).unwrap();
81 assert_eq!(data.len(), 128);
82
83 let (hash, pubkey) = validate_identify_data(&data, &link_id).unwrap();
84 assert_eq!(hash, *identity.hash());
85 assert_eq!(pubkey, identity.get_public_key().unwrap());
86 }
87
88 #[test]
89 fn test_identify_wrong_link_id() {
90 let mut rng = FixedRng::new(&[0x42; 128]);
91 let identity = Identity::new(&mut rng);
92 let link_id: LinkId = [0xAA; 16];
93 let wrong_id: LinkId = [0xBB; 16];
94
95 let data = build_identify_data(&identity, &link_id).unwrap();
96 assert_eq!(validate_identify_data(&data, &wrong_id), Err(LinkError::InvalidSignature));
97 }
98
99 #[test]
100 fn test_identify_tampered() {
101 let mut rng = FixedRng::new(&[0x42; 128]);
102 let identity = Identity::new(&mut rng);
103 let link_id: LinkId = [0xAA; 16];
104
105 let mut data = build_identify_data(&identity, &link_id).unwrap();
106 data[10] ^= 0xFF; assert_eq!(validate_identify_data(&data, &link_id), Err(LinkError::InvalidSignature));
108 }
109
110 #[test]
111 fn test_identify_invalid_length() {
112 let link_id: LinkId = [0xAA; 16];
113 assert_eq!(validate_identify_data(&[0u8; 64], &link_id), Err(LinkError::InvalidData));
114 }
115
116 #[test]
117 fn test_identify_public_only_fails() {
118 let mut rng = FixedRng::new(&[0x42; 128]);
119 let identity = Identity::new(&mut rng);
120 let pubkey = identity.get_public_key().unwrap();
121 let public_only = Identity::from_public_key(&pubkey);
122 let link_id: LinkId = [0xAA; 16];
123
124 assert!(build_identify_data(&public_only, &link_id).is_err());
126 }
127}