aboutsummaryrefslogtreecommitdiffstats
path: root/src/no_std_identity.rs
diff options
context:
space:
mode:
authorWill Dillon <william@housedillon.com>2025-12-04 17:07:12 +0000
committerWill Dillon <william@housedillon.com>2025-12-04 17:07:12 +0000
commitbf21ebaaae44b267cfefc87eee9608c09aab96b7 (patch)
tree67234092d3c85a9c58d1fa9ca51337ac480ebfb7 /src/no_std_identity.rs
parentBetter than 90% everywhere. (diff)
downloadmeshcore-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.rs108
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