4709f557da4946768b2d62f0aa6ccbfeb6a9adc5
[claws.git] / doc / src / password_encryption.txt
1 Unless --with-password-encryption=old is active, account passwords are
2 stored encrypted using AES-256-CBC, using following scheme:
3 ----------------------------------------------------------------------
4
5 Encryption/decryption key is either PASSCRYPT_KEY, or user-selected master passphrase.
6
7 We take the digest of the key using SHA-512, which gives us a 64 bytes
8 long hash.
9
10 The first half of the hash is XORed with the second (1st byte with
11 33rd, 2nd with 34th, etc.). This is gives us 32 bytes, which is
12 the exact length required for AES-256-CBC.
13
14 IV for the cipher is filled with random bytes.
15
16
17 Encryption
18 ----------
19 We prepare a buffer 128+blocksize bytes long, with one block of random
20 data at the beginning, followed by the password we want to encrypt,
21 rest is padded with zero bytes.
22
23 We encrypt the buffer.
24
25 We base64-encode the ciphertext, and store it as:
26 "{algorithm}encodedciphertext"
27
28
29 Decryption
30 ----------
31 We strip the "{algorithm}" (after verifying that it matches what we
32 expect) and base64-decode the remaining ciphertext.
33
34 We decrypt the ciphertext.
35
36 We discard the first block, and the rest is a zero-terminated string
37 with our password.
38
39
40 Why the random block at the beginning?
41 --------------------------------------
42 We are taking advantage of property of CBC mode where decryption with
43 a wrong IV results in only first block being garbled. Therefore we
44 prepend a random block to our plaintext before encryption, and discard
45 first block from plaintext after decryption.
46
47
48 Master passphrase
49 -----------------
50 This can be any string user chooses. We store its 64 bytes long key
51 derivation (KD), using PBKDF2 with HMAC-SHA1, and later check correctness
52 of user-entered passphrase by making same KD from it and comparing it
53 to the stored one. Only if the two KDs match, the passphrase is accepted
54 and remembered for session, thus giving access to account or plugin
55 passwords.
56
57 Salt used for PBKDF2 is stored in 'master_passphrase_salt', encoded
58 as base64. It consists of 64 randomly generated bytes.
59
60 Number of rounds for PBKDF2 is stored in hidden preference
61 'master_passphrase_pbkdf2_rounds'.