Test vectors - noiseprotocol/noise_wiki GitHub Wiki

Introduction

This document describes the file format used to represent test vectors for Noise.

The format is JSON compliant, but it is formatted specifically to ease the implementation of alternative parsers. The rationale for this decision was provided by Trevor:

About JSON: I worry about JSON files with large numbers of tests, since I think streaming APIs for JSON are less common than document-based APIs. Also, I worry about someone developing for embedded systems, or smartcards, or IoT or something, who doesn't have JSON tools lying around.

Would it be reasonable to make the format JSON-compatible but more restrictive, to make it easier to consume for dumb streaming parsers, but still allow consumers to use JSON? This would make it harder for producing, but I think the tests will be consumed more than produced. Also, these restrictions could make the tests more human-readable.

A python script is available which pretty prints JSON as outlined below.

Format

{
"vectors": [
{
"name": "free form description of handshake",
"protocol_name": "<any valid handshake pattern name>", -- e.g. Noise_NN_25519_AESGCM_BLAKE2b
"hybrid": "25519|448|NewHope"
"fail": false|true,
"fallback": false|true,
"fallback_pattern": "<any valid handshake pattern name>",
"init_prologue": "hex string",
"init_psks": ["hex string", ...]
"init_static": "hex string",
"init_ephemeral": "hex string",
"init_remote_static": "hex string",
"resp_prologue": "hex string",
"resp_psks": ["hex string", ...]
"resp_static": "hex string",
"resp_ephemeral": "hex string",
"resp_remote_static": "hex string",
"handshake_hash": "hex string",
"messages": [
{
"payload": "hex string",
"ciphertext": "hex string"
}, ...
]
}, ...
]
}

The following keys are optional:

  • name
  • init_* and resp_* (except the prologues)
  • handshake_hash
  • fallback (used for testing Noise Pipes, described below, defaults to false)
  • fallback_pattern
  • hybrid

Optional keys may be null or omitted entirely. The fail key, if omitted, defaults to false. The name key, if omitted, defaults to protocol_name. The init_psks and resp_psks keys default to an empty list if omitted. All other keys are mandatory.

PSKs are applied to the handshake in the same order specified in the vector.

The handshake_hash key specifies the expected handshake hash value for both parties at the end of a successful handshake. If fail is true and the failure occurs on a handshake packet, then the handshake_hash key should be ignored.

The messages array describes a conversation alternating between the initiator and responder, starting with the initiator. No distinction is made between when the handshake begins and when it is complete. For example, if a handshake pattern has three messages in it, the responder will send the first non-handshake Noise message. For one-way patterns the messages simply flow from the initiator to the responder.

Noise Pipes

There are three main scenarios to test for Noise Pipes: XX for a "full handshake", IK with a successful response for an "abbreviated handshake", and IK followed by XXfallback for a "fallback handshake".

The "full handshake" and successful "abbreviated handshake" cases are tested in the same way as before because they are normal XX and IK handshake patterns.

The "fallback handshake" case requires some special handling by the test runner to deal with the transition from IK to XXfallback. This special handling is indicated in the test case by setting fallback to true. The pattern for the test case must be set to IK and init_remote_static must be a different public key than the one corresponding to resp_static, to trigger the fallback (they would normally correspond for a successful IK handshake).

The first message in the messages array is the initial IK handshake message from initiator to responder. The responder fails on this message and triggers fallback. The roles are reversed and the handshake restarts with the pattern set to XXfallback. The init_remote_static value is ignored when the handshake restarts and the init_* and resp_* fields are reversed in meaning.

The initiator's semi-ephemeral public key is carried across from IK to XXfallback. This value does not explicitly appear in the test case as an init_* or resp_* field. It is assumed that the implementation will extract the value from the first IK handshake message and pass it to the XXfallback session.

The second message in the messages array is the initial XXfallback handshake message from the former responder (now the initiator) back to the former initiator (now the responder).

The remaining messages proceed as per a normal handshake followed by data transfer.

If the fallback pattern name is not XXfallback, then the fallback_pattern key can be provided to specify an alternative pattern:

"fallback": true
"fallback_pattern": "XXfallback+hfs"

Hybrid Forward Secrecy

The hybrid key specifies the name of the algorithm to use for Hybrid Forward Secrecy.

Examples