diff options
| author | Will Dillon <william@housedillon.com> | 2025-11-07 19:56:31 +0000 |
|---|---|---|
| committer | Will Dillon <william@housedillon.com> | 2025-11-07 19:56:31 +0000 |
| commit | c76a6ef610768d529ebb75b2af5d721d09797e06 (patch) | |
| tree | 9f6e22e4ab5ce185c21fd8f1677c020a259f9c60 /src | |
| parent | Decryption is working! (diff) | |
| download | meshcore-rs-c76a6ef610768d529ebb75b2af5d721d09797e06.tar.gz meshcore-rs-c76a6ef610768d529ebb75b2af5d721d09797e06.zip | |
Switching to Mac
Diffstat (limited to 'src')
| -rw-r--r-- | src/crypto.rs | 14 | ||||
| -rw-r--r-- | src/identity.rs | 80 |
2 files changed, 88 insertions, 6 deletions
diff --git a/src/crypto.rs b/src/crypto.rs index 8215f94..d428c20 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,5 +1,6 @@ -use std::str::FromStr; +use std::{fmt::{Debug, Display}, str::FromStr}; use ed25519_dalek::{VerifyingKey, hazmat::ExpandedSecretKey}; +use serde::Deserialize; use tokio_util::bytes::{Buf, BufMut, Bytes, BytesMut}; use hex::{decode, decode_to_slice, encode}; @@ -23,6 +24,17 @@ pub enum MeshcoreCryptoError { KeyCreationError, } +impl Display for MeshcoreCryptoError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MeshcoreCryptoError::KeyLengthError => f.write_str("Key Length Error"), + MeshcoreCryptoError::TryFromSliceError => f.write_str("Try From Slice Error"), + MeshcoreCryptoError::HexDecodeError => f.write_str("Hex Decode Error"), + MeshcoreCryptoError::KeyCreationError => f.write_str("Key Creation Error"), + } + } +} + #[derive(PartialEq)] pub struct PrivateKey(ExpandedSecretKey); diff --git a/src/identity.rs b/src/identity.rs index ea88164..5737ec0 100644 --- a/src/identity.rs +++ b/src/identity.rs @@ -1,30 +1,100 @@ -use std::collections::{HashMap}; +use std::{collections::HashMap, str::FromStr}; +use serde::{Deserialize, de}; use x25519_dalek::PublicKey; -use crate::crypto::{PrivateKey, SharedSecret}; +use crate::crypto::{MeshcoreCryptoError, PrivateKey, SharedSecret}; -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone, Deserialize)] +/// The Identity structure contains the information to decrypt +/// incoming messages and sign and encrypt outgoing messages. +/// +/// It has the necessary cryptographic material needed to appear +/// as this identity when creating messages. pub struct Identity { + /// The display name if this user identity. pub name: String, - pub private_key: PrivateKey + + /// The private key of this identity. There are currently + /// no ways in this library to generate a new private key + /// from scratch (while ensuing it's sound) so it must be + /// provided by the user. + #[serde(deserialize_with = "private_key")] + pub private_key: PrivateKey, + + /// The derived public key given this identity's + /// private key. The hash prefix of this (typically 1-byte) + /// is used as a first-pass to identity the recipient. + #[serde(deserialize_with = "public_key")] + pub public_key: PublicKey, + + /// The secrets has is a collection of shared secrets + /// indexed by the public key of the other side of the + /// connection. The whole remote public key must be + /// used because there are many many hash collisions + /// when using just the 1-byte hash prefix. + #[serde(skip)] + pub secrets: HashMap<String, SharedSecret> } #[derive(PartialEq, Debug, Clone)] + +/// The Contact structure contains the information needed +/// to decrypt messages from a remote user intended for +/// either an identity or a channel. +/// +/// It's cryptographic material is also needed to uniquely +/// identify the origin of a message. Most source values +/// are only one byte, so that information just limits the +/// number of entries in the contact list that must be searched +/// before the correct contact is found. pub struct Contact { + /// The display name of the contact pub name: String, + + /// The provided public key of the remote contact pub public_key: PublicKey } #[derive(PartialEq, Debug, Clone)] +/// A Group in MeshCore is a kind of contact, except that its +/// secret is fixed and shared directly. It's not derived via +/// a public and private key. Otherwise, it behaves more like a +/// contact in the sense that it's full identity is discovered +/// by whether its secret can correctly decrypt messages. pub struct Group { + /// The display name of the group pub name: String, + + /// The group's shared secret pub secret: SharedSecret } pub struct Keystore { identities: HashMap<String, Identity>, contacts: HashMap<String, Contact>, - groups: HashMap<String, Group> + groups: HashMap<String, Group>, + +} + +impl Identity { + fn private_key<'de, D>(deserializer: D) -> Result<PrivateKey, D::Error> + where D: de::Deserializer<'de> { + let s: &str = de::Deserialize::deserialize(deserializer)?; + let key = PrivateKey::from_str(s).map_err(de::Error::custom)? + } +} + +impl<'de> Deserialize<'de> for Contact { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: serde::Deserializer<'de> { + todo!() + } } +impl<'de> Deserialize<'de> for Group { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: serde::Deserializer<'de> { + todo!() + } +}
\ No newline at end of file |
