saorsa_seal/lib.rs
1//! # Threshold Sealing for Group Data in the Saorsa Network
2//!
3//! `saorsa-seal` provides threshold sealing capabilities for the Saorsa network,
4//! combining threshold cryptography, forward error correction, and authenticated encryption
5//! to create a robust distributed data protection system.
6//!
7//! ## Architecture Integration
8//!
9//! This crate leverages the Saorsa ecosystem:
10//! - **[`saorsa-core`]**: Threshold cryptography and DHT abstraction
11//! - **[`saorsa-fec`]**: Forward error correction and AEAD encryption
12//! - **[`saorsa-pqc`]**: Post-quantum cryptography
13//!
14//! ## Core Features
15//!
16//! - **Threshold Sealing**: Uses Shamir's Secret Sharing via [`saorsa-core`] for configurable threshold schemes
17//! - **Forward Error Correction**: Reed-Solomon coding via [`saorsa-fec`] for fault tolerance
18//! - **AEAD Encryption**: XChaCha20-Poly1305 content encryption via [`saorsa-fec::CryptoEngine`]
19//! - **Post-Quantum Security**: ML-KEM-768 encryption via [`saorsa-pqc`]
20//! - **Distributed Storage**: DHT abstraction from [`saorsa-core`] for decentralized storage
21//! - **Verifiable Shares**: Feldman commitments for cryptographic share verification
22//! - **Envelope Encryption**: Post-quantum recipient encryption using ML-KEM-768
23//!
24//! ## Quick Start
25//!
26//! ```rust
27//! use saorsa_seal::{seal_bytes, open_bytes, SealPolicy, FecParams, EnvelopeKind, Recipient, RecipientId};
28//! use std::collections::HashMap;
29//! use std::sync::Mutex;
30//!
31//! // Simple DHT implementation for testing
32//! #[derive(Debug)]
33//! struct TestDht {
34//! storage: Mutex<HashMap<[u8; 32], Vec<u8>>>,
35//! }
36//!
37//! impl TestDht {
38//! fn new() -> Self {
39//! Self { storage: Mutex::new(HashMap::new()) }
40//! }
41//! }
42//!
43//! impl saorsa_seal::Dht for TestDht {
44//! fn put(&self, key: &[u8; 32], value: &[u8], _ttl: Option<u64>) -> anyhow::Result<()> {
45//! self.storage.lock().unwrap().insert(*key, value.to_vec());
46//! Ok(())
47//! }
48//!
49//! fn get(&self, key: &[u8; 32]) -> anyhow::Result<Vec<u8>> {
50//! self.storage.lock().unwrap().get(key).cloned()
51//! .ok_or_else(|| anyhow::anyhow!("Key not found"))
52//! }
53//! }
54//!
55//! #[tokio::main]
56//! async fn main() -> anyhow::Result<()> {
57//! let dht = TestDht::new();
58//! let plaintext = b"Hello, Saorsa Network!";
59//!
60//! // Create recipients (5 total, threshold of 3)
61//! let recipients: Vec<Recipient> = (0..5)
62//! .map(|i| Recipient {
63//! id: RecipientId::from_bytes(vec![i; 32]),
64//! public_key: None,
65//! })
66//! .collect();
67//!
68//! // Configure sealing policy
69//! let policy = SealPolicy {
70//! n: 5, t: 3, recipients,
71//! fec: FecParams { data_shares: 3, parity_shares: 2, symbol_size: 1024 },
72//! envelope: EnvelopeKind::PostQuantum,
73//! aad: vec![],
74//! };
75//!
76//! // Seal and recover data
77//! let summary = seal_bytes(plaintext, &policy, &dht).await?;
78//! // ... (recovery process)
79//!
80//! Ok(())
81//! }
82//! ```
83//!
84//! ## Features
85//!
86//! - **`std`** (default): Standard library support
87//! - Post-quantum cryptography is always enabled via saorsa-pqc
88//! - **`telemetry`**: Tracing and metrics support
89
90// DHT trait for storage abstraction
91pub trait Dht {
92 fn put(&self, key: &[u8; 32], value: &[u8], ttl: Option<u64>) -> anyhow::Result<()>;
93 fn get(&self, key: &[u8; 32]) -> anyhow::Result<Vec<u8>>;
94}
95pub use types::*;
96
97// Main API functions
98pub use api::{open_bytes, open_file, seal_bytes, seal_file};
99
100pub mod aead;
101pub mod api;
102pub mod envelope;
103pub mod types;
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use std::collections::HashMap;
109 use std::sync::Mutex;
110
111 #[derive(Debug)]
112 struct TestDht {
113 storage: Mutex<HashMap<[u8; 32], Vec<u8>>>,
114 }
115
116 impl TestDht {
117 fn new() -> Self {
118 Self {
119 storage: Mutex::new(HashMap::new()),
120 }
121 }
122 }
123
124 impl Dht for TestDht {
125 fn put(&self, key: &[u8; 32], value: &[u8], _ttl: Option<u64>) -> anyhow::Result<()> {
126 self.storage.lock().unwrap().insert(*key, value.to_vec());
127 Ok(())
128 }
129
130 fn get(&self, key: &[u8; 32]) -> anyhow::Result<Vec<u8>> {
131 self.storage
132 .lock()
133 .unwrap()
134 .get(key)
135 .cloned()
136 .ok_or_else(|| anyhow::anyhow!("Key not found"))
137 }
138 }
139
140 #[tokio::test]
141 async fn test_basic_seal_and_open() {
142 let dht = TestDht::new();
143 let plaintext = b"Hello, Saorsa Network!";
144
145 let recipients: Vec<Recipient> = (0..5)
146 .map(|i| Recipient {
147 id: RecipientId::from_bytes(vec![i; 32]),
148 public_key: None,
149 })
150 .collect();
151
152 let policy = SealPolicy {
153 n: 5,
154 t: 3,
155 recipients,
156 fec: FecParams {
157 data_shares: 3,
158 parity_shares: 2,
159 symbol_size: 1024,
160 },
161 envelope: EnvelopeKind::PostQuantum,
162 aad: vec![],
163 };
164
165 let summary = seal_bytes(plaintext, &policy, &dht).await.unwrap();
166
167 // Get shares for recovery
168 let sealed_meta_bytes = dht.get(&summary.handle.sealed_meta_key).unwrap();
169 let sealed_meta: types::SealedMetaV1 = serde_cbor::from_slice(&sealed_meta_bytes).unwrap();
170
171 let shares: Vec<ProvidedShare> = sealed_meta
172 .shares
173 .iter()
174 .take(3)
175 .map(|sr| ProvidedShare {
176 index: sr.index,
177 share_bytes: sr.share_plain.clone().unwrap(),
178 recipient_id: sr.recipient.clone(),
179 })
180 .collect();
181
182 let recovered = open_bytes(&summary.handle, &shares, &dht).unwrap();
183 assert_eq!(plaintext, &recovered[..]);
184 }
185}