Расшифровка базы данных KeePass: пошаговое руководство. Безопасное хранение паролей в KeePass Professional
Tutorial
На днях мне нужно было реализовать расшифровку базы данных KeePass. Меня поразило то, что нет ни одного документа и ни одной статьи с исчерпывающей информацией об алгоритме расшифровки файлов.kdb и.kdbx с учетом всех нюансов. Это и побудило меня написать данную статью.
На данный момент существует 2 версии KeePass:
KeePass 1.x (генерирует файлы.kdb);
KeePass 2.x (генерирует файлы.kdbx).
Структура файла с базой данных KeePass (.kdb, .kdbx) состоит из 3 частей:
Подпись (не зашифрована);
Заголовок (не зашифрован);
Данные (зашифрованы).
Расшифровка базы данных KeePass
Последовательность действий
:
Читаем подпись базы данных.
Читаем заголовок базы данных.
Генерируем мастер-ключ.
Расшифровываем базу данных.
Проверяем целостность данных.
Если файл был сжат, распаковываем его.
Расшифровываем пароли.
Пункты 5, 6 и 7 относятся только к.kdbx файлам
!
Подпись
BaseSignature (4 байта)
Первая подпись одинакова для.kdb и.kdbx файлов. Она говорит о том, что данный файл является базой данных KeePass:
0x9AA2D903
VersionSignature (4 байта)
Bторая подпись указывает на версию KeePass и, следовательно, отличается для.kdb и.kdbx файлов:
Третья подпись есть только у файлов.kdbx и содержит в себе версию файла. Для файлов.kdb данная информация содержится в заголовке базы данных.
Таким образом, в KeePass 1.x длина подписи составляет 8 байт, а в KeePass 2.x - 12 байт
.
Заголовок
После подписи базы данных начинается заголовок.
Заголовок KeePass 1.x
Заголовок.kdb файла состоит из следующий полей:
Flags (4 байта): данное поле говорит о том, какие виды шифрования использовались при создании файла:
0x01 - SHA256;
0x02 - AES256;
0x04 - ARC4;
0x08 - Twofish.
Version (4 байта): версия файла.
Master Seed (16 байт): используется для создания мастер-ключа.
Encryption IV (16 байт): используется для расшифровки данных.
Number of Groups (4 байта): общее количество групп в базе данных.
Number of Entries (4 байта): общее количество записей в базе данных.
Content Hash (32 байта): hash расшифрованных данных.
Transform Seed (32 байта): используется для создания мастер-ключа.
Transform Rounds (4 байта): используется для создания мастер-ключа.
Заголовок KeePass 2.x
В.kdbx файлах каждое поле заголовка состоит из 3 частей:
ID поля (1 байт): возможные значения от 0 до 10.
Длина данных (2 байта).
Данные ([длина данных] байт)
Заголовок.kdbx файла состоит из следующий полей:
ID=0x01 Comment: данное поле может быть представлено в заголовке, но в моей базе данных его не было.
ID=0x02 Cipher ID: UUID, указывающий на используемый метод шифрования (например, для AES 256 UUID = ).
ID=0x03 Compression Flags: ID алгоритма, использующегося для сжатия базы данных:
0x00: None;
0x01: GZip.
ID=0x04 Master Seed: используется для создания мастер-ключа.
ID=0x05 Transform Seed: используется для создания мастер-ключа.
ID=0x06 Transform Rounds: используется для создания мастер-ключа.
ID=0x07 Encryption IV: используется для расшифровки данных.
ID=0x08 Protected Stream Key: используется для расшифровки паролей.
ID=0x09 Stream Start Bytes: первые 32 байта расшифрованной базы данных. Они используются для проверки целостности расшифрованных данных и корректности мастер-ключа. Эти 32 байта рандомно генерируются каждый раз, когда в файле сохраняются изменения.
ID=0x0A Inner Random Stream ID: ID алгоритма, использующегося для расшифровки паролей:
0x00: None;
0x01: ARC4;
0x02: Salsa20.
ID=0x00 End of Header: последнее поле заголовка базы данных, после него начинается сама база данных.
Генерация мастер-ключа
Генерация мастер-ключа происходит в 2 этапа:
Генерация составного ключа;
Генерация мастер-ключа на основе составного ключа.
1. Генерация составного ключа
Для генерации составного ключа используется хэш-алгоритм SHA256. В таблицах ниже представлен псевдокод для генерации составного ключа, исходя из того, какая версия KeePass используется, и какие входные данные необходимы для расшифровки базы данных (только пароль, только файл-ключ или все вместе):
KeePass 1.x
KeePass 2.x
Обращаю внимание на то, что если для расшифровки базы данных необходимо несколько сущностей (например, пароль и файл-ключ), то сначала нужно получить хэш от каждой сущности, а потом соединить их вместе (concat) и взять хэш от объединенной последовательности.
2. Генерация мастер-ключа на основе составного ключа
Нужно зашифровать
составной ключ, полученный выше, с помощью алгоритма AES-256-ECB.
В качестве ключа нужно использовать Transform Seed из заголовка.
Данное шифрование нужно произвести Transform Rounds (из заголовка) раз.
С помощью SHA256 получаем хэш от зашифрованного составного ключа.
Соединяем Master Seed из заголовка с полученным хэшем.
С помощью SHA256 получаем хэш от объединенной последовательности - это и есть наш мастер-ключ!
Псевдокод
void GenerateMasterKey()
{
//шифруем составной ключ TransformRounds раз
for(int i = 0; i < TransformRounds; i++) {
result = encrypt_AES_ECB(TransformSeed, composite_key);
composite_key = result;
}