Skip to content

Extract security-critical core to Rust library #12

@SkogsErik

Description

@SkogsErik

Summary

Move sensitive cryptographic and protocol code from Python to a small, auditable Rust library. Python CLI calls it via FFI (PyO3).

Motivation

Python has inherent limitations for security-critical code:

  • No guaranteed memory zeroing (GC timing unpredictable)
  • Keys may remain in heap after use
  • mlock() requires ctypes hacks
  • Harder to audit (dynamic typing, large stdlib)

A Rust core would provide:

  • Memory safety guarantees
  • zeroize crate for secure memory clearing
  • Single audit target (<2000 lines)
  • Shared with firmware (C FFI) and future WASM clients

Architecture

┌─────────────────────┐     PyO3 FFI          ┌──────────────────┐
│   Python CLI/UI     │◄────────────────────►│  loramesh-core   │
│                     │                       │  (Rust crate)    │
│  - User interaction │                       │                  │
│  - Config/settings  │                       │  - IdentityKey   │
│  - Tor management   │                       │  - NoiseSession  │
│  - Contact import   │                       │  - Ratchet state │
│                     │                       │  - CBOR parsing  │
│                     │                       │  - secure_wipe() │
└─────────────────────┘                       └──────────────────┘

Rust Core Responsibilities

MUST be in Rust:

  • Key derivation (Ed25519 → X25519)
  • Noise_IK handshake state machine
  • Session key ratcheting
  • Secure memory zeroing (zeroize on drop)
  • CBOR parsing (serde_cbor)

Stays in Python:

  • CLI commands and user interaction
  • Tor process management
  • File I/O (config, contacts)
  • Network transport

Proposed API

// Exposed to Python via PyO3
pub struct IdentityKey { /* zeroize on drop */ }
pub struct Session { /* zeroize on drop */ }

impl IdentityKey {
    pub fn generate() -> Self;
    pub fn from_seed(seed: &[u8; 32]) -> Self;
    pub fn public_bytes(&self) -> [u8; 32];
    pub fn derive_x25519(&self) -> X25519Key;
}

impl Session {
    pub fn initiate(identity: &IdentityKey, peer_pubkey: &[u8; 32]) -> (Self, Vec<u8>);
    pub fn respond(identity: &IdentityKey, handshake_msg: &[u8]) -> Result<(Self, Vec<u8>), Error>;
    pub fn encrypt(&mut self, plaintext: &[u8]) -> Vec<u8>;
    pub fn decrypt(&mut self, ciphertext: &[u8]) -> Result<Vec<u8>, Error>;
}

pub fn secure_wipe(data: &mut [u8]);

Dependencies (Rust)

  • ring or dalek-cryptography for Ed25519/X25519
  • chacha20poly1305 for AEAD
  • zeroize for secure memory clearing
  • serde + serde_cbor for parsing
  • pyo3 for Python bindings

Timeline

  1. Phase 1: Continue Python prototype, stabilize protocol
  2. Phase 2: Create loramesh-core Rust crate with tests
  3. Phase 3: Create PyO3 bindings, integrate into Python CLI
  4. Phase 4: Deprecate Python crypto code, audit Rust core

Priority

MEDIUM - Not blocking prototype, required before production high-risk deployment

Related

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    hardeningSecurity hardeningsecuritySecurity-critical features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions