Skip to content

Instantly share code, notes, and snippets.

@u1735067
Last active January 23, 2022 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save u1735067/a078613c7336d93441f9c622785eb29f to your computer and use it in GitHub Desktop.
Save u1735067/a078613c7336d93441f9c622785eb29f to your computer and use it in GitHub Desktop.
KeePass kdbx kaitai format
meta:
id: kdbx
file-extension: kdbx
endian: le
license: ISC # https://spdx.org/licenses/ISC.html
doc: |
composite_key = sha256(sha256(password) + composites)
aes = new AES(128, CBC, iv=0x0 *16, key TRANSFORMSEED
transformed_key=sha256(for i in TRANSFORMROUNDS: aes.encrypt(transformed_key)))
master_key=sha256(CONCAT(MASTERSEED,transformed_key))
Kaitai drafty imprementation by Alexandre LEVAVASSEUR <alexandre+oss@13x.fr> (2017, ISC license)
doc-ref: http://keepass.info/help/kb/kdbx_4.html
doc-ref: https://gist.github.com/msmuenchen/9318327
doc-ref: https://max-weller.github.io/kdbx-viewer/kdbx_format.html
doc-ref: https://sourceforge.net/p/keepass/discussion/329220/thread/68aa10f7/
doc-ref: http://keepass.info/help/base/keys.html
doc-ref: https://forum.keepassx.org/viewtopic.php?t=3603
seq:
- id: header
type: header
- id: dynamic_header_entries
type: dynamic_header_entry
repeat: until
repeat-until: _.type == dynamic_header_type::end
- id: payload
type: payload
types:
header:
enums:
version:
0x65: keepass1
0x66: keepass2_prerelease
0x67: keepass2
seq:
- id: primary_identifier
contents: [0x03, 0xD9, 0xA2, 0x9A]
- id: version
type: u1
enum: version
- id: secondary_identifier
contents: [0xFB, 0x4B, 0xB5]
- id: file_version
type: u4
dynamic_header_entry:
enums:
#dynamic_header_type_cipherid_list:
#0x31c1f2e6bf714350be5805216afc5aff: AES256
# [49, 193, 242, 230, 191, 113, 67, 80, 190, 88, 5, 33, 106, 252, 90, 255]: AES256
# [214, 3, 138, 43, 139, 111, 76, 181, 165, 36, 51, 154, 49, 219, 181, 154]: ChaCha20
dynamic_header_type_compression_list:
0: none
1: gzip
dynamic_header_type_inner_random_stream_id_list:
0: none
1: arc4_variant
2: salsa20
3: chacha20
types:
dynamic_header_type_comment:
seq:
- id: content
size: _parent.size
type: str
encoding: ascii # Not sure
dynamic_header_type_cipherid:
seq:
- id: type
size: _parent.size
#enum: dynamic_header_type_cipherid_list
dynamic_header_type_compression:
seq:
- id: type
#size: _parent.size
type: u4 # Dynamic int conversion would be better
enum: dynamic_header_type_compression_list
dynamic_header_type_transform_rounds:
seq:
- id: count
type: u8 # Same
dynamic_header_type_inner_random_stream_id:
seq:
- id: type
type: u4 # Same
enum: dynamic_header_type_inner_random_stream_id_list
dynamic_header_type_kdf_parameters:
seq:
- id: parameters
# size: _parent.size # For the var dict type // but it is not set :(
type: variant_dictionary
seq:
- id: type
type: u1
enum: dynamic_header_type
- id: size
type: u2
if: _root.header.file_version < 0x40000
- id: size
type: u4
if: _root.header.file_version >= 0x40000 # Introduced in 2.35
- id: data
size: size
type:
switch-on: type
cases:
dynamic_header_type::comment: dynamic_header_type_comment
dynamic_header_type::cipher_id: dynamic_header_type_cipherid
dynamic_header_type::compression_flags: dynamic_header_type_compression
dynamic_header_type::transform_rounds: dynamic_header_type_transform_rounds
dynamic_header_type::inner_random_stream_id: dynamic_header_type_inner_random_stream_id
dynamic_header_type::kdf_parameters: dynamic_header_type_kdf_parameters
variant_dictionary:
types:
serialized_items:
types:
serialized_item:
meta:
encoding: UTF-8 # Mainly for serialized_item_type::string, but also for key_name
enums:
serialized_item_type:
0x04: uint32
0x05: uint64
0x08: bool
0x0C: int32
0x0D: int64
0x18: string # (UTF-8, without BOM, without null terminator)
0x42: byte_array
seq:
- id: type
type: u1
enum: serialized_item_type
- id: key_name_len
type: u4
- id: key_name
size: key_name_len
type: str
- id: key_value_len
type: u4
- id: key_value
size: key_value_len
type:
switch-on: type
cases:
serialized_item_type::uint32: u4
serialized_item_type::uint64: u8
serialized_item_type::bool: u1
serialized_item_type::int32: s4
serialized_item_type::int64: s8
serialized_item_type::string: str
seq:
- id: items
repeat: eos
type: serialized_item
seq:
- id: version
type: u2
- id: serialized_items
size: _parent._parent.size-3 # Can't set size on parent > have to use parent.parent
type: serialized_items
- id: terminator
size: 1
contents: [ 0x00 ]
payload:
seq:
- id: data
size-eos: true
enums:
dynamic_header_type:
0: end
1: comment
2: cipher_id
3: compression_flags
4: master_seed
5: transform_seed
6: transform_rounds
7: encryption_iv
8: protected_stream_key
9: stream_start_bytes # bytes from the unencrypted payload
10: inner_random_stream_id
11: kdf_parameters
12: public_custom_data
#
# Alternative parsing for the Variant Dictionnary (setting 0x00 as eod) :
# variant_dictionary:
# seq:
# - id: version
# type: u2
# - id: serialized_items
# type: serialized_item
# repeat: until
# repeat-until: _.type == serialized_item_type::eod
# #- id: terminator
# # size: 1
# # contents: [ 0x00 ]
# serialized_item:
# seq:
# - id: type
# type: u1
# enum: serialized_item_type
# - id: key_name_len
# if: type != serialized_item_type::eod
# type: u4
# - id: key_name
# if: type != serialized_item_type::eod
# size: key_name_len
# type: str
# encoding: UTF-8
# - id: key_value_len
# if: type != serialized_item_type::eod
# type: u4
# - id: key_value
# if: type != serialized_item_type::eod
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment