Selected Functions
While it would be simpler and more robust in the short term to define a fixed set of cryptographic functions, Converge must be able to maintain backwards compatibility to read old data during a transition to new functions. So instead, each data type for each function is tagged to indicate which cryptographic system it is for.
That said, there is currently only one system defined to serve each function.
Sets of cryptographic functions should be defined to minimize redundant functionality, in particular the signature schemes and DAEADs should employ most current hash function defined. If this means re-paramaterizing a signature scheme or DAEAD to minimize code bloat, so be it. The initial set of blake3, schnorr-blake3-ristretto255, and blake3-xchacha8 exemplify this, as the latter two are based on blake3.
Defined Hashes
blake3
Blake3 is an extremely fast cryptographic hash function, based on a merkle tree.
It is secure against length extension attacks and leaf substitution attacks and is safe to use as a PRF.
Converge uses the derive_key
mode and keyed_hash
modes,
to implement the initial domain separation and any necessary subdomain separation.
The output is 32 bytes.
The tag for blake3 is 0.
Defined Signatures
schnorr-blake3-ristretto255
r255b3 is a fast and compact signature scheme based on Schnorr signatures in their original formulation and Ristretto255. It features built-in and required domain separation, and optionally deterministic signatures. The secret key is an integer modulo the order of Ristretto255, while the public key is a member of the Ristretto255 group.
Key rotation is provided for by generating [committed keys] for [self-evident certificates].
The secret and public keys are 32 bytes, and the signatures are 48 bytes.
The tag for secret keys, public keys, and signatures are all 0.
Defined DAEADs
blake3-xchacha8
This is a MAC and Encrypt scheme where the MAC includes the domain, plaintext, associated data, MAC Context, and shared key, and is used as the initialization vector for the encryption. The chosen plaintext attack on MAC and Encrypt is minimized to the extent possible for a deterministic encryption scheme - if any of the inputs change the MAC changes unpredictably, as does the entire ciphertext.
The shared key can be derived from the plaintext with
sk = Blake3(domain, len(pt) | pt | len(data) | data | "Blake3-XChaCha8 Key Derivation" | convergence_domain)
,
where len(x)
is the length of x
in bytes as a 64-bit little endian unsigned integer.
Or it can be derived from a master key with sk = Blake3(domain, master_key)
.
Encryption first proceeds with deriving the initialization vector,
iv = Blake3(domain, len(pt) | pt | len(data) | data | "Blake3-XChaCha8 Nonce Derivation" | sk)[0..24]
.
Note that the initial portion of the hash input is the same, so a key and nonce can be created in a single pass over the plaintext and data.
Then the plaintext is encrypted with the key and iv, ct = iv | XChaCha8(sk, iv, pt)
.
Decryption begins with splitting the first 24 bytes from the ciphertext to get the iv
and ct'
.
The plaintext is then decrypted pt = XChaCha8(sk, iv, ct')
.
Finally, the mac/iv is recalculated
iv' = Blake3(domain, len(pt) | pt | len(data) | data | "Blake3-XChaCha8 Nonce Derivation" | sk)[0..24]
,
and compared to the actual initialization vector iv == iv'
.
If they are equal the plaintext is returned, otherwise an error is returned.
Given the 24 byte nonce, there is approximately a 1 in 2⁶⁵ chance of nonce collision after 2⁶⁴ messages.
The tag for the shared key is 0.