-
Notifications
You must be signed in to change notification settings - Fork 14
Recovery codes
Recovery codes encode a stored password in such a way that it can be printed safely. The password is encrypted and can only be extracted if the password protecting the recovery code (typically user’s main password) is known.
Note: This recovery code format was used by PfP 2.x. Starting with PfP 3.0, V2 recovery codes are used.
The raw data of a stored password consists of the following fields:
Field | Size in bytes | Value |
---|---|---|
version | 1 | 1 |
salt | 16 | Salt used to derive the encryption key from the master password |
iv | 12 | Random initialization vector for encryption |
ciphertext | Encrypted password |
Password is padded with NUL characters before encryption to ensure that the size of binary data is a multiple of 14 bytes. With AES-GCM the size of ciphertext always increases by 16 bytes (tag size) compared to plaintext size, so shorter passwords will be NUL-padded towards 11 characters (total data size 56 bytes) whereas longer ones will be NUL-padded towards 25 characters (total data size 70 bytes).
For the human-readable representation, the binary data is split up into blocks of 14 bytes. For each block a Pearson hash is generated to detect input errors, single typos are guaranteed to be detected. This algorithm requires a substitution table which is built as follows:
for i from 0 to 255
T[i] = (i + 379) * 467 % 256
The hashing function is always applied to 15 bytes of data. Here the first byte is the zero-based block index for regular blocks and 255 - block index
for the last block. The other 14 bytes are the actual block contents. The result are 15 bytes where the first 14 bytes are the block contents and the last byte is the calculated hash value.
Finally, these 15 bytes are encoded as 24 base32 characters. The base32 alphabet used here is ABCDEFGHJKLMNPQRSTUVWXYZ23456789
, some characters have been removed to avoid ambiguities when the recovery code is printed out (1 vs. I, 0 vs. O). These 24 characters form a row, with separators added for better readability:
ABCD-EFGH-JKLM:NPQR-STUV-WXYZ
Typically, a recovery code will consist of 4 or 5 such rows.