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
//! Pure symmetric read-crypto for the Digstore content contract (paper §11):
//! the per-URN AES-256-GCM-SIV chunk seal + the HKDF content-key derivation.
//!
//! This lives in `dig-capsule-core` so EVERY layer derives keys and seals/opens
//! chunks from ONE implementation: the producer (`dig-capsule-store`), the host
//! serve path, and the browser verifier (`dig-capsule-wasm`). `dig-capsule-crypto`
//! re-exports these (and layers BLS + a typed `TamperError` on top); the wasm
//! read crate depends only on this crate. Previously the wasm crate reproduced
//! this byte-for-byte (policed by a parity test) because `dig-capsule-crypto` pulls
//! `chia-bls → blst` (not wasm-buildable) — a duplication that allowed crypto to
//! skew between layers. Centralizing it here removes that class of bug.
//!
//! `no_std` + `alloc`, wasm-clean: AES-256-GCM-SIV under a FIXED nonce (no RNG —
//! see below) and HKDF-SHA256, neither of which drags in `getrandom` or `blst`.
use crateSecretSalt;
use ;
use ;
use Vec;
use Hkdf;
use ;
/// The Chia BLS AugScheme ciphersuite tag — the SINGLE SOURCE OF TRUTH for the
/// scheme string shared across every BLS layer (CONVENTIONS C8): `dig-capsule-crypto`
/// (native BLS sign/verify) and `dig-capsule-guest` (the wasm verifier) re-export /
/// compare against THIS constant so the ciphersuite can never skew between layers.
/// (#131: previously `dig-capsule-crypto` defined it locally with a NOTE that core
/// should own it; core now exports it and crypto re-exports, closing the
/// one-source-of-truth gap.)
pub const CHIA_BLS_SCHEME: &str = "chia-aug-scheme-bls12381-g2-xmd-sha256-sswu-ro";
/// Fixed HKDF salt domain string for stores (paper §11.1, §11.4).
const HKDF_SALT_DOMAIN: & = b"digstore-hkdf-salt-v1";
/// Fixed HKDF `info` context for the AES-256-GCM content key (paper §11.1).
const HKDF_INFO: & = b"digstore-aes-256-gcm-key-v1";
/// Fixed 12-byte nonce for the misuse-resistant AEAD (RFC 8452, AES-256-GCM-SIV).
///
/// GCM-SIV derives its synthetic IV internally with POLYVAL over key + plaintext,
/// so each distinct plaintext gets an independent IV even under a fixed nonce —
/// reusing a (key, nonce) pair leaks neither a keystream XOR nor the auth key
/// (unlike plain GCM's "forbidden attack"). Holding the nonce fixed keeps
/// encryption deterministic so the ciphertext-committed merkle root is
/// reproducible (the committed root is taken over the ciphertext bytes).
const FIXED_NONCE: = ;
/// Derive the 32-byte AES-256 content key for a resource from its canonical URN.
///
/// `ikm = canonical_urn` bytes. Public stores use `salt = SHA-256(HKDF_SALT_DOMAIN)`.
/// Private stores (paper §11.4) mix the 32-byte secret salt in:
/// `salt = SHA-256(HKDF_SALT_DOMAIN || secret_salt)`. Distinct URNs (and distinct
/// salts) derive distinct keys — the invariant that makes the fixed nonce safe.
/// The salt is borrowed (`Option<&SecretSalt>`, CONVENTIONS C10).
/// Encrypt a chunk with AES-256-GCM-SIV under the per-URN `key`, returning
/// `ciphertext || tag`. Infallible for in-memory plaintext.
/// Decrypt + authenticate a chunk. `Err(())` is a tamper / wrong-key failure;
/// the unit error is deliberate — every caller layers its own typed error on top
/// (`dig-capsule-crypto` → `TamperError`, `dig-capsule-wasm` → `JsError`), so a
/// dedicated error type here would only force a redundant conversion.