diff options
| author | Will Dillon <william@housedillon.com> | 2025-12-04 17:07:12 +0000 |
|---|---|---|
| committer | Will Dillon <william@housedillon.com> | 2025-12-04 17:07:12 +0000 |
| commit | bf21ebaaae44b267cfefc87eee9608c09aab96b7 (patch) | |
| tree | 67234092d3c85a9c58d1fa9ca51337ac480ebfb7 /src/no_std_identity.rs | |
| parent | Better than 90% everywhere. (diff) | |
| download | meshcore-rs-bf21ebaaae44b267cfefc87eee9608c09aab96b7.tar.gz meshcore-rs-bf21ebaaae44b267cfefc87eee9608c09aab96b7.zip | |
Getting closer to no-std being done
Diffstat (limited to 'src/no_std_identity.rs')
| -rw-r--r-- | src/no_std_identity.rs | 108 |
1 files changed, 108 insertions, 0 deletions
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<NameString>)> { + 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 |
