These fixed vectors pin the on-disk format. Any independent implementation that decrypts them
to the stated plaintext is reading the container correctly; any change to the format or
cryptography that breaks them is a deliberate, breaking change (bump FormatVersion and
regenerate).
They are exercised by:
- .NET —
tests/.../KnownAnswerVectorTests.csandCrossImplementationTests.cs - Rust → WASM —
samples/pqfe-wasm/tests/vectors.rs
The two implementations validate each other: the Rust core decrypts the .NET-produced vectors, and the .NET library decrypts the Rust-produced vector. CI runs both suites on every change.
All containers are shown as Base64. See FILE-FORMAT.md for the byte layout.
The same bytes are committed as ready-to-use binary artifacts in
test-vectors/ at the repository root, with pinned SHA-256 sums and a
30-second verification walkthrough — no decoding required.
| Field | Value |
|---|---|
| Key source | passphrase |
| KDF | PBKDF2-HMAC-SHA256 |
| Iterations | 100,000 |
| Salt length | 16 bytes |
| Chunk size | 1024 bytes |
| Passphrase (UTF-8) | test-vector-passphrase |
| Expected plaintext | PostQuantum.FileEncryption known-answer vector v2. |
UFFGRQIBAQAAAAQAJo6h8gAWARBX1MFqqxklHk56hMpD/FOOAAGGoAEAAAAyj/fP3REMAehh9VkK47SfhqQqgW68lRjDYDqIhW+b+6ytzaFAGCYaqA5JyaVkf24z17nYMoDST2h5xVdPtgEB23Fj
| Field | Value |
|---|---|
| Key source | passphrase |
| KDF | Argon2id (version 0x13) |
| Memory | 8192 KiB (8 MiB) |
| Iterations (passes) | 1 |
| Parallelism (lanes) | 1 |
| Salt length | 16 bytes |
| Chunk size | 1024 bytes |
| Passphrase (UTF-8) | test-vector-passphrase |
| Expected plaintext | PostQuantum.FileEncryption known-answer vector v2. |
UFFGRQIBAQAAAAQAS7aXNQAbAhCZBPTffR0AgJ7we1bozxQOAAAgAAAAAAEBAQAAADJOzagbj5vUN9WHVWy1t7KN/pG9O5ab04z0IO4xyV5vRMxDN2TsXQGStrNyW5eC77skRpx0WhB0BC6SxsnfnwherIM=
The Argon2id vector matters cross-implementation: the .NET library (Konscious) and the Rust core (RustCrypto
argon2) must produce identical Argon2id output for the same parameters — and they do.
| Field | Value |
|---|---|
| Produced by | samples/pqfe-wasm (browser core) |
| Key source | passphrase |
| KDF | PBKDF2-HMAC-SHA256 |
| Iterations | 600,000 |
| Chunk size | 65536 bytes |
| Passphrase (UTF-8) | cross-impl-passphrase |
| Expected plaintext | Encrypted by the Rust/WASM core, decrypted by .NET. |
UFFGRQIBAQAAAQAAikYbOgAWARDAQkJamtz3O4G2K80C5ZtbAAknwAEAAAAzWyXs57NvJnc4YxIUzCNJW+xE9IyXeQ4Tt5MFvTwMC27G/Dry6A/4bdieeZmpXSTcNsrumLpyzzeTILIOh5eGh+nR9g==
Pins the SIGNATURE-FORMAT.md sidecar: layout, domain-separation
context, and SHA-512 pre-hash. ML-DSA signing is hedged (randomized per FIPS 204), so the
vector is verify-only — implementations must verify it, not reproduce it byte-for-byte.
Exercised by tests/.../SigningKnownAnswerVectorTests.cs.
| Field | Value |
|---|---|
| Algorithm | Ed25519 + ML-DSA-65 hybrid (AlgorithmId 1) |
| Signed message (UTF-8) | PostQuantum.FileEncryption.Signing known-answer vector v1. |
| Public key | Ed25519-pk(32) ‖ ML-DSA-65-pk(1952), Base64 below |
| Signature | 3,379-byte sidecar, Base64 below |
Public key:
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
Signature:
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
Pins the KEY-FILE-FORMAT.md framing: the PQKF magic and version,
the embedded .pqfe v2 passphrase container, and the authenticated KeyType binding. An
implementation reads it correctly when decryption with the passphrase yields
0x01 ‖ ExpectedPrivateKey — and when the same file, with the same passphrase, is
rejected by a signing-key importer (the type byte is inside the authenticated plaintext).
Exercised by tests/.../KeyFileKnownAnswerVectorTests.cs, and cross-validated by the Rust
core (samples/pqfe-wasm/tests/vectors.rs), which decrypts the embedded body as a plain v2
container — proving the framing adds nothing the other implementation needs to know beyond
this document. The key pair was generated solely for this vector and protects nothing.
| Field | Value |
|---|---|
| Framing | PQKF v1 |
| Body | .pqfe v2 passphrase container, Argon2id (8 MiB, 1 pass, 1 lane), 16-byte salt |
| Passphrase (UTF-8) | key-file-vector-passphrase |
| KeyType | 1 (hybrid recipient private key) |
| Expected key bytes | X25519(32) ‖ ML-KEM-dk(2400) = 2,432 bytes, Base64 below |
Key file:
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
Expected private key (PqHybridPrivateKey.Export() bytes):
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
The only vector that pins the hybrid combiner byte-exactly: the KeySource-3 wrap block
layout, the X25519 agreement + ML-KEM-768 decapsulation, the HKDF-SHA256(ss_pq ‖ ss_classical) KEK derivation (HYBRID-COMBINER.md), and the AES-256-GCM
key unwrap. Encryption is randomized (a fresh KEM encapsulation and ephemeral X25519 key per
container), so the vector is decrypt-only — implementations must decrypt it, not reproduce
it. Exercised by tests/.../HybridKnownAnswerVectorTests.cs. The key pair was generated
solely for this vector and protects nothing.
| Field | Value |
|---|---|
| Key source | 3 (hybrid recipient) |
| Recipient private key | X25519(32) ‖ ML-KEM-dk(2400) = 2,432 bytes, Base64 below |
| Expected plaintext (UTF-8) | PostQuantum.FileEncryption hybrid recipient known-answer vector (X25519 + ML-KEM-768). |
Recipient private key (PqHybridPrivateKey.Export() bytes):
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
Container:
UFFGRQIBAwAAAQAAbJ94MQSfAQRApwX6GPuwscQTlP7g05KlVuy/M0lS7//jpMdspyN6UiJyLux73Kx26roy6YKAHnxf/M03kxfMZBIgTKAEWyubzia26L60Z55pMt3vG2zzCSqJ6CwMfcEEAqbg6fyQii8aCByjGata8FTv42bTcA67O98YHiJEiuCwlLUBDaiUiVFtVU51giibidZC/GFbx4Xi+No4qR0wBeXDpCyI9EgJeumXJtpcjcQcxDauG/RzX+Pq1MpxCZw7sID7Dj2wLb6I/wn1/WGiHlwO4PkXf0FB7NH82+YyUDeww0ihS6vQ+JZeGAaULwfWeyb2eXT/OPLdcFr/cXpUMHzyzs4U8a2+C/hC5+GAP6f2R6+cLbNewJyHBhe7i6EOaDnJH+UkWFXl02t9jfM/iy1cAl0nkMICEgB7c7uVEQFkticzFL4/dUMShsbl6P0dKD0LWF8P8CSYnomqDOB7SewKBUTDZk+RsMJCgulK/V2a3Z57NbPbMnE12YKuemkNe68djbRzPQxdII610oFppQhArObbtv43Y64SlBrA13l/d6sTZBU7SxKYllV3B2G7An24ITVGtPZm1F3fSgjlr9UlbFztkR9LAIWJfYmmFsP6dNFDOzscrOtaPOCp0Nzd5j8/PJoPG89E6ozM0WWlRswmq55kKvrsEbplktQ7TxY4hie5IZPQa5q+YNANbxBz/ks5xUtMeEgAlEtDwJhEKlLt8oHTNQD4t/cUDR5iuTG1xECIfmi2g4vT4lZHtKY2Oa/H6KkZa4iJ51RAMVrmx6E2pKK7MJiNH9hR6KavrzpOpUH4ddHgO5vpWqN5uHWB2E2+fyDB+72Jj/mPeaiCfAulwPTv0jTp6Ni5RPhe/n0HK3GoXOB0Y2HFSIPzipxcPByBuXBWEdL0P3CtrAIRPIFgOIo9fxJmfwdBnIPU0SXlgaD4RxAbmbjyhmR0Xw7lihzORWu0U4AK3XKc64TOrwJlgdlPRUkAhQMIoO1VkiQtoC7BiITpSLRU/iLK+sZByy0FOdrah34OrPXXUZ5KJAU8/R11gL7yOKMk8xlg67OAZyw86xIINYDNF6q/xMxTYcqqy9w9/mqN1a7uPOFgcPJOnZZw5pCXLgeikqNWpbucUDqK5KchiU6nQZnFQHg2E7MxSgFayxGehSMGlif/ICXRl9JYX98Ov1RNdzzyaw9Q7XAVga3L6Mdu0XyRLnu2oeZeTV/tm5GR5+ish8Za6nBjOpcK8mdqwbtmQH3J6KUeog6t4uGngbnoCvTSHHj+WN7tL6EVsIHER4H3BT9XP+KIYmnSxzOkbO0RFhBps2dFSoMxFq2w0UKpW8ZcVJie+E/A1fW3SA0OgApV+/PkcmYBaurEsfVbAsaXpgCbxgviSpXyFfbbWZLXeJiWYANCVDeDad6d8MZxXSazLVJZOFf8W0uAlwf6djFmsowQ6MyK06dtkGIR926eeLt/lWIgcRawsIqy/MeOhfuPHtD+JMK3nijSwMmPeLT6JjxZvpxutNnoIaxbkSJv+lRqse1UTYZBKABzw80Tk2sHjgFVKbj6MRv1PnFPxQb/95NbcvvSUxFm+wEAAABWygDtr/evifS8gBJKj/O2k+GKMFzLToZcsXZ3ay6P64UH4p8fcrJix9J/Lbl7oQ3ELgXZFbEC2kBWu9UrJSvUkOAxdfHu9FVHoRuJqKlFwi2QdkP69z9sOAihwG427RV6tZ5O4C5x
Three frames (two full 1 KiB data frames + a final frame), so this vector pins what the
single-chunk vectors cannot: the per-chunk nonce counter (prefix ‖ big-endian counter) and
the per-chunk AAD chaining (header ‖ counter ‖ frameType). An implementation with a broken
counter round-trips its own output happily — but can never decrypt this fixed container.
Exercised by tests/.../KnownAnswerVectorTests.cs (which also verifies that swapping the two
equal-size data frames fails closed) and by the Rust core's tests/vectors.rs.
| Field | Value |
|---|---|
| Key source | passphrase |
| KDF | PBKDF2-HMAC-SHA256, 100,000 iterations |
| Chunk size | 1024 bytes |
| Passphrase (UTF-8) | test-vector-passphrase |
| Expected plaintext | 3,000 bytes; byte i is (i * 31 + 7) & 0xFF |
The container is pinned in both test suites (MultiChunkVector / MULTICHUNK_VECTOR); it is
omitted here for length — the source constants are the normative copies.
Pins the multi-recipient path that Vector 6 (single recipient) cannot: the KeySource-4 body
layout (RecipientCount ‖ (Mode ‖ BlockLength ‖ block)*, FILE-FORMAT.md)
and the block scan that tries, and skips, a non-matching recipient block before reaching the
caller's. The container wraps one content key to three recipients; the pinned private key
is the middle one, so a passing decrypt proves the reader advanced past an earlier block
that was not its own. As with Vector 6, encryption is randomized, so the vector is
decrypt-only. Exercised by tests/.../HybridMultiRecipientKnownAnswerVectorTests.cs and,
cross-implementation, by the Rust core (samples/pqfe-wasm/tests/vectors.rs, HYBRID8_*) —
both pin the identical bytes. The key pairs were generated solely for this vector and protect
nothing.
| Field | Value |
|---|---|
| Key source | 4 (multiple recipients) |
| Recipients | 3 (hybrid, Mode 3); pinned key is recipient #2 of 3 |
| Recipient private key | X25519(32) ‖ ML-KEM-dk(2400) = 2,432 bytes |
| Expected plaintext (UTF-8) | PostQuantum.FileEncryption hybrid known-answer vector v2. |
The 2,432-byte private key and the ~3.6 KiB container are pinned as the normative copies in
the two test suites above (PrivateKeyVector / ContainerVector and HYBRID8_PRIVATE_KEY /
HYBRID8_KS4_VECTOR); they are omitted here for length.
Pins the deprecated inline recipient path byte-exactly: the KeySource-2 wrap layout
(KemId ‖ C ‖ KemCiphertext ‖ WrapNonce ‖ WrapTag ‖ WrappedKey), the ML-KEM-768
decapsulation, the HKDF-SHA256 KEK derivation, and the AES-256-GCM key unwrap — the one
key-establishment path no other vector covered (its randomized round-trip tests self-skip on
hosts without platform ML-KEM). Encryption is randomized, so the vector is decrypt-only.
Generated once on a Linux host with OpenSSL 3.5 (platform ML-KEM) and frozen. The artifacts
are committed files rather than inline Base64, hash-pinned by VectorArtifactTests and
test-vectors/SHA256SUMS; the decrypt is exercised by
tests/.../RecipientKnownAnswerVectorTests.cs wherever PqKeyPair.IsSupported. The key pair
was generated solely for this vector and protects nothing. The Rust core does not implement
this mode, so the vector is not in the cross-implementation manifest.
| Field | Value |
|---|---|
| Key source | 2 (inline ML-KEM-768 recipient, deprecated PQFE001/PQFE002) |
| Container | test-vectors/mlkem-recipient.pqfe, SHA-256 02d3614753172b9eb9690cb35325794fac5e9a67faf5f81377b708725ed00503 |
| Recipient private key | test-vectors/mlkem-recipient.key (PqRecipientPrivateKey.Export(), 2,400 bytes), SHA-256 ff8599053e453e11aad3149736c7094484a39cf8d982ab9ab285956889ca5444 |
| Expected plaintext (UTF-8) | PostQuantum.FileEncryption inline ML-KEM-768 recipient known-answer vector. |
# .NET
dotnet test --filter "FullyQualifiedName~KnownAnswerVector|FullyQualifiedName~CrossImplementation"
# Rust
cd samples/pqfe-wasm && cargo testImplementations must also reject corrupted input, and must accept exactly the inputs the
frozen v2 reader accepts — including its documented leniencies. Both are pinned as a committed,
machine-readable corpus at test-vectors/, indexed by
test-vectors/manifest.json and run in both implementations by
the .NET ConformanceManifestTests and the Rust core's tests/conformance.rs.
Each manifest entry declares the outcome a conforming reader must produce:
reject-format— a structural error (PqFormatException/PqError::Format): bad magic, unsupported version, unknown AEAD or key source, out-of-range chunk size, or an out-of-range PBKDF2 iteration count (range-checked before any KDF work).reject-decryption— an authentication failure (PqDecryptionException/PqError::Decryption): a wrong passphrase, any flipped header/ciphertext/tag byte, or a truncation (dropped tag or any proper prefix). The error type stays consistent across these so the reader is not an oracle.accept— the positive vectors above, plus the lenient vectors that pin the frozen v2 reader corners from CONFORMANCE.md §2.2: a nonzero reservedFlagsbyte, trailing bytes in passphraseKeyParams, trailing bytes after the final frame, and a block past a multi-recipient count. A1.xreader must accept these; they are format-v3 candidates.
The negatives are deterministic single mutations of Vector 1, so any implementer can reproduce
and inspect them. Regenerate the corpus only as part of a deliberate major-version format
revision (PQFE_REGEN_VECTORS=1), never to make a failing test pass.
To God be the glory — 1 Corinthians 10:31.