1use crate::{
2 database::redb::rkyv_adapter::said_wrapper::SaidValue,
3 event::sections::key_config::SignatureError,
4};
5
6use self::error::Error;
7use cesrox::primitives::codes::PrimitiveCode;
8pub use cesrox::primitives::CesrPrimitive;
9use core::str::FromStr;
10use said::SelfAddressingIdentifier;
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12use std::fmt::Display;
13
14pub mod attached_signature;
15pub mod basic;
16pub mod cesr_adapter;
17pub mod error;
18pub mod seed;
19pub mod self_signing;
20
21pub use attached_signature::IndexedSignature;
22pub use basic::BasicPrefix;
23pub use seed::SeedPrefix;
24pub use self_signing::SelfSigningPrefix;
25
26#[derive(Debug, PartialEq, Clone, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
27#[rkyv(derive(Debug))]
28pub enum IdentifierPrefix {
29 Basic(BasicPrefix),
30 SelfAddressing(SaidValue),
31 SelfSigning(SelfSigningPrefix),
32}
33
34impl IdentifierPrefix {
35 pub fn self_addressing(said: SelfAddressingIdentifier) -> Self {
36 IdentifierPrefix::SelfAddressing(said.into())
37 }
38
39 pub fn basic(bp: BasicPrefix) -> Self {
40 IdentifierPrefix::Basic(bp)
41 }
42
43 pub fn self_signing(self_signing: SelfSigningPrefix) -> Self {
44 IdentifierPrefix::SelfSigning(self_signing)
45 }
46}
47
48impl Display for IdentifierPrefix {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 write!(f, "{}", self.to_str())
51 }
52}
53
54impl FromStr for IdentifierPrefix {
55 type Err = Error;
56 fn from_str(s: &str) -> Result<Self, Self::Err> {
57 match BasicPrefix::from_str(s) {
58 Ok(bp) => Ok(Self::Basic(bp)),
59 Err(_) => match SelfAddressingIdentifier::from_str(s) {
60 Ok(sa) => Ok(Self::SelfAddressing(sa.into())),
61 Err(_) => Ok(Self::SelfSigning(SelfSigningPrefix::from_str(s)?)),
62 },
63 }
64 }
65}
66
67impl CesrPrimitive for IdentifierPrefix {
68 fn derivative(&self) -> Vec<u8> {
69 match self {
70 Self::Basic(bp) => bp.derivative(),
71 Self::SelfAddressing(sap) => sap.said.derivative(),
72 Self::SelfSigning(ssp) => ssp.derivative(),
73 }
74 }
75 fn derivation_code(&self) -> PrimitiveCode {
76 match self {
77 Self::Basic(bp) => bp.derivation_code(),
78 Self::SelfAddressing(sap) => sap.said.derivation_code(),
79 Self::SelfSigning(ssp) => ssp.derivation_code(),
80 }
81 }
82}
83
84impl Serialize for IdentifierPrefix {
86 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87 where
88 S: Serializer,
89 {
90 serializer.serialize_str(&self.to_str())
91 }
92}
93
94impl<'de> Deserialize<'de> for IdentifierPrefix {
96 fn deserialize<D>(deserializer: D) -> Result<IdentifierPrefix, D::Error>
97 where
98 D: Deserializer<'de>,
99 {
100 let s = String::deserialize(deserializer)?;
101
102 IdentifierPrefix::from_str(&s).map_err(serde::de::Error::custom)
103 }
104}
105
106impl Default for IdentifierPrefix {
107 fn default() -> Self {
108 IdentifierPrefix::SelfAddressing(SelfAddressingIdentifier::default().into())
109 }
110}
111
112pub fn verify(
117 data: &[u8],
118 key: &BasicPrefix,
119 signature: &SelfSigningPrefix,
120) -> Result<bool, SignatureError> {
121 match key {
122 BasicPrefix::Ed25519(pk) | BasicPrefix::Ed25519NT(pk) => match signature {
123 SelfSigningPrefix::Ed25519Sha512(signature) => {
124 Ok(pk.verify_ed(data.as_ref(), signature))
125 }
126 _ => Err(SignatureError::WrongSignatureTypeError),
127 },
128 BasicPrefix::ECDSAsecp256k1(key) | BasicPrefix::ECDSAsecp256k1NT(key) => match signature {
129 SelfSigningPrefix::ECDSAsecp256k1Sha256(signature) => {
130 Ok(key.verify_ecdsa(data.as_ref(), signature))
131 }
132 _ => Err(SignatureError::WrongSignatureTypeError),
133 },
134 _ => Err(SignatureError::WrongKeyTypeError),
135 }
136}
137
138pub fn derive(seed: &SeedPrefix, transferable: bool) -> Result<BasicPrefix, Error> {
142 let (pk, _) = seed.derive_key_pair()?;
143 Ok(match seed {
144 SeedPrefix::RandomSeed256Ed25519(_) if transferable => BasicPrefix::Ed25519(pk),
145 SeedPrefix::RandomSeed256Ed25519(_) if !transferable => BasicPrefix::Ed25519NT(pk),
146 SeedPrefix::RandomSeed256ECDSAsecp256k1(_) if transferable => {
147 BasicPrefix::ECDSAsecp256k1(pk)
148 }
149 SeedPrefix::RandomSeed256ECDSAsecp256k1(_) if !transferable => {
150 BasicPrefix::ECDSAsecp256k1NT(pk)
151 }
152 _ => return Err(Error::WrongSeedTypeError),
153 })
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use crate::keys::{PrivateKey, PublicKey};
160 use ed25519_dalek::SigningKey;
161 use rand::rngs::OsRng;
162 use said::derivation::{HashFunction, HashFunctionCode};
163
164 #[test]
165 fn simple_deserialize() -> Result<(), Error> {
166 let pref: IdentifierPrefix = "BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".parse()?;
167
168 assert_eq!(pref.derivation_code().to_str(), "B");
169
170 assert_eq!(pref.derivative().len(), 32);
171
172 assert_eq!(pref.derivative().to_vec(), vec![0u8; 32]);
173
174 Ok(())
175 }
176
177 #[test]
178 fn length() -> Result<(), Error> {
179 assert!(IdentifierPrefix::from_str("BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").is_ok());
181 assert!(IdentifierPrefix::from_str("CBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").is_ok());
182
183 assert!(!IdentifierPrefix::from_str("BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").is_ok());
185
186 assert!(
188 !IdentifierPrefix::from_str("BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").is_ok()
189 );
190
191 assert!(
193 !IdentifierPrefix::from_str("ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").is_ok()
194 );
195
196 assert!(
198 !IdentifierPrefix::from_str("BAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAA").is_ok()
199 );
200
201 Ok(())
202 }
203
204 #[test]
205 fn simple_serialize() -> Result<(), Error> {
206 let pref = BasicPrefix::Ed25519NT(PublicKey::new(
207 ed25519_dalek::VerifyingKey::from_bytes(&[0; 32])
208 .unwrap()
209 .to_bytes()
210 .to_vec(),
211 ));
212
213 assert_eq!(
214 pref.to_str(),
215 "BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
216 );
217
218 Ok(())
219 }
220
221 #[test]
222 fn verify() -> Result<(), Error> {
223 let data_string = "hello there";
224
225 let kp = SigningKey::generate(&mut OsRng);
226 let pub_key = PublicKey::new(kp.verifying_key().to_bytes().to_vec());
227 let priv_key = PrivateKey::new(kp.to_bytes().to_vec());
228
229 let key_prefix = BasicPrefix::Ed25519NT(pub_key);
230
231 let sig = priv_key.sign_ed(&data_string.as_bytes()).unwrap();
232 let sig_prefix = SelfSigningPrefix::Ed25519Sha512(sig);
233
234 let check = key_prefix.verify(&data_string.as_bytes(), &sig_prefix);
235 assert!(check.is_ok());
236 assert!(check.unwrap());
237
238 Ok(())
239 }
240
241 #[test]
242 fn prefix_deserialization() -> Result<(), Error> {
243 fn all_codes<F>(codes: Vec<(&str, usize)>, pred: F) -> Result<(), Error>
246 where
247 F: Fn(IdentifierPrefix) -> bool,
248 {
249 for (code, length) in codes {
250 let pref: IdentifierPrefix =
251 [code.to_string(), "A".repeat(length)].join("").parse()?;
252 assert!(pred(pref.clone()));
253 assert_eq!(pref.derivation_code().to_str(), code);
254 }
255 Ok(())
256 }
257
258 let basic_codes = vec!["B", "C", "D", "L", "1AAA", "1AAB", "1AAC", "1AAD"].into_iter();
260 let allowed_lengths = vec![43, 43, 43, 75, 44, 44, 76, 76].into_iter();
262 let is_basic = |identifier| matches!(&identifier, IdentifierPrefix::Basic(_));
263 all_codes(basic_codes.zip(allowed_lengths).collect(), is_basic)?;
264
265 let self_adressing_codes =
267 vec!["E", "F", "G", "H", "I", "0D", "0E", "0F", "0G"].into_iter();
268 let allowed_lengths = vec![43, 43, 43, 43, 43, 86, 86, 86, 86].into_iter();
270 let is_self_addresing =
271 |identifier| matches!(&identifier, IdentifierPrefix::SelfAddressing(_));
272 all_codes(
273 self_adressing_codes.zip(allowed_lengths).collect(),
274 is_self_addresing,
275 )?;
276
277 let is_self_signing = |identifier| matches!(&identifier, IdentifierPrefix::SelfSigning(_));
279 let self_signing_codes = vec!["0B", "0C", "1AAE"].into_iter();
281 let allowed_lengths = vec![86, 86, 152].into_iter();
282 all_codes(
283 self_signing_codes.zip(allowed_lengths).collect(),
284 is_self_signing,
285 )?;
286
287 Ok(())
288 }
289
290 #[test]
291 fn prefix_serialization() -> Result<(), Error> {
292 assert_eq!(
297 BasicPrefix::Ed25519NT(PublicKey::new(
298 ed25519_dalek::VerifyingKey::from_bytes(&[0; 32])
299 .unwrap()
300 .to_bytes()
301 .to_vec()
302 ))
303 .to_str(),
304 ["B".to_string(), "A".repeat(43)].join("")
305 );
306 assert_eq!(
307 BasicPrefix::X25519(PublicKey::new(
308 ed25519_dalek::VerifyingKey::from_bytes(&[0; 32])
309 .unwrap()
310 .to_bytes()
311 .to_vec()
312 ))
313 .to_str(),
314 ["C".to_string(), "A".repeat(43)].join("")
315 );
316 assert_eq!(
317 BasicPrefix::Ed25519(PublicKey::new(
318 ed25519_dalek::VerifyingKey::from_bytes(&[0; 32])
319 .unwrap()
320 .to_bytes()
321 .to_vec()
322 ))
323 .to_str(),
324 ["D".to_string(), "A".repeat(43)].join("")
325 );
326 assert_eq!(
327 BasicPrefix::X448(PublicKey::new([0; 56].to_vec())).to_str(),
328 ["L".to_string(), "A".repeat(75)].join("")
329 );
330 assert_eq!(
331 BasicPrefix::ECDSAsecp256k1NT(PublicKey::new([0; 33].to_vec())).to_str(),
332 ["1AAA".to_string(), "A".repeat(44)].join("")
333 );
334 assert_eq!(
335 BasicPrefix::ECDSAsecp256k1(PublicKey::new([0; 33].to_vec())).to_str(),
336 ["1AAB".to_string(), "A".repeat(44)].join("")
337 );
338 assert_eq!(
339 BasicPrefix::Ed448NT(PublicKey::new([0; 57].to_vec())).to_str(),
340 ["1AAC".to_string(), "A".repeat(76)].join("")
341 );
342 assert_eq!(
343 BasicPrefix::Ed448(PublicKey::new([0; 57].to_vec())).to_str(),
344 ["1AAD".to_string(), "A".repeat(76)].join("")
345 );
346
347 assert_eq!(
349 SelfAddressingIdentifier::new(HashFunctionCode::Blake3_256.into(), vec![0; 32])
350 .to_str(),
351 ["E".to_string(), "A".repeat(43)].join("")
352 );
353 assert_eq!(
354 SelfAddressingIdentifier::new(HashFunctionCode::Blake2B256(vec!()).into(), vec![0; 32])
355 .to_str(),
356 ["F".to_string(), "A".repeat(43)].join("")
357 );
358 assert_eq!(
359 SelfAddressingIdentifier::new(HashFunctionCode::Blake2S256(vec!()).into(), vec![0; 32])
360 .to_str(),
361 ["G".to_string(), "A".repeat(43)].join("")
362 );
363 assert_eq!(
364 SelfAddressingIdentifier::new(HashFunctionCode::SHA3_256.into(), vec![0; 32]).to_str(),
365 ["H".to_string(), "A".repeat(43)].join("")
366 );
367 assert_eq!(
368 SelfAddressingIdentifier::new(HashFunctionCode::SHA2_256.into(), vec![0; 32]).to_str(),
369 ["I".to_string(), "A".repeat(43)].join("")
370 );
371 assert_eq!(
372 SelfAddressingIdentifier::new(HashFunctionCode::Blake3_512.into(), vec![0; 64])
373 .to_str(),
374 ["0D".to_string(), "A".repeat(86)].join("")
375 );
376 assert_eq!(
377 SelfAddressingIdentifier::new(HashFunctionCode::SHA3_512.into(), vec![0; 64]).to_str(),
378 ["0E".to_string(), "A".repeat(86)].join("")
379 );
380 assert_eq!(
381 SelfAddressingIdentifier::new(HashFunctionCode::Blake2B512.into(), vec![0; 64])
382 .to_str(),
383 ["0F".to_string(), "A".repeat(86)].join("")
384 );
385 assert_eq!(
386 SelfAddressingIdentifier::new(HashFunctionCode::SHA2_512.into(), vec![0; 64]).to_str(),
387 ["0G".to_string(), "A".repeat(86)].join("")
388 );
389
390 assert_eq!(
392 SelfSigningPrefix::ECDSAsecp256k1Sha256(vec![0; 64]).to_str(),
393 ["0C".to_string(), "A".repeat(86)].join("")
394 );
395 assert_eq!(
396 SelfSigningPrefix::Ed25519Sha512(vec![0; 64]).to_str(),
397 ["0B".to_string(), "A".repeat(86)].join("")
398 );
399 assert_eq!(
400 SelfSigningPrefix::Ed448(vec![0; 114]).to_str(),
401 ["1AAE".to_string(), "A".repeat(152)].join("")
402 );
403
404 Ok(())
405 }
406
407 #[test]
408 pub fn test_identifier_encoding() {
409 use crate::keys::PublicKey;
410 use sodiumoxide::hex;
411 let pub_key = "694e894769e6c3267e8b477c2590284cd647dd42ef6007d254fce1cd2e9be423";
412 let key = hex::decode(pub_key).unwrap();
413 let bp = BasicPrefix::Ed25519NT(PublicKey::new(key));
414 let hash_function: HashFunction = HashFunctionCode::Blake3_256.into();
415 let expected_identifier = "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj";
416 assert_eq!(bp.to_str(), expected_identifier);
417
418 let to_digest = "abcdefghijklmnopqrstuvwxyz0123456789";
420 let dig = hash_function.derive(to_digest.as_bytes());
421 dig.verify_binding(to_digest.as_bytes());
422 assert_eq!(dig.to_str(), "ELC5L3iBVD77d_MYbYGGCUQgqQBju1o4x1Ud-z2sL-ux");
423
424 let to_digest = "BDjXHlcskwOzNj8rYbV8IQ6ox2TW_KkbA1K3-n0EU0un";
426 let dig = hash_function.derive(to_digest.as_bytes());
427 assert_eq!(dig.to_str(), "EP9XvFnpQP4vnaTNDNAMU2T7nxDPe1EZLUaiABcLRfS4");
428
429 let self_signing_b64 =
431 "mdI8OSQkMJ9r-xigjEByEjIua7LHH3AOJ22PQKqljMhuhcgh9nGRcKnsz5KvKd7K_H9-1298F4Id1DxvIoEmCQ==";
432 let self_signing_raw = base64::decode_config(self_signing_b64, base64::URL_SAFE).unwrap();
433
434 let ssp = SelfSigningPrefix::Ed25519Sha512(self_signing_raw);
435 assert_eq!(
436 ssp.to_str(),
437 "0BCZ0jw5JCQwn2v7GKCMQHISMi5rsscfcA4nbY9AqqWMyG6FyCH2cZFwqezPkq8p3sr8f37Xb3wXgh3UPG8igSYJ"
438 );
439 }
440}