This document describes certificate and private key formats that are proposed for use in implementations of Noise.
The certificate format is represented on the wire using Protocol Buffers or "protobufs" for short. The full protocol description is contained in the noise-certificate.proto file in the Noise-C distribution.
The following is an example of a certificate for "Jane Smith" that has been signed by "Trent Peoples". To make things easier, we will use a simplified text syntax for describing the contents of a protobuf message. The data is actually encoded in binary on the wire using the standard Protocol Buffers Encoding.
Here, Jane has declared that her Curve25519 and Curve448 Diffie-Hellman keys will be used in the "foo-chat-user" role. Trent then accepted that role, hashed the certificate data with "BLAKE2b", and added his signature using the "Ed25519" algorithm.
The signature covers the contents of the "subject" and "extra_signed_info" fields, represented in the standard Protocol Buffers Encoding. The encoding MUST be "canonical" in that all integer values, field tag numbers, and field lengths are represented using the minimum number of bytes for the value, and the fields are listed strictly in order of field tag number.
Multiple signature blocks can be included from multiple signers:
Each signature is independent, covering the "subject" information and continuing with the "extra_signed_info" details for the specific signer. In the above example, Mary's signature does not include the details from Trent. The certificate would be equally valid with Mary's signature listed first.
Because the signatures are independent, new signatures can be added to the end of the certificate at any time. Or old signatures can be removed from the certificate at any time. Any remaining signatures will remain valid as they only vouch for Jane's identity, not the identity of the other signers.
This approach also allows certificates to be trimmed when they are sent in Noise packets. If the client is communicating with a server that trusts Trent as a certificate authority, then there is no need to send the signature block for Mary. Certificates may also be trimmed to hide the identity of additional signers from remote parties that do not need to know about those signers.
The format details below are specified in the proto3 language.
The top level of a certificate contains a version number, information about the subject, and any optional signatures:
The version number MUST be 1 for this version of the format.
In all of the definitions here, field tags 1 to 15 are intended for use by this format description (or future versions of it). Field tags 16 and higher are available for private use extensions, although this shouldn't be necessary because the "meta" field described later provides a standard way to add extensions.
Certificate chains are a list of one or more certificates:
The field tag number on the certificates in a chain is deliberately set to 8, which is different than any of the field tags in "Certificate". This allows applications to quickly determine if the supplied data is a single certificate or a certificate chain.
When a chain of certificates is given, the first is assumed to be the subject with the remainder of the certificates intended to provide additional information to verify the subject.
id
- The identity of the subject, formatted as "foo@domain" and encoded in UTF-8. The Id
may look like an e-mail address but it doesn't have to be. It only needs to be unique in the context of the larger Noise protocol.
name
- The name of the subject for the certificate. This string is intended to be human-readable and MUST be encoded in UTF-8. If the name
is not present, id
can be displayed to the human user instead.
Both id
and name
are OPTIONAL. If neither are present, then the subject is identified by their public key fingerprint. This option is provided to protect the identity of anonymous users. A pseudonym could be used instead, but pseudonym use is not required.
role
- The role that the subject's keys are intended to be used for. There are no predefined roles yet and the field can be omitted. The role may be an application name; e.g. "foo-chat", or a sub-role within an application; e.g. "foo-chat-user" and "foo-chat-server".
keys
- List of public keys for the subject.
meta
- Extra meta information about the subject as a list of freeform name/value pairs:
MetaInfo blocks may be used to add extra information that is of interest to an application. For example, "Foo-Nickname" may convey the nickname of a user for the "foo-chat" application. For privacy reasons, any meta information that may identify the user MUST be OPTIONAL. Applications SHOULD use meta names that are obviously unique to that application to avoid conflict with other applications.
The id
and name
fields have the same format and meaning as for subject information blocks. In this case they identify the signer. Both fields can be omitted to hide the identity of the signer.
The signing_key
field specifies the algorithm name and public key that was used to sign the certificate.
The hash_algorithm
indicates the algorithm that was used to hash the subject information and extra_signed_info
. It should be one of BLAKE2s
, BLAKE2b
, SHA256
, or SHA512
. BLAKE2b
or SHA512
is recommended to ensure signature longevity.
The extra_signed_info
field contains information that is signed along with the subject information:
The nonce
is an extra pseudorandom value added by the signer, which ensures that multiple signatures for the same subject from the same signer will be different. The value should be considered opaque. It is recommended that it consist of at least 128 bits of pseudorandom data. This field SHOULD be included. It MAY be omitted for anonymous users to avoid the watermarking problems described under Other issues below. The valid_from
field SHOULD be included in this case to provide a fallback nonce that is different between signatures.
The valid_from
and valid_to
OPTIONAL fields indicate the starting and ending times for the validity of the signature. Note: This is the validity of the signature, not of the certificate. The signer is not saying "this key is valid for this period" but rather "I do not vouch for this certificate outside this time period". The subject information may remain valid for much longer. The format MUST comply with ISO 8601 as profiled in RFC 3339.
The signature
field MUST be the last line in the Signature
block, and contains the actual signature produced with the signing_key
and hash_algorithm
.
If there were any existing Signature
blocks in the certificate to be signed, they are ignored when calculating the hash. The new signature block is inserted at the end of the certificate.
Any strings that are read from a certificate and presented to a human user should be preprocessed to remove or transform control characters or other data that may be problematic for the output device. The security considerations from RFC 3629 should be kept in mind to ensure that all strings are strict UTF-8.
The nonce
value and implementation-specific meta fields could be used to watermark users who otherwise wish to remain anonymous. Once a certificate is signed, the subject will need to import the signature into their key ring. At this point the subject can see if any extra fields were inserted that concern them and reject the signature.
The nonce
field is opaque and non-obvious but highly recommended to deal with duplicate signatures for the same subject key. The nonce
field MAY be omitted by a signer from certificates if they wish to provide some assurance to anonymous users that they have not watermarked the signature. The valid_from
field is used as a fallback nonce for this case.
Anonymous users can choose to reject signatures that include a nonce
. They should also carefully inspect the valid_from
and valid_to
timestamps. Odd date or time values might provide another opportunity to include watermarking bits.
The main protection against this is disclosure. If it was discovered that well-known signing authorities were watermarking certificates, affected users can remove the offending signatures and seek new signers.
Signers may require some kind of proof that the subject is in possession of the relevant key before adding a signature. For Diffie-Hellman keys, the Noise protocol itself provides handshake patterns that can prove key possession.
A hypothetical certificate issuing protocol should check that the static public key for the session matches that in the supplied certificate. This does become more complex if the subject has multiple encryption keys or signing keys. Multiple requests may be necessary to prove ownership of the additional keys.
The private key information is similar to the subject information from the certificate format:
The format of "PrivateKey" and "PrivateKeyInfo" are identical to "SubjectInfo" and "PublicKeyInfo", which may allow applications to share the format handling code between the two use cases if they so wish.
The private key information is encrypted to protect it inside an "EncryptedPrivateKey" wrapper:
For example:
The version
must be 1 for this version of the encrypted private key format.
The algorithm
indicates the cipher, hash, and KDF schemes that are used to protect the private key. Any Noise cipher or hash algorithm supported by the application can be used, although "ChaChaPoly_BLAKE2b_PBKDF2" is recommended for minimum interoperability.
The only KDF algorithm that is defined at present is PBKDF2 from RFC 2898. The salt
and iterations
fields are two of the parameters to PBKDF2 (the other being the passphrase).
Other KDF algorithms may be defined in the future. The salt
and iterations
fields can be repurposed to contain whatever parameters those KDF algorithms require.
As an example, the algorithm identifier "ChaChaPoly_BLAKE2b_PBKDF2" is implemented as follows. PBKDF2 is used with BLAKE2b to generate an encryption key and nonce for ChaChaPoly. The first 32 bytes of the PBKDF2 output are used as the encryption key. The next 8 bytes of the PBKDF2 output are interpreted as a big-endian 64-bit value and used as the nonce. The entirety of the private key details are encrypted in a single request, which limits the size to 65535 bytes including the MAC.
The salt
SHOULD be at least 16 bytes in length, and MAY be longer at the implementation's discretion. The unsigned 32-bit iteration
count should be large enough to make dictionary attacks on the private key file time-consuming on current hardware.
Encrypted private keys can be a hassle for servers and other systems that run unattended. Such systems may need to use a static passphrase, even if only the empty passphrase.
The field tag numbers on "EncryptedPrivateKey" are deliberately different than those for "Certificate" and "CertificateChain" so that an application can easily determine what type of data it is processing. Applications may use this to cross-check that a private key is not accidentally sent over the wire as a certificate.
When displaying a public key to a human user, the public key SHOULD be hashed with SHA256 with the first 16 bytes of the value formatted in hexadecimal, separated by colons. For example:
Fingerprints MAY be calculated with other hash algorithms or MAY include more than 16 bytes. However, SHA256 with truncation is RECOMMENDED to improve interoperability of fingerprints between implementations.