-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathslh_dsa_sidecar.rs
More file actions
91 lines (75 loc) · 3.7 KB
/
Copy pathslh_dsa_sidecar.rs
File metadata and controls
91 lines (75 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Example: Create a Carbonado archive and produce a SLH-DSA (post-quantum)
//! sidecar signature over its Bao hash.
//!
//! This is the intended use of SLH-DSA in Carbonado: signing manifests,
//! catalogs, or important checkpoints as *separate* sidecar files, never
//! inside the per-segment .cXX containers.
//!
//! See AGENTS.md §2.3 for the exact sidecar format and security model.
use carbonado::crypto::{
read_slh_sidecar, slh_dsa_generate_keypair, slh_dsa_sign, slh_dsa_verify, write_slh_sidecar,
};
use carbonado::file::{encode, Header};
use getrandom::getrandom;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// === 1. Create some data and encode it ===
let master_key = {
let mut k = [0u8; 32];
getrandom(&mut k)?;
k
};
let important_data = b"This could be a manifest, a checkpoint, or a critical archive.";
let (encoded, _info) = encode(&master_key, important_data, 15, None)?;
// The high-level encode includes a Header. Parse it to get the authoritative Bao hash
// that represents this archive (this is the value we sign for a sidecar).
let header = Header::try_from(&encoded[..Header::LEN])?;
let bao_hash = header.hash;
println!(
"Created Carbonado archive with Bao hash: {}",
carbonado::utils::encode_bao_hash(&bao_hash)
);
// === 2. Generate a SLH-DSA keypair (post-quantum) ===
let mut entropy = [0u8; 128];
getrandom(&mut entropy)?;
let keypair = slh_dsa_generate_keypair(&entropy)?;
println!("Generated SLH-DSA keypair (pk = 32 bytes, sk = 64 bytes)");
// === 3. Sign the Bao hash (or a higher-level structure containing it) ===
// The Bao hash (and thus the signature) corresponds to the specific Format combination
// used for this segment. With 16 possible combinations, the hash is multi-dimensional:
// it names a particular (data + processing pipeline) result. See AGENTS.md §2.3.
// For a real sidecar you would typically sign a canonical manifest that
// includes the hash, timestamp, description, etc.
let message_to_sign = bao_hash.as_bytes();
let signature = slh_dsa_sign(&keypair.secret_key, message_to_sign)?;
println!(
"Produced SLH-DSA signature ({} bytes)",
signature.bytes.len()
);
// === 4. Persist the sidecar (SLH1 magic + 7856-byte signature) ===
let sidecar_path =
std::env::temp_dir().join(format!("carbonado-slh-example-{}.slh", std::process::id()));
write_slh_sidecar(&sidecar_path, &signature.bytes)?;
let sidecar_sig = read_slh_sidecar(&sidecar_path)?;
assert_eq!(sidecar_sig, signature.bytes);
println!(
"Wrote SLH-DSA sidecar to {} ({} bytes on disk)",
sidecar_path.display(),
4 + signature.bytes.len()
);
// Production naming: <bao-hash-hex>.c15.slh
// The 32-byte SLH-DSA public key lives in Header.slh_public_key; the sidecar
// carries only the signature over the Bao hash (or a higher-level manifest).
// === 5. Verification (done by anyone who has the public key) ===
let valid = slh_dsa_verify(&keypair.public_key, message_to_sign, &signature)?;
println!("Signature verification result: {}", valid);
assert!(valid);
// Tamper test
let mut tampered = message_to_sign.to_vec();
tampered[0] ^= 0x01;
let still_valid = slh_dsa_verify(&keypair.public_key, &tampered, &signature)?;
println!("Tampered message verification result: {}", still_valid);
assert!(!still_valid);
println!("\nSLH-DSA sidecar signing example completed successfully.");
println!("Remember: SLH-DSA public key is stored in the Carbonado Header; only the signature is handled in the sidecar. Never embed signatures inside the container.");
Ok(())
}