Repository navigation
Cryptography V14
This page describes the cryptographic construction implemented by the active server package engine.
V14 is a layered construction. The password and pattern do not directly become the long-lived file encryption key.
| Purpose | Primitive |
|---|---|
| Password derivation | Argon2id13 via libsodium |
| Pattern derivation | Argon2id13 via libsodium |
| Credential combination | HKDF-SHA-256 |
| Root key size | 256 bits |
| Key wrapping | XChaCha20-Poly1305-IETF |
| Manifest encryption | XChaCha20-Poly1305-IETF |
| Filename encryption | XChaCha20-Poly1305-IETF |
| File streaming | secretstream_xchacha20poly1305 |
| Header binding | SHA-256 over canonical JSON |
| Blob integrity | SHA-256 |
| Package Merkle tree | SHA-256 |
| Release signatures | Ed25519 |
The exact profile is stored in header.json and is validated against the implementation's canonical V14 descriptor.
Every package begins with:
rootKey = random 32-byte value
The builder generates this value independently of the user's password and pattern.
This is important because a credential change does not conceptually require re-encrypting every file: the credential slot is the layer that protects the package root key.
V14 generates a 32-byte random package salt.
The salt is not a secret. It is stored in header.json and is part of the canonical header core that feeds the header binding.
The password and pattern are processed independently through Argon2id13 using separate purpose-derived salts.
Conceptually:
passwordKey = Argon2id13(password, purposeSalt(salt, "password"))
patternKey = Argon2id13(pattern, purposeSalt(salt, "pattern"))
Both derivations produce 32-byte values under the V14 profile.
The two values are concatenated and combined through HKDF-SHA-256:
credentialWrapKey = HKDF-SHA-256(
IKM = passwordKey || patternKey,
info = "SecurePackage|V14|credential-wrap",
salt = packageSalt
)
The intermediate derived values are explicitly zeroized after use where the runtime permits it.
The package binds its cryptographic profile and identity before key-slot operations begin.
The header core contains:
- format
- version
- schema
- package ID
- creation timestamp
- package salt
- cryptographic profile
The project serializes this structure with deterministic CanonicalJson ordering and hashes it with SHA-256:
headerBinding = SHA-256(CanonicalJSON(headerCore))
The resulting 64-character hexadecimal digest is stored in header.json.
This binding is then included in associated data for important authenticated operations.
The credential wrapping key does not encrypt files directly. Instead it wraps the random package root key using authenticated XChaCha20-Poly1305.
Conceptually:
credentialWrapKey
|
+---- AEAD unwrap ----> packageRootKey
The associated data includes the package ID and header binding, preventing the wrapped key from being transplanted into another package context without authentication failure.
When enabled, the builder generates another random 32-byte secret.
recoveryKey = random 32-byte value
The same package root key is then independently wrapped under that recovery key.
The recovery slot is authenticated separately and uses distinct associated data:
SecurePackage|V14|slot|recovery|<package-id>|<header-binding>
This means the recovery credential is not derived from the user's password or pattern.
Once the package root key is unlocked, V14 derives dedicated subkeys:
manifestKey = HKDF(rootKey, purpose="manifest", context=packageId)
filenameKey = HKDF(rootKey, purpose="filename", context=packageId)
fileRootKey = HKDF(rootKey, purpose="files", context=packageId)
A file key is then derived from the file root and the 128-bit file record identifier:
fileKey = HKDF(fileRootKey, purpose="file", context="id:<file-id>")
The goal is key separation: unrelated operations do not share the same raw encryption key.
The manifest stores encrypted names rather than plaintext names.
A filename is sealed with XChaCha20-Poly1305 and associated data containing:
SecurePackage|V14|name|<package-id>|<header-binding>|<node-id>
Thus the encrypted name is bound not only to the key, but also to its package and manifest node identity.
The plaintext manifest is canonicalized and encrypted with manifestKey.
Associated data:
SecurePackage|V14|manifest|<package-id>|<header-binding>
The manifest therefore cannot be silently moved between packages or altered without authentication failure.
Each file is encrypted using libsodium's authenticated secretstream construction.
The V14 stream has a small format prefix:
SPK14STR
followed by the libsodium stream header and length-delimited authenticated ciphertext records.
The default builder chunk size is 4 MiB, with accepted stream configuration bounded between 64 KiB and 8 MiB.
Chunk associated data is:
SecurePackage|V14|file|<package-id>|<header-binding>|<file-id>
plus per-chunk context containing the chunk index and expected plaintext size.
The final record must carry the final secretstream tag. The reader also requires the exact expected plaintext length and rejects trailing data.
V14 does not treat encryption and integrity as separate afterthoughts. The AEAD and secretstream operations authenticate their inputs and associated context.
This means an attacker who changes ciphertext, authentication tags, or bound metadata should trigger a failure rather than producing silently modified plaintext.
The strength of a cryptographic construction is not a substitute for independent review. V14 is explicitly documented as a high-assurance engineering baseline, not as a certification or proof that the implementation has no vulnerabilities.
The project therefore combines cryptographic composition with adversarial tests, parser limits, restore safety, release verification, and a documented threat model.
Secure Package V14 · SECURE-PKG-V14 · Version 14.1.0 · MIT License · Author: ElmanCod110
This Wiki describes the implementation currently documented by the repository. Security-sensitive behavior should be verified against the active source tree before production deployment.
Start
V14 Engine
Security
Integration
Operations
- Storage and Data Lifecycle
- Deployment
- Testing and Validation
- Release and Supply Chain
- Migration V13 to V14
Contributing