orbinum-encrypted-memo
Encrypted memo primitives for private transaction metadata in Orbinum Network.
Features
- ChaCha20Poly1305 AEAD: Authenticated encryption for memo data
- Viewing key encryption: Only recipient can decrypt note details
- Selective disclosure: ZK proofs for partial data revelation
- Key derivation: Deterministic keys from spending key
- no_std compatible: WASM runtime support
Installation
[]
= "0.2"
# For selective disclosure (ZK proofs)
= { = "0.2", = ["disclosure"] }
Usage
Basic Encryption/Decryption
use ;
// Create memo data
let memo = new;
// Encrypt for recipient
let nonce = random;
let encrypted = encrypt_memo?;
// Recipient decrypts
let decrypted = decrypt_memo?;
assert_eq!;
Key Derivation from Spending Key
use KeySet;
// Derive all keys from master spending key
let keys = from_spending_key;
// Access derived keys
let viewing_key = &keys.viewing_key; // For decryption
let nullifier_key = &keys.nullifier_key; // For double-spend prevention
let eddsa_key = &keys.eddsa_key; // For signatures
// Decrypt with viewing key
let memo = decrypt_memo?;
Selective Disclosure with ZK Proofs
use ;
// Create mask (reveal only value, hide owner and blinding)
let mask = only_value;
// Load circuit artifacts (client responsibility)
let proving_key_bytes = load_artifact?;
let wasm_bytes = load_artifact?;
// Generate ZK proof
let proof = generate_disclosure_proof?;
// Extract revealed data
let partial = proof.extract_partial_memo;
assert_eq!;
assert_eq!; // Hidden
Note Scanning (Wallet Use Case)
use decrypt_memo;
// Scan blockchain for owned notes
for in blockchain_notes
Encryption Scheme
Uses ChaCha20Poly1305 AEAD with per-note key derivation:
encryption_key = SHA256(viewing_key || commitment || domain_separator)
ciphertext = ChaCha20Poly1305(memo_data, encryption_key, nonce)
encrypted_memo = nonce(12) || ciphertext(76) || mac(16) = 104 bytes
Key Derivation Hierarchy
spending_key (master secret, 32 bytes)
│
├── viewing_key = SHA256(spending_key || "orbinum-viewing-key-v1")
├── nullifier_key = SHA256(spending_key || "orbinum-nullifier-key-v1")
└── eddsa_key = SHA256(spending_key || "orbinum-eddsa-key-v1")
Memo Structure
| Field | Type | Size | Description |
|---|---|---|---|
value |
u64 | 8 bytes | Note amount |
owner_pk |
FieldElement | 32 bytes | Owner public key |
blinding |
FieldElement | 32 bytes | Blinding factor |
asset_id |
u32 | 4 bytes | Asset identifier |
Total plaintext: 76 bytes Encrypted memo: 104 bytes (with nonce + MAC)
Selective Disclosure Features
With the disclosure feature flag:
| Disclosure Mask | Reveals | Use Case |
|---|---|---|
only_value() |
Amount only | Prove balance without revealing identity |
only_owner() |
Owner only | Prove ownership without revealing amount |
value_and_owner() |
Amount + Owner | Compliance disclosure |
none() |
Nothing | Prove knowledge without revealing anything |
Circuit Artifacts
⚠️ Client Responsibility: This crate does NOT bundle circuit artifacts (WASM, proving keys).
Download from: orbinum/circuits releases
# Download disclosure circuit artifacts (v0.1.0)
# Verify checksums
Security Properties
- Confidentiality: Only viewing key holder can decrypt
- Authenticity: AEAD MAC prevents tampering
- Unlinkability: Unique encryption key per note (derived from commitment)
- Forward Secrecy: Compromising one key doesn't reveal others
- Zero-Knowledge: Selective disclosure without revealing hidden fields
Performance
| Operation | Time | Notes |
|---|---|---|
| Encrypt | 15μs | ChaCha20Poly1305 |
| Decrypt | 20μs | Includes verification |
| Key Derivation | 8μs | SHA256 hashing |
| Disclosure Proof | 150ms | ZK proof generation |
Measured on Apple M1
License
Licensed under either of Apache License, Version 2.0 or GPL v3 at your option.