Cryptography

Cryptography in Algebraic

There are two distinct steps when Algebraic encrypts a file. The first step, password hashing, creates an encryption key from the user-supplied password. The second step, data encryption, encrypts file data using the encryption key.

Password Hashing

Password hashing uses the user-supplied password to derive a longer encryption key.

Password hashing is designed to be a computationally expensive step. The idea is that an adversary, who may attempt to guess the encryption password by brute force (i.e. by trying every possible password combination), will be thwarted by the computationally intensive nature of the password hashing step.

Algebraic uses the Argon2id password hash, from the Argon2 family, designed to resist both side-channel attacks, due to operating partially in a password independent order, and cracking attacks, due to operating partially in a password dependent order.

The latest versions of Algebraic use the following Argon2id parameters.

Parameter Value
Memory 4 GiB
Parallelism = number of logical CPUs
Time 1

The 16-byte random salt for Argon2id for each group of encryption operations is derived from the cryptographically secure RNG functions in package crypto/rand in the Go standard library.

Data Encryption

Algebraic uses XChaCha20-Poly1305 for authenticated encryption of the metadata header and XChaCha20 for streamed, unauthenticated encryption of file data. The implementations use the golang.org/x/crypto module.

Note that file data is not authenticated, only the metadata header is. This means that an adversary with write access to an encrypted file may be able to tamper encrypted file data undetected, which can result in tampered data being decrypted later. You should not use Algebraic if such adversaries are part of your threat model.

For each item encrypted, two 24-byte nonces for the encryption algorithms are randomly generated using the cryptographically secure RNG functions in package crypto/rand in the Go standard library.