Skip to content

Security: containerscrew/rsecure

Security

SECURITY.md

Security Policy

rsecure is a file encryption CLI built on top of AES-256-GCM. Because it handles sensitive data, the following document describes what it does and does not protect against, and how to responsibly report a vulnerability.

Supported Versions

Only the latest released version receives security fixes. Older versions are unsupported. Check the latest release at https://github.com/containerscrew/rsecure/releases.

Cryptographic Design

File format v3 (current)

Element Value
Cipher AES-256-GCM (256-bit key, 128-bit tag)
Construction STREAM (chunked AEAD) via aes_gcm::aead::stream::EncryptorBE32
Chunk size 131072 bytes (128 KiB), declared per-file in the header
Key derivation HKDF-SHA256(ikm=master_key, salt=random 32 B per file, info="rsecure-v3-aes256gcm-stream") → 32-byte AES-256 subkey
STREAM nonce Fixed all-zero 7-byte salt; uniqueness is provided by the per-file HKDF subkey, with STREAM's 4-byte BE32 counter ensuring uniqueness across chunks within the file
File header RSEC (4 B) + version 0x03 (1 B) + flags (1 B) + chunk_size (u32 LE, 4 B) + HKDF salt (32 B) = 42 bytes; passphrase mode appends Argon2 params (9 B) + Argon2 salt (16 B) for 67 bytes total
Header authenticity The entire on-disk header is passed as AAD on every chunk; any tampering invalidates the first GCM tag and decryption fails before any plaintext is recovered
Master key source Either a 32-byte keyfile (default) or derived once-per-invocation from a passphrase via Argon2id, see below

Master key sources

flags & 0x01 == 0 (keyfile): the master key is the 32-byte keyfile passed via -p. This is the strongest default — the master key has 256 bits of OS-RNG entropy.

flags & 0x01 == 1 (passphrase): the master key is derived via Argon2id(passphrase, argon2_salt, params) where the salt and parameters live in the file header. Default parameters: m_cost = 19456 KiB (~19 MiB), t_cost = 2, p_cost = 1, output length 32 bytes. These defaults can be overridden per-invocation via --argon2-memory, --argon2-time, and --argon2-parallelism; the chosen values are recorded in each file's header so decryption picks them up automatically. Raising the parameters (more memory, more iterations) strengthens the KDF; lowering them below the defaults weakens it and is discouraged. The salt is generated once per invocation, so an entire encrypt batch shares one Argon2 derivation; the decrypter caches by salt to avoid re-running the KDF on subsequent files of the same batch.

Security in passphrase mode is bounded by the entropy of your passphrase. Argon2id raises the cost-per-attempt enough to make weak passphrases significantly harder to brute-force, but a 6-character dictionary word remains weak regardless of the KDF.

Because the AES-256 subkey is unique per file (derived from a fresh 256-bit random salt), the (key, nonce) pair is globally unique across all files even with a fixed STREAM nonce. This eliminates the birthday-bound nonce-collision concern that would otherwise apply to AES-GCM's 96-bit nonce when many files are encrypted under the same master key.

On decrypt, a sanity bound (chunk_size ≤ 16 MiB) rejects pathological headers before any buffer is allocated, so a hostile .enc cannot trigger an unbounded allocation.

File formats v1 and v2 (legacy, decrypt-only)

  • v1 (rsecure ≤ 0.5.0): AES-256-GCM STREAM with a 7-byte random nonce derived directly from the master key, no HKDF, no magic header.
  • v2 (interim, brief release window before v3): RSEC 0x02 header, HKDF-derived subkey, AAD-bound — same scheme as v3 keyfile mode but without the flags byte.

rsecure decrypt reads both transparently; the dispatcher picks the right code path from the magic + version. New encryptions always use v3.

The cryptographic primitives are provided by the aes-gcm, hkdf, and argon2 crates from RustCrypto, widely-used, audited, pure-Rust implementations.

Post-Quantum Considerations

rsecure is being developed with the intent of remaining safe against a large-scale quantum adversary. This is a stated design goal, not a formal certification — the project is small, evolving, and has not undergone independent cryptanalytic review. Read this section for what the intent means in concrete terms and where the honest limits sit.

Primitives and their post-quantum status

Primitive Classical security Post-quantum security Notes
AES-256-GCM 256-bit key ~128-bit (Grover) NIST PQC Category 5; part of NSA CNSA 2.0 symmetric baseline.
HKDF-SHA256 256-bit preimage ~128-bit preimage (Grover) Used for per-file subkey derivation only; not for long-lived signatures.
Argon2id Memory-hard Memory-hard (√ speedup only) Symmetric password KDF; unaffected by Shor. See RFC 9106.

No asymmetric primitives are used anywhere in rsecure. There is no RSA, no elliptic-curve Diffie–Hellman, no ECDSA, and no X25519 — so Shor's algorithm has nothing to break in the current design. This is the single biggest post-quantum risk in tools that rely on public-key primitives for key agreement or signing, and rsecure sidesteps it by construction.

What this does NOT mean

  • No formal PQ certification exists for this implementation. NIST PQC categories apply to the primitives, not to this specific codebase or parameter choices.
  • No post-quantum KEM or signature is included. rsecure does not ship ML-KEM (Kyber) or ML-DSA (Dilithium) today because there is no key-exchange or signing surface in scope. If a future feature ever requires asymmetric crypto (e.g., recipient-based encryption), the intention is to reach for NIST PQC standards rather than pre-quantum primitives.
  • Legacy formats (v1, v2) inherit the parameters of their era. The post-quantum posture applies to files produced by the current v3 format; re-encrypting long-lived archives is recommended.
  • Distributing keys and passphrases still relies on out-of-band channels; the post-quantum properties of those channels are outside rsecure's scope and remain the user's responsibility.
  • Side-channel resistance is best-effort (inherited from aes-gcm) and is not itself a post-quantum property, but is listed here alongside the other honest caveats.

References

  • NSA CNSA 2.0 (2022) — AES-256 and SHA-384+ as post-quantum symmetric baseline.
  • NIST FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), FIPS 205 (SLH-DSA) — standardized post-quantum asymmetric primitives, referenced here for future work only.
  • NIST SP 800-208 — stateful hash-based signatures (not used by rsecure).

Threat Model

What rsecure guarantees

  • Confidentiality of file contents under a chosen-plaintext attacker that does not possess the master key.
  • Integrity & authenticity of each chunk — any tampering will be detected on decrypt (GCM authentication tag).
  • Resistance to chunk reordering or truncation — STREAM binds chunks via a counter and a final-chunk marker.
  • No catastrophic nonce reuse across files — the per-file HKDF subkey makes the (key, nonce) pair globally unique even with a fixed STREAM nonce.
  • Best-effort memory hygiene for secrets. Passphrases, master keys, and derived subkeys are wrapped in zeroize guards and cleared on drop. This is best-effort — Rust does not guarantee freedom from compiler-introduced copies or spilled stack slots, and swap / hibernation / core dumps can still leak secrets outside the process — but it narrows the residual-memory attack surface.
  • Header authenticity (v2 only). Modifying any byte of the on-disk header (magic, version, chunk_size, salt) causes decryption to fail with an auth error on the first chunk, before any plaintext is written. There is no downgrade, rebinding, or wrong-key-via-salt-swap path that produces valid plaintext.
  • Post-quantum design intent (symmetric-only). No RSA, ECDH, ECDSA, or X25519 is used, so Shor's algorithm has nothing to break in the current design. AES-256 and SHA-256 are only reduced to ~128-bit security by Grover. See Post-Quantum Considerations for the honest limits — this is a design goal, not a certification.

What rsecure does NOT guarantee

  • Filename and directory structure are not protected. Only the file contents are encrypted; metadata (paths, sizes, timestamps) remain visible.
  • Key storage is the user's responsibility. A master key file left on disk in plaintext offers no protection against an attacker with filesystem access. Use full-disk encryption, a hardware token, or a password manager for key custody.
  • No forward secrecy / no post-compromise security. If the master key (or passphrase) is compromised, all past and future ciphertext under it is exposed (HKDF subkeys are derived deterministically from the master key and the per-file salt).
  • No authenticated key exchange. Distributing the master key to another party is out of scope; use an out-of-band secure channel (Signal, age, GPG, in person).
  • No plausible deniability. Encrypted files are clearly identifiable as such (.enc extension and structured header).
  • Side-channel resistance is best-effort, inherited from aes-gcm. The crate uses constant-time arithmetic but does not formally guarantee freedom from cache or timing side channels on every target architecture. On CPUs without AES-NI (or equivalent hardware-accelerated AES), software AES is more exposed to cache-timing side channels.
  • Legacy v1 nonce collisions. Files encrypted by rsecure ≤ 0.5.0 used a 7-byte random nonce (56 bits), which approaches the birthday bound around 2²⁸ files (~268M) and crosses NIST's 2⁻³² safety margin around ~6k files. Re-encrypt long-lived v1 archives with the current version to migrate them to v3.
  • Passphrase strength. In passphrase mode, the master key's effective security is bounded by your passphrase's entropy. Argon2id raises the per-attempt cost but cannot rescue a weak passphrase from an offline brute-force attacker who obtains a .enc file. Use a key file for the strongest guarantee, or a long, high-entropy passphrase (e.g., a diceware phrase of 6+ words).

Reporting a Vulnerability

Do not file public issues for security vulnerabilities.

Please report security issues via one of these channels:

  1. GitHub Security Advisories (preferred): open a private advisory at https://github.com/containerscrew/rsecure/security/advisories/new
  2. Email: info@containerscrew.com with the subject prefixed by [rsecure-sec].

Please include:

  • A description of the issue and its impact.
  • A minimal reproduction (file, command, expected vs. actual behavior).
  • Your suggested fix, if any.

You can expect an acknowledgement within 7 days and a status update within 30 days. Coordinated disclosure is preferred; please give us a reasonable window to ship a fix before public disclosure.

There aren't any published security advisories