Appendix A. Test vectors
Golden hex fixtures are committed in cryptography and p2p (see below). Live MLS+Signal+ML-KEM+AES vectors with production keys remain a Profile-v1 gate.
A.1 Conformance statement
An implementation conforms to this specification when it:
- Implements all MUST rules in P6.
- Recognizes all PDU types in P4.
- Passes all Published (hex) vectors in this appendix (V1–V7).
- SHOULD pass automated golden tests (commands in A.9).
Profile id for mock cascade vectors: EnkryptedChat-Profile-v0-golden-mock.
Profile id for wire PDU vectors: EnkryptedChat-Profile-v0-golden-wire.
A.2 Minimum vector set
| ID | Path | Status |
|---|---|---|
| V1 | Mock cascade "Hi" (3 layers) | Published (hex) |
| V2 | Profile-order mock cascade (4 layers) | Published (hex) |
| V3 | cascadedPayload JSON shape | Published (structure) |
| V4 | Handshake PDU pair UTF-8 | Published (hex) |
| V5 | MLS-only fallback envelope | Published (hex) |
| V6 | __mls_chunk__ PDU | Published (hex) |
| V7 | Chunk count for 9000 B payload | Published (math) |
| V8 | Live MLS+Signal+ML-KEM+AES round-trip | Deferred — Profile-v1 |
| V9 | protocol-error PDU | Published (hex) |
A.3 Vector V1 — Three-layer mock cascade
Source: golden-vectors.fixtures.js
| Step | Hex |
|---|---|
Plaintext ("Hi") | 4869 |
finalCiphertext (MockCipher1→3) | 4869010203 |
cd cryptography && npm test -- golden-vectors.test.js
A.4 Vector V2 — Four-layer profile-order mock cascade
Simulates layer depth MLS → Signal → ML-KEM → AES using deterministic mock layers (append 0x01…0x04).
| Step | Hex |
|---|---|
| Plaintext | 0a141e28 |
finalCiphertext | 0a141e2801020304 |
Same test file as V1.
A.5 Vector V3 — cascadedPayload JSON shape
Structure normative when wrapping V1/V2 bytes in encryptedMessage:
{
"encrypted": true,
"cascaded": true,
"cascadedPayload": {
"finalCiphertext": [72, 105, 1, 2, 3],
"layerParameters": [{}],
"layers": [{ "algorithm": "MLS", "version": "1.0.0-golden" }],
"originalSize": 2,
"finalSize": 5,
"timestamp": 1717000000000
}
}
A.6 Vector V4 — Handshake PDU pair (UTF-8 hex)
Source: protocol-golden-vectors.fixtures.js
| PDU | JSON | UTF-8 hex |
|---|---|---|
| Request | {"type":"mls-key-package-request"} | 7b2274797065223a226d6c732d6b65792d7061636b6167652d72657175657374227d |
| Response | {"type":"mls-key-package","keyPackage":"golden-fixture-key-package-bytes"} | 7b2274797065223a226d6c732d6b65792d7061636b616765222c226b65795061636b616765223a22676f6c64656e2d666978747572652d6b65792d7061636b6167652d6279746573227d |
Full handshake order: P3.
A.7 Vector V5 — MLS-only fallback envelope (UTF-8 hex)
{"encrypted":true,"envelope":{"groupId":[1,2,3],"epoch":0,"ciphertext":[10,20,30]}}
UTF-8 hex:
7b22656e63727970746564223a747275652c22656e76656c6f7065223a7b2267726f75704964223a5b312c322c335d2c2265706f6368223a302c2263697068657274657874223a5b31302c32302c33305d7d7d
A.8 Vector V6 — __mls_chunk__ PDU (UTF-8 hex)
JSON:
{"type":"__mls_chunk__","messageType":"message","messageId":"golden-msg-0001","chunkIndex":0,"totalChunks":2,"chunk":[1,2,3],"timestamp":1717000000000}
UTF-8 hex:
7b2274797065223a225f5f6d6c735f6368756e6b5f5f222c226d65737361676554797065223a226d657373616765222c226d6573736167654964223a22676f6c64656e2d6d73672d30303031222c226368756e6b496e646578223a302c22746f74616c4368756e6b73223a322c226368756e6b223a5b312c322c335d2c2274696d657374616d70223a313731373030303030303030307d
A.9 Vector V7 — Chunk count (9000 B finalCiphertext)
Per P8 cascade chunk size 8192:
| Input | Expected totalChunks |
|---|---|
| 9000 bytes | 2 |
Verified in protocol-golden-vectors.test.js.
A.11 Vector V9 — protocol-error PDU (UTF-8 hex)
{"type":"protocol-error","code":1,"messageId":"golden-msg-0001"}
UTF-8 hex:
7b2274797065223a2270726f746f636f6c2d6572726f72222c22636f6465223a312c226d6573736167654964223a22676f6c64656e2d6d73672d30303031227d
Codes 1–5 defined in P8.8. Implementation: p2p/src/utils/protocolError.ts.
A.12 Authoritative automated tests
| Repository | Command | Vectors |
|---|---|---|
cryptography | npm test -- golden-vectors.test.js | V1, V2 |
p2p | npm test -- protocol-golden-vectors.test.js | V4, V5, V6, V7, V9 |
p2p | npm test -- protocolError.test.ts | protocol-error helper |
cryptography | npm test -- cascading-cipher-manager.test.js | Layer order (legacy) |
signal-protocol | npm test | X3DH, ratchet, WASM |
p2p | npm test -- MLSProvider | Handshake routing |
Formal models: ProVerif.
A.13 Profile-v1 requirement (V8)
Before EnkryptedChat-Profile-v1, add V8: fixed hex for a full encrypt/decrypt round-trip using live MLS, Signal, ML-KEM, and AES layers with frozen keys in a committed fixture.