yzbtdiy

yzbtdiy

github
bilibili

KeePass kdbx4 file decryption

KDBX Decryption Process#

To simplify the decryption steps, no data verification is performed during the decryption process.

  1. Enter the password and compute the SHA256 hash of the password to obtain the password hash value.
  2. Add the key file content to the password hash value and perform SHA256 hashing again. If there is no key file, perform SHA256 hashing on the password hash value again to obtain a new password hash value, which is SHA256(SHA256(password) + keyfile).
  3. Obtain the encryption algorithm KDF-related parameters from the file header. The default is AES-KDF. From the KDF parameters, obtain the KDF's Salt/seed and Rounds.
  4. Use the second SHA256 password hash value, along with the KDF's Salt/seed and Rounds, to perform AES-KDF calculations to obtain the transformed key.
  5. Obtain the Master salt/seed from the file header and perform SHA256 calculations with the transformed key to obtain the final decryption key.
  6. Obtain the Encryption IV/nonce from the file header and use the decryption key to perform AES decryption on the encrypted data.
  7. Decompress the decrypted data using Gzip to obtain the Inner Header and XML content. The password in the XML is encrypted using ChaCha20 by default.
  8. Obtain the Inner encryption key from the Inner Header, perform SHA512 hashing, where the hash string index from 0 to 31 bytes is the ChaCha20 key, and from 32 to 43 is the ChaCha20 encryption nonce.
  9. Decrypt the encrypted string using the ChaCha20 key and nonce to obtain the plaintext password. Since it is a stream cipher, decryption needs to be performed sequentially according to the order of the encrypted string.

Creating a KDBX File#

Use the KeePass client to create a KDBX file, using all default parameters. Open the KDBX file with a hex editor and split the file header as shown in the KeePass documentation KDBX File Format Specification - KeePass.

image-20240822172200397

Hexadecimal Detailed Analysis#

image-20240822113406561

1. Header#

The first 12 bytes of the file are divided into three groups, each group is of type UInt32, occupying four bytes, followed by multiple Fields.

Fields consist of id, value length, and value. The id is 1 byte, the value length is of type Int32, occupying 4 bytes, and the corresponding byte data is extracted as the value based on the value length.

For detailed file format specifications, refer to KDBX File Format Specification - KeePass.

KDBX files use little-endian byte order, and numeric types need to be read from right to left.

Signature1#

image-20240821190624226
image-20240821174503304

Signature1 is a fixed value 0x9AA2D903, of type UInt32, occupying 4 bytes.

Signature2#

image-20240821190749110
image-20240821180053815

Signature2 is a fixed value 0xB54BFB67, of type UInt32, occupying 4 bytes.

Format Version#

image-20240821190950704
image-20240821180207025

Format version is the file format version, of type UInt32, occupying 4 bytes. The current type is 0x00040000, and the current version is 4.

Encryption Algorithm#

image-20240821181812965
image-20240821180719734

0x02 converted to Int32 is 2, id 2 corresponds to Encryption algorithm, indicating the encryption algorithm, of type UUID, length 0x00000010 converted to Int32 is 16, indicating a length of 16 bytes, UUID as a hexadecimal string, value is 31C1F2E6BF714350BE5805216AFC5AFF, corresponding to AES-256 in the above image.

Compression Algorithm#

image-20240821185423228
image-20240821182532355

0x03 converted to Int32 is 3, id 3 corresponds to Compression algorithm, indicating the compression algorithm, of type UInt32, length 0x00000004 converted to Int32 is 4, indicating the value length for the next 4 bytes, hexadecimal 0x00000001 converted to UInt32 is 1, indicating GZip compression is used.

Master Salt/Seed#

image-20240821190432826
image-20240821190323382

0x04 converted to Int32 is 4, id 4 corresponds to Master salt/seed, indicating the encryption salt/seed, of type 32-byte array, length 0x00000020 converted to Int32 is 32, indicating the value length for the next 32 bytes, corresponding byte array is [0xFA, 0xC9, 0x50, 0x39, 0x79, 0x5F, 0x19, 0x83, 0x21, 0x22, 0x8F, 0x24, 0x8F, 0x59, 0x63, 0xD5, 0x30, 0x38, 0x7A, 0x55, 0xD8, 0x08, 0xD5, 0x19, 0xC4, 0xD6, 0xEC, 0xEC, 0xEE, 0xDF, 0xA8, 0x24], which is the salt used for AES encryption.

KDF Parameters#

image-20240821194315863
image-20240821194224498

0x0B converted to Int32 is 11, corresponding to KDF parameters, indicating the parameters for the Key Derivation Function (KDF), length 0x0000005D converted to Int32 is 93, indicating the value consists of the next 93 characters, value type is Variant Dictionary, which can be understood as a special object structure, split into version information and an array of multiple dictionary objects, where each dictionary object consists of value type, name length, name, value length, and value.

image-20240821194643768

The Variant Dictionary can be split as follows, the last byte 0x00 has no practical use.

image-20240822091916730

KDF Format Version#

image-20240822092645747

First is the version information of type UInt16, value is 0x0100, occupying 2 bytes.

KDF UUID#

image-20240822094338216
image-20240822093441124

0x42 indicates []byte type, 0x000005 converted to Int32 is 5, indicating name length of 5 bytes, 0x2455554944 corresponds to ASCII string $UUID, then 0x00000010 converted to Int32 is 16, indicating UUID length of 16 characters, corresponding hexadecimal string is C9D9F39A628A4460BF740D08C18A4FEA, which uses AES-KDF by default.

KDF Rounds#

image-20240822100518464
image-20240822100401677

0x05 indicates UInt64 type, 0x000001 converted to Int32 is 1, indicating name length of 1 byte, 0x52 corresponds to ASCII character R, value length 0x000008 converted to Int32 is 8, indicating Rounds value for the next 8 bytes, 0x00000000000927C0 converted to UInt64 is 600000, indicating the number of iterations is 600000.

KDF Salt/Seed#

image-20240822102413474
image-20240822102318666

0x42 indicates []byte type, 0x000001 converted to Int32 is 1, indicating name length of 1 byte, 0x53 corresponds to ASCII string S, then 0x00000020 converted to Int32 is 32, indicating Salt/Seed length of 32 characters, corresponding byte array is [0x0C, 0x34, 0x88, 0x19, 0x8E, 0x90, 0xA3, 0x65, 0x40, 0xB4, 0x1C, 0x4E, 0xCC, 0x85, 0x5D, 0x11, 0xC3, 0x0A, 0x20, 0xD6, 0xF4, 0xAA, 0x20, 0xE4, 0xEC, 0xF3, 0xCF, 0xF3, 0xD9, 0x81, 0xC5, 0xED], which is also the salt used for KDF encryption.

Encryption IV/Nonce#

image-20240822111052671
image-20240822110900590

0x07 converted to Int32 is 7, id 7 corresponds to Encryption IV/nonce, indicating the initialization vector or random number for the encryption algorithm, length 0x00000010 converted to Int32 is 16, indicating the value consists of the next 16 bytes, the initialization vector is the byte array [0x6C, 0x77, 0x12, 0xF7, 0xE2, 0xD0, 0x2E, 0xAE, 0x63, 0x9D, 0x53, 0x92, 0xD6, 0x03, 0xFD, 0x08].

End of Header#

image-20240822112151756
image-20240822112040258

0x00 converted to Int32 is 0, id 0 corresponds to End of header, indicating the end of the header, length 0x00000004 converted to Int32 is 4, value consists of the next 4 bytes, which is a fixed value [0x0D, 0x0A, 0x0D, 0x0A].

2. SHA-256 Hash of the Header#

image-20240822114126587

The 32 bytes after [0x0D, 0x0A, 0x0D, 0x0A] are the SHA-256 hash value of the header, used to verify the integrity of the header information.

3. HMAC-SHA-256 Hash of the Header#

image-20240822114637960

The 32 bytes after the hash of the header are the HMAC-SHA-256 value of the header, which requires the master key to complete the verification.

4. In HMAC-Protected Block Stream#

Unknown Data#

image-20240822130720931

Unknown part, decryption and verification do not use this part of the data, and the documentation does not provide relevant explanations. Decryption needs to skip this part; otherwise, it will result in an error.

Encrypted Data#

The section until the end of the file is the encrypted part (the last four bytes 0x00000000 need to be removed). After decryption, Gzip compressed data is obtained, and the header of the Gzip compressed content is 0x1F8B.

image-20240823160036633

Gzip Decompress#

After performing Gzip decompression, the Inner Header and XML content are obtained.

image-20240823162455324

Inner Header#

Inner Encryption Algorithm#

image-20240823162909414
image-20240823162938566

0x01 converted to Int32 is 1, id 1 corresponds to Inner encryption algorithm, indicating the internal encryption algorithm, length 0x00000004 converted to Int32 is 4, indicating a value length of 4 bytes, value 0x0000003 converted to Int32 is 3, indicating ChaCha20 encryption is used.

Inner Encryption Key#

image-20240823163118692
image-20240823163628791

0x02 converted to Int32 is 2, id 2 corresponds to Inner encryption key, indicating the internal encryption key, length 0x00000040 indicates a length of 64-byte array, which is [0x68, 0x34, 0xD6, 0x1D, 0xFA, 0x98, 0x64, 0xB1, 0x8A, 0x51, 0x05, 0xAB, 0x26, 0x10, 0x35, 0xC8, 0xB0, 0x22, 0xF5, 0x14, 0x91, 0x0F, 0x47, 0x8C, 0x3D, 0xE7, 0x63, 0x86, 0x9C, 0x87, 0xC1, 0x26, 0xC6, 0xB7, 0xDE, 0x59, 0x77, 0x3B, 0xC6, 0x13, 0xF7, 0x17, 0x6C, 0x05, 0x7E, 0x1C, 0xF3, 0xDC, 0x78, 0x25, 0x64, 0xCA, 0x44, 0x7E, 0xFD, 0xB4, 0x6F, 0xEB, 0x4D, 0xDC, 0xD5, 0x91, 0x7B, 0x5C].

The value here needs to be hashed using SHA512, and then the hash value array index from 0 to 31 is the key, and from 32 to 43 is the nonce.

image-20240823164208028

XML Document#

image-20240823164722691

The password in the XML document contains the Protected="True" attribute, which needs to be Base64 decoded first, and then decrypted using ChaCha20. Since it is a stream cipher, the decryption of the subsequent passwords requires the previous password stream.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.