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