CREAM header for encrypted streams
──────────────────────────────────────────────────────────────────────
Symmetric encryption is a crypto algorithm where the same key is used to
encrypt _and_ decrypt data. As opposed to asymmetric encryption, where
there are two keys: one to encrypt, and the other to decrypt data.

While this sounds more convenient because there is only one key to
manage, symmetric crypto comes with a complex challenge: sharing the key
with the other party.
Whoever has the key can decipher the message, so extra care should be
taken when sharing it with anyone. There are many ways to securely share
a key, and one of them is to use Key derivation functions, or KDF.

Key Derivation Function (KDF)
-----------------------------

The idea behind this method is that, rather than sharing the actual key,
the other party should be capable of recreating it, based on a secret
value known to both parties (a passphrase for example). There are many
algorithms to choose from for this purpose, but the best solution as of
today (late 2022), is the Argon2[0] algorithm.

Argon2 is well suited for this purpose, because it maximize the cost it
takes to an attacker to recreate the key from a secret, making
brute-force attack a non-viable solution.

The algorithm takes multiple parameters into account:

- Secret - the password to generate a key from)
- Salt - Arbitrary data used to randomize key output
- Memory cost - how much memory is needed to compute the key
- Time cost - how many times to pass over that memory
- Parallelism - how many concurrent threads to use

If you change one of these parameters, the resulting key will be totally
different. This means that all these parameters must be known to both
parties for the encrypted conversation to happen.

While the secret must be kept, well..., secret, hiding the other
parameters is not needed at all. For convenience, they can thus be
shared directly with the ciphertext, so the person decrypting it only
has to know the secret.

CREAM header
------------

This is where the CREAM header shimes in. Its sole purpose is to provide
all these parameters to the decryption side in a compact header, to help
with key derivation.

Version 1.0 of the header is made specifically for Argon2:

 +-------+-------+------+------+----+-----------+----+
 |CREAM\1|VERSION|BLKSIZ|MEMORY|TIME|PARALLELISM|SALT|
 +-------+-------+------+------+----+-----------+----+

Full header size is 40 bytes, and includes all the information needed to
decipher the data appended to it.
For more details, take a look at the cream(5)[1] manual page.

Because it is prepended to the data, the payload (encrypted data) can be
of any size, which allow encrypted streams of any size.

I've implemented this format in the cream[2] utility, as a reference
implementation, as well as in my personal secret manager, safe[3].
--
~wgs

[0]: gopher://z3bra.org/d/notes/argon2.pdf
[1]: gopher://z3bra.org/0/man/cream.5
[2]: gopher://z3bra.org/0/projects/cream.txt
[3]: gopher://z3bra.org/0/projects/safe.txt

20221024.1415