← vault manual
Afterberry Vault

Embedding Specification

Core vault document — v1.0 — March 2026. Classification: pre-authentication disclosure.

§E1 Overview

This document specifies the complete process by which cryptographic private keys are embedded into The 8 Museum photographs. It is written so that a future accessor — possessing computational capability far beyond the era of authorship — can reverse the process mechanically, without ambiguity, and recover all keys from the canonical photograph set.

The process has five stages: format canonicalisation, key generation, steganographic embedding, integrity sealing, and distribution. Each stage is fully deterministic given the specified inputs. No stage involves randomness that is not derived from documented seeds.

§E2 Format Canonicalisation

The source photographs are captured in HEIC (High Efficiency Image Container, based on HEIF/HEVC), the native format of the capture device. HEIC is a lossy-compressed format with 10-bit per channel colour depth. It is not suitable for steganographic embedding because the compression scheme is complex, poorly standardised across decoders, and unlikely to remain widely implemented over the vault's timeframe.

Each source HEIC is converted to 8-bit PNG (Portable Network Graphics) as a one-time, irreversible canonicalisation step. PNG is losslessly compressed, universally implemented, and specified by a simple, public standard (ISO/IEC 15948, W3C Recommendation) that can be reimplemented from the specification alone. The 10-bit to 8-bit tonal range reduction is an accepted and deliberate trade-off: it produces the standard 8-bit channel values that the embedding algorithm operates on, and that any future extractor will expect.

Source format HEIC (HEIF/HEVC), 10-bit per channel
Canonical format PNG, 8-bit per channel, RGB colour space
Colour space sRGB (IEC 61966-2-1). No ICC profile embedding. No colour management transformation during conversion.
Metadata All EXIF, XMP, and IPTC metadata is stripped during canonicalisation. The PNG contains pixel data only. Metadata is preserved separately in the vault manifest.
Conversion tool ImageMagick convert, invoked as: convert input.heic -depth 8 -strip -colorspace sRGB PNG24:output.png
Provenance hash The SHA-3-512 hash of the original HEIC file is recorded in the vault manifest before conversion, preserving provenance.
After canonicalisation, the HEIC originals are retained as provenance records but are not part of the vault's key infrastructure. Only the canonical PNGs carry embedded keys. Only the canonical PNGs are distributed. Only the canonical PNGs are hashed in the vault manifest.

§E3 Key Generation

The vault uses 8,888 distinct SPHINCS+-256s keypairs (NIST FIPS 205, SLH-DSA). All keypairs are derived deterministically from a single 256-bit master key (MK), ensuring that the full key set can be regenerated from MK alone if the vault manifest is lost.

Signature scheme SPHINCS+-256s (SLH-DSA, NIST FIPS 205)
Security level NIST Level V (256-bit post-quantum)
Private key components SK.seed (32 bytes) + SK.prf (32 bytes) = 64 bytes
Public key components PK.seed (32 bytes) + PK.root (32 bytes) = 64 bytes
Master key (MK) 256-bit value generated from OS entropy. Stored in key material archive (not in vault manifest).
Per-image key derivation seed_i = HKDF-SHA-256(MK, salt=empty, info="afterberry-sphincs-" || i) where i is the 4-byte big-endian image index (1 to 8,888). The 64-byte output is split: first 32 bytes → SK.seed, last 32 bytes → SK.prf.
Public key derivation PK.seed and PK.root are computed from SK.seed and SK.prf per the SPHINCS+-256s key generation algorithm (FIPS 205 §7.1).
Key generation procedure For each image index i from 1 to 8,888: (1) Derive 64 bytes of key material from MK via HKDF-SHA-256 with info string "afterberry-sphincs-" || i. (2) Split into SK.seed (bytes 0–31) and SK.prf (bytes 32–63). (3) Generate the SPHINCS+-256s keypair per FIPS 205 §7.1. (4) Store the public key (PK.seed || PK.root, 64 bytes) in the vault manifest under index i. (5) The private key material (SK.seed || SK.prf, 64 bytes) is the payload to be embedded in photograph i.

§E4 Steganographic Embedding

The embedding algorithm is S-UNIWARD (Spatial UNIversal WAvelet Relative Distortion), operating in the spatial domain on 8-bit RGB pixel values. S-UNIWARD assigns a distortion cost to each possible modification of each pixel channel, then embeds the payload by making the minimum-cost set of changes. The cost function uses a directional filter bank to identify high-texture, high-noise regions where modifications are statistically undetectable.

Algorithm S-UNIWARD (spatial domain)
Reference Holub, V., Fridrich, J., Denemark, T. "Universal Distortion Function for Steganography in an Arbitrary Domain." EURASIP Journal on Information Security, 2014(1).
Wavelet basis Daubechies-8 (db8), three directional subbands: horizontal (LH), vertical (HL), diagonal (HH)
Stabilisation constant σ = 1 (standard S-UNIWARD stabilisation to prevent division by zero in smooth regions)
Colour channels All three (R, G, B). Cost is computed independently per channel. The embedding path interleaves channels by ascending cost across the full image.
Modification ±1 LSB modification per selected sample. Each modification encodes one bit of payload.
Payload size 512 bits (64 bytes) per image
Typical embedding rate ~0.000014 bpp for a 12-megapixel image (4 orders of magnitude below steganalytic detection thresholds)

§E5 Embedding Path Derivation

The embedding path — the specific sequence of pixel locations and colour channels modified during embedding — must be deterministic and reproducible from documented parameters. It is derived as follows:

Master embedding key (MEK) 256-bit value generated from OS entropy. Independent of MK. Stored in key material archive. Published in vault manifest (required for extraction).
Per-image embedding seed eseed_i = HKDF-SHA-256(MEK, salt=empty, info="s-uniward-seed-" || i) where i is the 4-byte big-endian image index.
Seed output 32 bytes, used to initialise a ChaCha20 CSPRNG for the embedding path selection.
Embedding procedure for image i (1) Load the canonical PNG as a 3-dimensional array of 8-bit unsigned integers: height × width × 3 (R, G, B).

(2) Compute the S-UNIWARD cost map. For each pixel (x, y) and each channel c ∈ {R, G, B}, compute the distortion cost ρ(x, y, c) as the reciprocal of the sum of absolute values of the three directional wavelet residuals (LH, HL, HH) at that position, with stabilisation constant σ = 1 added to the denominator: ρ(x, y, c) = 1 / (|r_LH(x,y,c)| + |r_HL(x,y,c)| + |r_HH(x,y,c)| + σ)

(3) Enumerate all candidate positions as triples (x, y, c). Exclude any position where the pixel value is 0 or 255 (boundary values that cannot accommodate ±1 modification in one direction). Sort all remaining positions by ascending cost ρ.

(4) Initialise a ChaCha20 CSPRNG with the per-image embedding seed eseed_i as the key and a zero nonce. Use the CSPRNG to generate a permutation of the lowest-cost 2,048 candidate positions (4× the payload size, providing selection margin). The first 512 positions in the permuted list are the embedding path.

(5) For each of the 512 positions in the embedding path, in order: read the corresponding bit of the 64-byte payload (MSB first, byte 0 bit 7 through byte 63 bit 0). If the payload bit matches the current LSB of the pixel channel value, make no change. If it does not match, modify the pixel channel value by +1 or −1, choosing the direction that results in lower S-UNIWARD distortion (or +1 if equal).

(6) Write the modified image as PNG, preserving all PNG encoding parameters (compression level, filter method) from the canonicalised input. The output PNG is the canonical embedded photograph for index i.
The selection of 2,048 low-cost candidates (step 4) rather than embedding directly into the 512 lowest-cost positions is deliberate. Embedding exclusively into the absolute lowest-cost positions creates a detectable statistical signature (the "always embed at minimum cost" artefact). The CSPRNG-driven selection from a 4× candidate pool introduces controlled randomness while still concentrating modifications in high-distortion-tolerance regions.

§E6 Integrity Sealing

After all 8,888 photographs have been embedded, the full set is sealed with integrity hashes and a signed Merkle tree.

Sealing procedure (1) For each embedded PNG (index 1 to 8,888), compute the SHA-3-512 hash of the complete file (including PNG headers, not just pixel data). Record in the vault manifest as photo_hash[i].

(2) Construct a Merkle tree over the 8,888 hashes. Use SHA-3-256 as the internal hash function. Leaf nodes are SHA-3-256("leaf:" || i || photo_hash[i]). Internal nodes are SHA-3-256("node:" || left || right). Pad the tree to the next power of 2 (16,384) with leaves hashing the empty string.

(3) Sign the Merkle root with Berry's personal Ed25519 signing key. The signature, public key, and Merkle root are published in the vault manifest.

(4) For each image, compute and record a Merkle proof (the sibling hashes needed to verify that image's leaf against the root). These proofs are included in the vault manifest, enabling per-image verification without downloading the full set.

(5) Record the SHA-3-512 hash of the vault manifest itself as the final integrity anchor. Publish this hash independently (in the reconstruction guide, on the afterberry.com website, and in all documentation copies).

§E7 Distribution Protocol

Once sealed, the canonical embedded PNGs are distributed to all storage locations documented in the vault locations manifest. The distribution protocol is:

Distribution rules (1) Transfer files as raw byte streams. Use checksummed transfer protocols (SCP, rsync with checksum verification, S3 PUT with Content-MD5). Verify the SHA-3-512 hash of each file at the destination after transfer.

(2) Never re-encode, resize, resample, rotate, crop, colour-correct, strip metadata from, add metadata to, or in any other way modify the pixel data of a canonical embedded PNG after sealing. Any modification to pixel data, however minor, may destroy the steganographic payload.

(3) Never serve canonical PNGs through any system that performs automatic image processing (CDN image optimisation, thumbnail generation from the embedded file, social media upload, cloud photo library sync). Serve only from raw object storage or static file hosting with no processing pipeline.

(4) Store the vault manifest alongside the photograph set at every storage location. The manifest is required for extraction and must travel with the photographs.

(5) Periodically (at least annually) verify the integrity of stored photographs by spot-checking SHA-3-512 hashes against the vault manifest. Replace any corrupted copies from a verified source.

§E8 Key Material Summary

The complete embedding process depends on exactly two secret values and one semi-public value:

Master key (MK) DESTROYED. 256 bits. Derived all 8,888 SPHINCS+ private keys during the key generation ceremony (see §E10). Existed only in volatile memory on an air-gapped machine for the duration of key derivation. Never written to persistent storage. Never transmitted. Overwritten and destroyed within minutes of creation. Cannot be recovered.

Master embedding key (MEK) PUBLISHED IN VAULT MANIFEST. 256 bits. Derives per-image embedding seeds. Required for both embedding and extraction. Without MEK, the embedding path cannot be reconstructed and payloads cannot be extracted. Published because extraction requires it — and because knowing the embedding path without the photograph originals reveals nothing.

Berry's Ed25519 signing key PUBLIC KEY PUBLISHED. Used to sign the Merkle root. The public key is in the vault manifest. The private signing key is held by Berry and used only for manifest signatures.
The security model: MK derived the private keys and is destroyed. MEK is published. The photographs are public. The vault manifest is public. The reconstruction guide is public. Everything is in the open — the private keys exist only as steganographic payloads inside the photographs themselves, and the AES-256-GCM key that protects the locations manifest has been destroyed. The vault hides in the gap between what is published and what is computable.

§E9 Extraction (Reverse Procedure)

For the complete extraction and reconstruction procedure, see the Reconstruction Guide. Extraction is the exact reverse of §E5: load the canonical PNG, compute the S-UNIWARD cost map, sort all eligible positions by ascending cost, take the 2,048 lowest-cost candidates, derive the per-image embedding seed from MEK, initialise the same ChaCha20 CSPRNG with that seed, apply the same permutation to the 2,048 candidates, and take the first 512 positions from the permuted list. These are the embedding path. Read the LSB of each pixel channel value at these 512 positions, in order, to recover the 64-byte payload. The payload is the SPHINCS+-256s private key (SK.seed || SK.prf) for that image's index.

§E10 Key Lifecycle

The master key (MK) is designed to exist for the shortest possible duration. The following lifecycle ensures that MK never persists beyond the initial key generation session, and that individual private keys are consumed progressively as photographs are completed.

Phase 1 — Key generation ceremony Boot a clean, air-gapped machine from a live operating system (Tails recommended). The machine must never have been and must never be connected to any network. Generate MK from /dev/urandom (32 bytes). Generate MEK from /dev/urandom (32 bytes). Derive all 8,888 SPHINCS+-256s keypairs from MK in a single session. Record all 8,888 public keys to the vault manifest. MK is then overwritten in memory and destroyed. MK's total lifetime is measured in minutes. It is never written to persistent storage, never transmitted, and never displayed beyond the air-gapped session.
Phase 2 — Immediate embedding (existing photographs) In the same session or an immediately subsequent air-gapped session, embed private keys into all existing canonical photographs (those already taken at the time of the ceremony). Each key is embedded per §E4–§E5, verified by test extraction per §E9, and then deleted from the working key set. Photograph indices are assigned chronologically: the earliest photograph receives index 1, and so on.
Phase 3 — Escrow of remaining keys Private keys for photographs not yet taken (indices beyond the current collection) are encrypted with AES-256-GCM using a key derived from a memorised passphrase via Argon2id (memory cost ≥ 1 GiB, time cost ≥ 4 iterations, parallelism = 1). The encrypted key file is stored on a single secure device (encrypted USB drive, air-gapped). This is the only location where unembedded private keys exist.
Phase 4 — Progressive consumption As each new photograph is taken and canonicalised (HEIC → PNG per §E2), the next available private key is retrieved from the encrypted escrow file, embedded into the photograph per §E4–§E5, verified by test extraction, and immediately deleted from the escrow file. The escrow file shrinks by one key with each new photograph. Indices are assigned chronologically: the next photograph taken receives the next sequential index.
Phase 5 — Sealing Upon completion of photograph 8,888: the last private key is embedded, the escrow file is empty and is destroyed. No private key material exists anywhere except within the 8,888 canonical photographs. The vault manifest is finalised, the Merkle tree is computed and signed, and the integrity seal is applied per §E6. The vault is sealed.
Interim risk (Phase 3–4): During the period between the key generation ceremony and photograph 8,888, the escrow file contains private keys for not-yet-taken photographs. These keys, if compromised, could decrypt their corresponding shards — but individual decrypted shards are algebraic noise due to the erasure coding (reconstruction requires 6,000 of 8,888 shards). The interim exposure is therefore limited: even total compromise of the escrow file does not enable archive reconstruction, provided fewer than 6,000 shards are decrypted in combination with shards from already-embedded keys. The escrow file's size decreases daily as keys are consumed, and the risk window closes permanently at photograph 8,888.

§E11 Historical Note — Key Storage Format

During the project's development phase (prior to the adoption of this specification), the master key was stored using a bespoke steganographic encoding: the key material was converted to randomised words and interpolated into a fictitious berry pie recipe. The resulting document — datavault_berrypie.txt — reads as an elaborate, whimsical baking recipe and contains no recognisable cryptographic notation. This format allowed the key to be carried, stored, and transmitted in contexts where a cryptographic key file would attract scrutiny. The encoding algorithm is intentionally not documented here; it was designed to be recoverable by brute force combined with insight by a sufficiently advanced system, but resistant to casual inspection.

The berrypie format is noted for historical completeness and as an illustration of the project's approach to hiding critical material in plain sight. Under this specification, MK does not survive beyond the key generation ceremony and therefore requires no storage format.