From bf21ebaaae44b267cfefc87eee9608c09aab96b7 Mon Sep 17 00:00:00 2001 From: Will Dillon Date: Thu, 4 Dec 2025 17:07:12 +0000 Subject: Getting closer to no-std being done --- src/no_std_identity.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/no_std_identity.rs (limited to 'src/no_std_identity.rs') diff --git a/src/no_std_identity.rs b/src/no_std_identity.rs new file mode 100644 index 0000000..2a0018e --- /dev/null +++ b/src/no_std_identity.rs @@ -0,0 +1,108 @@ +use bytes::Bytes; +use crate::{NameString, crypto::{Keystore, PrivateKey, PublicKey, SharedSecret}}; +use tinyvec::ArrayVec; + +#[derive(PartialEq, Clone, Debug)] +pub struct Identity { + pub private_key: PrivateKey, + pub hash_prefix: u32, + pub secrets: ArrayVec<[(u32, SharedSecret); 10]>, +} + +impl Default for Identity { + fn default() -> Self { + let private_key = PrivateKey::default(); + let hash_prefix = private_key.hash_prefix(); + + Self { + private_key, + hash_prefix, + secrets: Default::default() + } + } +} + +#[derive(PartialEq, Clone, Debug)] +pub struct StaticKeystore { + pub identities: ArrayVec<[Identity; 10]>, + pub groups: ArrayVec<[SharedSecret; 10]>, +} + +impl Keystore for StaticKeystore { + fn decrypt_and_id_p2p(&self, _source: u8, _dest: u8, mac: u16, data: &Bytes) -> Option<(Bytes, u32, u32)> { + // Just brute-force all the secrets until one matches... + for identity in self.identities.iter() { + for (peer_prefix, secret) in identity.secrets.iter() { + let result = secret.mac_then_decrypt(mac, data); + if let Some(result) = result { + return Some((result, identity.hash_prefix, *peer_prefix)); + } + } + } + None + } + + fn decrypt_and_id_group(&self, _group_hash_prefix: u8, mac: u16, data: &Bytes) -> Option<(Bytes, Option)> { + for group in self.groups.iter() { + let result = group.mac_then_decrypt(mac, data); + if let Some(result) = result { + return Some((result, None)); + } + } + + None + } + + fn decrypt_anon(&self, _dest: u8, pub_key: &PublicKey, mac: u16, data: &Bytes) -> Option<(Bytes, u32)> { + // For each identity, create a shared secret against the provided public key and check it. + for identity in self.identities.iter() { + let secret = identity.private_key.create_secret(pub_key); + let result = secret.mac_then_decrypt(mac, data); + if let Some(result) = result { + return Some((result, identity.hash_prefix)); + } + } + None + } +} + +#[derive(PartialEq, Debug, Clone)] +pub struct StaticKeystoreInput { + pub identities: ArrayVec<[PrivateKey; 10]>, + pub contacts: ArrayVec<[PublicKey; 10]>, + pub groups: ArrayVec<[SharedSecret; 10]>, +} + +impl StaticKeystoreInput { + pub fn compile(self) -> StaticKeystore { + let mut retval = StaticKeystore { + identities: ArrayVec::new(), + groups: ArrayVec::new(), + }; + + for identity_in in self.identities { + let mut identity = Identity::default(); + identity.private_key = identity_in; + identity.hash_prefix = PublicKey::from(&identity.private_key).hash_prefix(); + for contact_in in self.contacts.iter() { + identity.secrets.push((contact_in.hash_prefix(), identity.private_key.create_secret(&contact_in))); + } + + retval.identities.push(identity); + } + + for group in self.groups.iter() { + retval.groups.push(group.clone()); + } + + retval + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_compile() { + + } +} \ No newline at end of file -- cgit v1.2.3