Architecture & Flow Diagrams
This document provides visual representations of the Solana Secure Signer architecture.
ποΈ System Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER APPLICATION LAYER β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Your Python CLI (Coldstar SOL) β β
β β β’ Transaction building β β
β β β’ Network communication β β
β β β’ User interface β β
β βββββββββββββββββ¬βββββββββββββββββββββββββββββ¬ββββββββββββββββββ β
β β β β
β β β β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββΌββββββββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INTEGRATION LAYER β
β ββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ β
β β FFI Integration β β CLI Subprocess Integration β β
β β (Fast, Direct) β β (Portable, Isolated) β β
β β β β β β
β β β’ ctypes bindings β β β’ subprocess.run() β β
β β β’ Shared library β β β’ stdin/stdout JSON β β
β β β’ Direct function calls β β β’ Process isolation β β
β ββββββββββββββ¬ββββββββββββββ ββββββββββββββ¬ββββββββββββββββββββ β
β β β β
βββββββββββββββββΌβββββββββββββββββββββββββββββββΌββββββββββββββββββββββββ
β β
ββββββββββββ¬ββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RUST SIGNING CORE β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Public API β β
β β β’ sign_transaction(container, passphrase, tx) β β
β β β’ create_encrypted_container(key, passphrase) β β
β ββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Signing Logic (signer.rs) β β
β β 1. Derive decryption key (Argon2id) β β
β β 2. Decrypt ciphertext (AES-256-GCM) β β
β β 3. Copy to secure buffer β β
β β 4. Sign with Ed25519 β β
β β 5. Return signature β β
β ββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Secure Memory (secure_memory.rs) β β
β β β’ SecureBuffer: mlock/VirtualLock β β
β β β’ Automatic zeroization on drop β β
β β β’ Panic-safe cleanup β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Dependencies: ed25519-dalek, aes-gcm, argon2, zeroize, region β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Signing Flow (Detailed)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 1: INPUT PREPARATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Python Application β
β ββ Load encrypted container (JSON file) β
β ββ Get passphrase (user input, secure) β
β ββ Prepare unsigned transaction bytes β
β β
β Status: β
No sensitive data yet β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 2: ENTER RUST SECURE ZONE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β FFI Boundary / CLI Invocation β
β ββ Serialize inputs to JSON/bytes β
β ββ Call: sign_transaction_ffi() or subprocess β
β ββ Enter Rust memory space β
β β
β Status: β
Encrypted data crosses boundary β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 3: KEY DERIVATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Argon2id Key Derivation β
β ββ Input: passphrase + salt from container β
β ββ Compute: memory-hard hash β
β ββ Output: 32-byte AES key β
β ββ Zeroize: passphrase copy β
β β
β Status: β
Passphrase zeroized, no plaintext key yet β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 4: MEMORY ALLOCATION & LOCKING β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β SecureKeyBuffer::new_secret_key() β
β ββ Allocate: 32 bytes on heap β
β ββ Lock: mlock()/VirtualLock() syscall β
β ββ Verify: lock succeeded or return error β
β ββ Initialize: fill with zeros β
β β
β Memory State: β
β ββββββββββββββββββββββββββββββββββββββ β
β β Locked RAM (32 bytes) β β
β β [0, 0, 0, ..., 0] (all zeros) β β
β β Status: LOCKED, not swappable β β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β Status: β
Secure buffer ready, no sensitive data yet β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 5: DECRYPTION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β AES-256-GCM Decryption β
β ββ Input: ciphertext + nonce + derived key β
β ββ Decrypt: to temporary Vec<u8> β
β ββ Verify: authentication tag β
β ββ Output: plaintext key (32 bytes) β
β β
β Temporary State: β
β ββββββββββββββββββββββββββββββββββββββ β
β β Stack/Heap (decrypted_bytes) β β
β β [kβ, kβ, kβ, ..., kββ] β β
β β Status: PLAINTEXT KEY! β οΈ β β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β Status: β οΈ CRITICAL - Plaintext key in temporary buffer β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 6: SECURE TRANSFER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Copy to Locked Buffer β
β ββ Copy: decrypted_bytes β secure_key buffer β
β ββ Zeroize: decrypted_bytes (constant-time) β
β ββ Verify: no copies remain β
β β
β Before: After: β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β Temporary Buffer β β Temporary Buffer β β
β β [kβ, kβ, ..., kββ] β βββββββ> β [0, 0, ..., 0] β β
β β (plaintext key) β β (zeroized) β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β Locked Buffer β β Locked Buffer β β
β β [0, 0, ..., 0] β βββββββ> β [kβ, kβ, ..., kββ] β β
β β (empty) β β (plaintext key) β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β
β Status: β
Key in locked memory, temporary copy zeroized β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 7: SIGNING β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Ed25519 Signing β
β ββ Create: SigningKey from locked buffer (borrow, no copy) β
β ββ Sign: signature = signing_key.sign(transaction) β
β ββ Output: 64-byte signature β
β ββ Note: SigningKey borrows, doesn't own the key β
β β
β Memory State: β
β ββββββββββββββββββββββββββββββββββββββ β
β β Locked Buffer β β
β β [kβ, kβ, kβ, ..., kββ] ββββββββ SigningKey borrows β
β β Status: LOCKED, being used β β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β Status: β οΈ Key still in memory, being used for signing β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 8: RESULT PREPARATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Build Signed Transaction β
β ββ Allocate: new Vec<u8> for result β
β ββ Append: signature (64 bytes, public data) β
β ββ Append: original transaction β
β ββ Return: SignedTransaction struct β
β β
β Status: β
Public signature ready, key still in locked buffer β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 9: AUTOMATIC CLEANUP (Drop) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β SecureKeyBuffer::drop() automatically called β
β ββ Trigger: secure_key goes out of scope β
β ββ Zeroize: data.zeroize() (constant-time) β
β ββ Unlock: munlock()/VirtualUnlock() β
β ββ Extra: manual write_bytes for paranoia β
β β
β Before Drop: After Drop: β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β Locked Buffer β β Unlocked Memory β β
β β [kβ, kβ, ..., kββ] β βββββββ> β [0, 0, ..., 0] β β
β β (plaintext key) β β (zeroized) β β
β β Status: LOCKED β β Status: FREE β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β
β Note: This happens even if signing panicked! β
β β
β Status: β
Key completely erased from memory β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHASE 10: RETURN TO PYTHON β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β FFI Boundary / CLI Output β
β ββ Serialize: SignedTransaction to JSON β
β ββ Return: to Python via FFI or stdout β
β ββ Python receives: signature + signed transaction β
β β
β Data Returned to Python: β
β β’ signature: [sβ, sβ, ..., sββ] (64 bytes, public) β
β β’ signed_tx: signature + transaction (public) β
β β
β Status: β
Only public data crosses boundary β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
SECURITY SUMMARY:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β’ Plaintext key existed in locked memory for phases 6-8 only
β’ Key was zeroized immediately after use (phase 9)
β’ No copies of plaintext key exist outside locked buffer
β’ Cleanup is guaranteed even on panic
β’ Only public data (signature) returned to Python
β’ Private key NEVER exposed to Python memory space
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π¦ Data Flow (Input β Output)
INPUT (Python) SECURE ZONE (Rust) OUTPUT (Python)
βββββββββββββββ βββββββββββββββββββ βββββββββββββββ
ββββββββββββββββ ββββββββββββββββ
β Encrypted β β Signature β
β Container ββββββββββ β (64 bytes) β
β (JSON) β β β β
ββββββββββββββββ β ββββββββββββββββ
β β²
ββββββββββββββββ β βββββββββββββββββββββββ β
β Passphrase ββββββββββΌββββββββ>β Rust Signing Core ββββββββββββββββββ€
β (string) β β β β β
ββββββββββββββββ β β 1. Decrypt β ββββββββββββββββ
β β 2. Lock memory β β Signed β
ββββββββββββββββ β β 3. Sign β β Transaction β
β Unsigned TX ββββββββββ β 4. Zeroize β β (bytes) β
β (bytes) β β 5. Return β ββββββββββββββββ
ββββββββββββββββ βββββββββββββββββββββββ β²
β
Private key exists β
here only! Never β
leaves this box. β
β
ββββββββββββββββββββ β
β Locked Memory β β
β ββββββββββββββ β β
β β Private β β β
β β Key β β β
β β (32 bytes) β β β
β ββββββββββββββ β β
β Auto-zeroized! β β
ββββββββββββββββββββ β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FFI / CLI Boundary β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ§ββ
Legend:
ββββ> Data flow
βββ> Security boundary
βββββ Data container
π Memory Safety Guarantees
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MEMORY SAFETY GUARANTEES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Guarantee 1: MEMORY LOCKING
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RAM β
β βββββββββββββββββββββββββββββββββββββ β
β β Locked Pages (via mlock) β βββ Private key here β
β β Cannot be swapped to disk β β
β βββββββββββββββββββββββββββββββββββββ β
β β β
β β BLOCKED (no swap) β
β βΌ β
β βββββββββββββββββββββββββββββββββββββ β
β β Disk / Swap File β βββ Key never reaches here β
β β β Private key CANNOT be here β β
β βββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Guarantee 2: ZEROIZATION
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Before Drop: After Drop: β
β βββββββββββββββββββ βββββββββββββββββββ β
β β [kβ, kβ, ..., kββ]β β [0, 0, ..., 0] β β
β β Private key β ββββββββ> β All zeros β β
β β SENSITIVE! β οΈ β β Safe β
β β
β βββββββββββββββββββ βββββββββββββββββββ β
β β
β Method: zeroize crate (constant-time, not optimized out) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Guarantee 3: PANIC SAFETY
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Normal Flow: Panic Flow: β
β ββββββββββββ ββββββββββββ β
β β Signing β β Signing β β
β β Success β β PANIC! β β
β ββββββ¬ββββββ ββββββ¬ββββββ β
β β β β
β βΌ βΌ β
β ββββββββββββ ββββββββββββ β
β β Drop β β Drop β βββ Drop ALWAYS runs β
β β Runs β β Runs β β
β ββββββ¬ββββββ ββββββ¬ββββββ β
β β β β
β βΌ βΌ β
β ββββββββββββ ββββββββββββ β
β β Zeroized β β Zeroized β βββ Key erased in both cases β
β ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Guarantee 4: NO COPIES
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ONLY ONE instance of plaintext key exists: β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β SecureKeyBuffer β β
β β ββββββββββββββββββββββββββββββββββββ β β
β β β Private Key (32 bytes) β ββββββββ Single instance β
β β β [kβ, kβ, kβ, ..., kββ] β β β
β β ββββββββββββββββββββββββββββββββββββ β β
β β β² β β
β β β borrow (no copy) β β
β β β β β
β β βββββββββββ΄βββββββββββ β β
β β β SigningKey β β β
β β β (borrows data) β β β
β β βββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β All other buffers (decryption, etc.) are zeroized immediately β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Guarantee 5: EPHEMERAL LIFECYCLE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Function Scope: β
β β
β fn sign_transaction(...) { β
β let secure_key = SecureKeyBuffer::new(); βββ Created β
β // ... decrypt into secure_key ... β
β // ... use for signing ... β
β return signature; β
β } βββ secure_key dropped here, automatic cleanup β
β β
β Key exists ONLY during function execution β
β No global variables, no caching, no persistence β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π― Integration Comparison
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INTEGRATION MODE COMPARISON β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FFI Mode (libsolana_secure_signer.so/dll/dylib) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Python βββ(ctypes)βββ Rust Library β
β β
β Pros: β
β β
Fastest (no process overhead) β
β β
Direct function calls β
β β
Minimal latency (~0.1ms overhead) β
β β
β Cons: β
β β οΈ Requires compiled library for platform β
β β οΈ Shared memory space (less isolated) β
β β
β Use When: β
β β’ Production deployments β
β β’ High transaction throughput β
β β’ Minimal latency required β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLI Mode (solana-signer binary) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Python ββ(subprocess)βββ Rust Binary ββ(exit)βββ All memory freed β
β β
β Pros: β
β β
Maximum isolation (separate process) β
β β
Platform-agnostic (just needs binary) β
β β
Automatic cleanup (process exit) β
β β
No FFI complexity β
β β
β Cons: β
β β οΈ Slower (process startup ~10-50ms) β
β β οΈ IPC overhead (JSON serialization) β
β β
β Use When: β
β β’ Development/testing β
β β’ Maximum security isolation β
β β’ Cross-platform portability β
β β’ Occasional signing (not high frequency) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Performance Comparison:
ββββββββββββββββββ¬βββββββββββ¬ββββββββββββ¬βββββββββββββββ
β Operation β FFI β CLI β Difference β
ββββββββββββββββββΌβββββββββββΌββββββββββββΌβββββββββββββββ€
β Overhead β ~0.1ms β ~10-50ms β 100-500x β
β Throughput β High β Low β - β
β Memory Safety β Good β Excellentβ CLI better β
β Portability β Medium β High β CLI better β
ββββββββββββββββββ΄βββββββββββ΄ββββββββββββ΄βββββββββββββββ
This completes the visual documentation! π