Skip to content

Encryption

ph0llux edited this page Dec 13, 2024 · 8 revisions

Zff supports several methods to encrypt the dumped data.

Since zff v2, the data of each object can be encrypted with different methods. Each object is encrypted with different encryption keys.
The encryption of object X is completly independend of the encryption of object Y.

If an object is encrypted, an (optional) encryption header is present in the object header.
The encryption header contains (among several other things) the used encryption algorithm. Zff only supports AEAD algorithms.
The encryption header contains also the encryption key in an encrypted form. The key is encrypted with an password based encryption method. The used method and all other needed parameters to decrypt the key (excluding the needed password itself ;) ) are stored in the PBEHeader (which can be found inside the encryption header).
In Zffv3 are three key derivation functions and two encryption schemes supported:

kdf RFC
PBKDF2/SHA256 RFC 8018 Appendix A.2
Scrypt RFC 7914 section 7.1
Argon2id RFC 9106

The reference implementation uses the PKCS#5 PBES2 implementation of the RustCrypto-Team and an implementation from SRU Systems for Argon2id for the password based encryption of the encryption key(s).

One requierment for the correct use of an AEAD is a different nonce for different data by using the same encryption key. The following table shows you, which value is used as nonce for the appropriate data.
Note that the nonces of AES-GCM and ChaCha20Poly1305 are always 96-bit values. Every nonce is encoded in little endian format.

data calculated nonce
chunk data The appropriate chunk number as bytes (64bit value) padded with zeros (to fullfill the 96 bits), in little endian format. E.g. the chunk number is 1454, the appropriate nonce is 1010111000000101000...(filled with zeros to fullfill the 96 bits)
Ed25519 signature of chunk header The appropriate chunk number as bytes (64bit value) padded with zeros (to fullfill the 96 bits) in little endian format, except the second to last bit, which is a 1.
File header The appropriate file number as bytes (64bit value), padded with zeros (to fullfill the 96 bits) , except the third to last bit, which is a 1.
File footer The appropriate file number as bytes (64bit value), padded with zeros (to fullfill the 96 bits) , except the fourth to last bit, which is a 1.
Object header The appropriate object number as bytes (64bit value), padded with zeros (to fullfill the 96 bits) , except the fifth to last bit, which is a 1.
Object footer The appropriate object number as bytes (64bit value), padded with zeros (to fullfill the 96 bits) , except the sixth to last bit, which is a 1.
chunk offset map The appropriate object number as bytes (64bit value), padded with 0x00000001.
chunk size map The appropriate object number as bytes (64bit value), padded with 0x00000011.
chunk flag map The appropriate object number as bytes (64bit value), padded with 0x00000111.
chunk xxhash map The appropriate object number as bytes (64bit value), padded with 0x00001111.
chunk same bytes map The appropriate object number as bytes (64bit value), padded with 0x00011111.
chunk deduplication map The appropriate object number as bytes (64bit value), padded with 0x00111111.
Clone this wiki locally