Conformance vectors
Test vectors an implementation can check itself against. Each file is JSON with a description and one
or more cases. The conformance runner in ../examples/conformance loads and
checks every file here with Node’s crypto.
Deterministic construction vectors
These depend only on byte/string construction rules, not on key material, so they are fully specified in this repository:
aad.json— the additional-authenticated-data layout from SPEC §4:AAD = UTF8(repoId) || 0x1F || int64BE(payloadVersion) || int64BE(keyEpoch). Each case gives the inputs and the expected AAD as lowercase hex.key-binding-message.json— the canonical key-binding message from SPEC §9:utf8(ed25519PublicKey + "|" + x25519PublicKey). Each case gives the inputs and the expected message as a UTF-8 string.
Cryptographic primitive vectors (RFC-anchored)
Each primitive AVP relies on is pinned to a published RFC test vector, so a conformant implementation reproduces a known-good output and cannot drift on the primitive itself:
hkdf.json— HKDF-SHA256 (RFC 5869). Casesrfc5869-tc1(RFC 5869 Appendix A.1) andrfc5869-tc3(Appendix A.3, the zero-length-salt case that exercises the empty-salt → 32 zero bytes rule). Each case givesikmHex/saltHex/infoHex/lengthand the expectedprkHex(extract step) andokmHex(expand step).x25519.json— X25519 ECDH (RFC 7748), raw 32-byte little-endian keys, unhashed shared secret. Casesrfc7748-vec1andrfc7748-vec2are the RFC 7748 §5.2 single-iteration vectors;rfc7748-dhis the RFC 7748 §6.1 Diffie-Hellman example. Note: RFC 7748 prints thevec2input u-coordinate with its most-significant bit set; RFC 7748 §5 requires masking that bit before decoding, and the committed value is already masked so every conformant decoder (whether or not it masks internally) agrees byte-for-byte. Therfc7748-dhkeypairs (Alice = recipient, Bob = ephemeral) are reused bykey-wrap.json, anchoring the wrap composition’s shared secret to a published vector.ed25519.json— Ed25519 sign/verify (RFC 8032), raw 32-byte keys. Casesrfc8032-test2andrfc8032-test3are the RFC 8032 §7.1 vectors. The runner derives the public key from the seed, reproduces the (deterministic) signature byte-for-byte, and verifies it.
Composition vectors (generated, three-way cross-verified)
These exercise the full AVP envelope composition (SPEC §4). They embed fixed keys/IVs so they are reproducible, and their correctness is established by three independent sources agreeing byte-for-byte (see “Three-way verification” below):
payload-aead.json— AES-256-GCM payload encryption with the AVP AAD: 12-byte IV, 128-bit tag appended to the ciphertext,AAD = UTF8(repoId) || 0x1F || int64BE(payloadVersion) || int64BE(keyEpoch). The runner re-encrypts (deterministic given key+iv+aad) and asserts equality with the committed ciphertext, decrypts and asserts plaintext recovery, and asserts that decryption fails when the epoch bound into the AAD is changed (rollback/replay protection).key-wrap.json— the default wrap schemeX25519-HKDF-SHA256-AESGCM-v1:sharedSecret = X25519(ephemeralPriv, recipientPub);KEK = HKDF-SHA256(ikm=sharedSecret, salt=ephemeralPubRaw, info=UTF8("avp/rdk-wrap/v1"), L=32);wrappedCiphertext = AES-256-GCM(KEK, iv, aad=UTF8("avp/rdk-wrap/v1"), plaintext=dataKey)with the 16-byte tag appended. TheWrappedKeyon the wire is{schemeId, ephemeralPublicKey, iv, ciphertext}; the case additionally carriesrecipientPrivateKeyB64(not part of the wire format — only so a checker can unwrap) plus the intermediatesharedSecretHex/kekHexfor cross-reference. The recipient and ephemeral keypairs are the RFC 7748 §6.1 Alice and Bob keypairs, so the shared secret equals the published RFC 7748 §6.1 value. The runner recomputes the shared secret and KEK, re-wraps and asserts equality with the committed ciphertext, and unwraps and asserts data-key recovery.
Three-way verification
The composition vectors are public and must not contain mistakes, so each was confirmed by three independent sources agreeing byte-for-byte before being committed:
- Published RFC test vectors — every primitive carries at least one published anchor: HKDF-SHA256 from RFC 5869 (Test Cases 1 and 3), X25519 from RFC 7748 (§5.2 vectors and the §6.1 DH example), and Ed25519 from RFC 8032 (§7.1 TEST 2 and TEST 3). The composition vectors are anchored to RFC 7748 §6.1 via the wrap keypairs. The Node runner reproduces every published output exactly.
- The reference implementation (Java) — the
lol.trq.altscrypto primitives independently agree with every vector: its HKDF and X25519 reproduce the primitive outputs, it verifies (and reproduces) the Ed25519 signatures, itsPayloadCipherdecrypts the payload-aead vector under the AVP AAD and recovers the plaintext (and rejects a tampered epoch), and itsX25519HkdfAesGcmKeyWrapunwraps the key-wrap vector and recovers the data key. This was verified with a throwaway harness against the library’s compiled primitives. - The Node conformance runner — reproduces every primitive output and round-trips every composition
vector (decrypt/unwrap and assert recovery) with Node’s
crypto; see the runner’sREADME.md.npm testmust pass.
An implementation proves conformance by reproducing the deterministic and RFC-anchored vectors exactly, and by round-tripping the composition vectors (decrypting/unwrapping what a peer encrypted/wrapped, verifying what a peer signed).