XChaCha20-Poly1305 with key ratcheting and key commitment DEM. [cm/encrypted/]'s "/dem/a" equals to "xchapoly-krkc". CEK is 64 bytes long. Data is split on 128 KiB chunks, each of which is encrypted the following way: H = BLAKE2b CK0 = CEK CKi = HKDF-Extract(H, salt="", ikm=CK{i-1}) KEY = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krkc/key") IV = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krkc/iv", len=24) if last chunk { IV[23] |= 0x01 } else { IV[23] &= 0xFE } CIPHERTEXT || TAG = XChaCha20-Poly1305(key=KEY, ad="", nonce=IV, data=chunk) COMMITMENT = BLAKE2b-256(KEY || IV || TAG) CIPHERTEXT || TAG || COMMITMENT Chaining key (CK) advances with every chunk. 256-bit encryption key and randomised 192-bit nonce (initialisation vector) are derived from it. Nonce's lowest bit is set only if this is the last chunk we encrypting. "/payload"'s chunk length equals to 128KiB+16+32 bytes. => https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF => https://www.blake2.net/ BLAKE2b is hashing algorithm => https://datatracker.ietf.org/doc/html/rfc7693.html, RFC 7693, same => https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha, XChaCha20-Poly1305 AEAD => https://datatracker.ietf.org/doc/html/rfc8439.html, RFC 8439