Noise-C
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
Certificate and private key format

Table of Contents

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.

Certificate format examples

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.

Certificate {
version: 1
subject: SubjectInfo {
id: "jane.smith@example.com"
name: "Jane Smith"
role: "foo-chat-user"
keys: [
PublicKeyInfo {
algorithm: "25519"
key: "0xf14a2dedf6e1dd879a3af47900eedf17ae56868a7849a370ca732a571ef19e0f"
}
PublicKeyInfo {
algorithm: "448"
key: "0xd414a46bed6231540306818bdab08d8b06a28d98d0bfca47bcea1faf1aca78d8aabc7d7c2073779bd84cf0950ae10247975266267eebb1c8"
}
]
}
signatures: [
Signature {
id: "tpeoples@example.org"
name: "Trent Peoples"
signing_key: PublicKeyInfo {
algorithm: "Ed25519"
key: "0x0fdde4a7a7cc91ec509a74bd5f2369ac768a14bb6388ceb2e1710a4b85bfe001"
}
hash_algorithm: "BLAKE2b"
extra_signed_info: ExtraSignedInfo {
nonce: "0xa2bf177b31bd60ee0e8e00097d88e48e"
valid_from: "2016-03-15T00:00:00Z"
valid_to: "2026-03-15T23:59:59Z"
}
signature: "0x40fa37936793009750ca45e9ef1eb246eaaded93ddd356e7120e0dc171cfa51ff26b7d7a95ba9498d717bff6b9e5d5eeb0a4bbdbf7bcd8c5c4b617da36a68ed9"
}
]
}

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:

signatures: [
Signature {
id: "tpeoples@example.org"
name: "Trent Peoples"
signing_key: PublicKeyInfo {
algorithm: "Ed25519"
key: "0x0fdde4a7a7cc91ec509a74bd5f2369ac768a14bb6388ceb2e1710a4b85bfe001"
}
hash_algorithm: "BLAKE2b"
extra_signed_info: ExtraSignedInfo {
nonce: "0xa2bf177b31bd60ee0e8e00097d88e48e"
valid_from: "2016-03-15T00:00:00Z"
valid_to: "2026-03-15T23:59:59Z"
}
signature: "0x40fa37936793009750ca45e9ef1eb246eaaded93ddd356e7120e0dc171cfa51ff26b7d7a95ba9498d717bff6b9e5d5eeb0a4bbdbf7bcd8c5c4b617da36a68ed9"
}
Signature {
id: "mary.sue@example.com"
name: "Mary Sue"
signing_key: PublicKeyInfo {
algorithm: "Ed25519"
key: "0x8e15998d97f9b43150f05d1b895f5272a2ff1453dbf40ee4ea90df81147db5c3"
}
hash_algorithm: "SHA512"
extra_signed_info: ExtraSignedInfo {
nonce: "0x024e95d2a060df2be5e1fbdfe8e31c58"
valid_from: "2015-05-17T00:00:00Z"
valid_to: "2025-05-17T23:59:59Z"
}
signature: "0x833243ed18ac609880446c1ea147f6322db98ef9d2eaba30ece46bf7cabe50cd822fbe369f4c9c6bd8a5a5f400fff732f1a29c4113e12cb23138733ca880126d"
}
]

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.

Note
Signatures provide additional information that may help bind a key to an identity for specific use cases, but signatures are not necessary for secure communication to occur. Protocols should keep this in mind when using Noise certificates. The lack of a signature does not imply that the user is untrustworthy. It only implies that the user has not found anyone yet who they trust to sign their certificate. Other strategies such as "Trust On First Use" can be used to manage certificates that lack signatures.

Certificate format details

The format details below are specified in the proto3 language.

Top level of certificates and certificate chains

The top level of a certificate contains a version number, information about the subject, and any optional signatures:

message Certificate {
reserved 4 to 15;
uint32 version = 1;
SubjectInfo subject = 2;
repeated Signature signatures = 3;
}

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:

message CertificateChain {
reserved 1 to 7, 9 to 15;
repeated Certificate certs = 8;
}

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.

Subject information

message SubjectInfo {
reserved 6 to 15;
string id = 1;
string name = 2;
string role = 3;
repeated PublicKeyInfo keys = 4;
repeated MetaInfo meta = 5;
}

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.

message PublicKeyInfo {
reserved 3 to 15;
string algorithm = 1; // "25519", "448", "Ed25519", etc.
bytes key = 2; // Format depends upon the algorithm.
}

meta - Extra meta information about the subject as a list of freeform name/value pairs:

message MetaInfo {
reserved 3 to 15;
string name = 1;
string value = 2;
}

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.

Signature blocks

message Signature {
reserved 6 to 14;
string id = 1;
string name = 2;
PublicKeyInfo signing_key = 3;
string hash_algorithm = 4;
ExtraSignedInfo extra_signed_info = 5;
bytes signature = 15;
}

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:

message ExtraSignedInfo {
reserved 5 to 15;
bytes nonce = 1;
string valid_from = 2; // ISO 8601 format timestamp.
string valid_to = 3; // ISO 8601 format timestamp.
repeated MetaInfo meta = 4;
}

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.

Other issues

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.

Encrypted private key format

The private key information is similar to the subject information from the certificate format:

message PrivateKey {
reserved 6 to 15;
string id = 1;
string name = 2;
string role = 3;
repeated PrivateKeyInfo keys = 4;
repeated MetaInfo meta = 5;
}
message PrivateKeyInfo {
reserved 3 to 15;
string algorithm = 1; // "25519", "448", "Ed25519", etc.
bytes key = 2; // Format depends upon the algorithm.
}

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:

message EncryptedPrivateKey {
reserved 1 to 9, 14;
uint32 version = 10; // 1 for this version of the format.
string algorithm = 11; // e.g. "ChaChaPoly_BLAKE2b_PBKDF2".
bytes salt = 12; // Salt value for input to the KDF.
uint32 iterations = 13; // Iteration count for the KDF.
bytes encrypted_data = 15; // Encrypted version of PrivateKey.
}

For example:

EncryptedPrivateKey {
version: 1
algorithm: "ChaChaPoly_BLAKE2b_PBKDF2"
salt: "0x1621bb322ca96658eb6172d01031845f"
iterations: 50000
encrypted_data: "0x..."
}

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.

Note
The nonce value 2^64 - 1 (0xFFFFFFFFFFFFFFFF) is reserved by revision 30 of the Noise specification. If the PBKDF2 hashing process generates such a nonce, then the implementation should generate a new salt and hash the passphrase again. This situation is highly unlikely.

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.

Public key fingerprints

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:

34:da:01:7b:07:e1:a0:0d:64:14:be:e9:af:cf:db:7b

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.