Используемые библиотеки
В MyTetra, для шифрования, используется открытая библиотека RC5-Simple.
https://webhamster.ru/site/page/index/articles/projectcode/157
В Qt-проекте ее файлы просто кладутся в нужную директорию проекта:
/app/src/libraries/crypt/RC5Simple.cpp
/app/src/libraries/crypt/RC5Simple.h
Данная библиотека обеспечивает шифрование по схеме RC5-32/12/16 c CBC-режимом сцепления.
Еще используется реализация алгоритма хеширования Pbkdf2 для хорошего перемешивания бит пароля и сильного замедления перебора. Файлы Pbkdf2Qt.cpp/Pbkdf2Qt.h лежат в том же каталоге.
Установка пароля
Когда происходит шифрование ветки, если до этого пароль еще не устанавливался, происходит следующее:
1. Запрашивается пароль для шифрования и подтверждение этого пароля. Пароль и подтверждение должны совпадать.
2. В каталоге базы знаний, рядом с mytetra.xml имеется файл database.ini, и в нем выставляется параметр:
crypt_mode=1
3. Для того, чтобы в последствии не пытаться расшифровывать данные из базы данных с помощью неправильного пароля, в файле database.ini, заполняются два параметра:
crypt_check_salt
crypt_check_hash
Эти данные могут находиться в открытом виде, и они позволяют только проверить пароль, но не раскрывают сам пароль. Соль crypt_check_salt и хеш crypt_check_hash не используются при формировании ключа шифрования данных, они используется только для проверки пароля.
То есть, когда пользователь в следующих сеансах вводит пароль, то берутся символы пароля и берется соль из crypt_check_salt, на основе этих данных высчитывается хеш и сравнивается с crypt_check_hash. Если эти хеши совпадают, значит пароль введен правильно.
Поэтому, после того как пользователь ввел новый пароль шифрования:
1) Вычисляется 256-битная (т.е. 32 байта) случайная соль (проверочная соль).
2) Вычисляется хеш пароля с солью (проверочный хеш) через алгоритм Pbkdf2. На вход этому алгоритму подаются:
- символы пароля в кодировке UTF8
- 256 бит соли
- количество раундов 1000
- итоговая длинна хеша 160 байт
3) 32 байта соли (256 бит) записывается в параметр crypt_check_salt
4) 160 байт вычисленного Pbkdif2 хеша записывается в параметр crypt_check_hash
Другими словами, в параметрах crypt_check_salt и crypt_check_hash сохраняются такие же данные, которые хранятся в базах данных на WEB-форумах о пользователях и их паролях. Отличие в том, что в данном случае хранится только одна "запись БД" - для пользователя MyTetra. Попадание таких данных в открытый доступ совершенно некритично. Хранение хеша пароля не раскрывает сам пароль. Хранимая в данном месте соль используется только для процедуры проверки правильности ввода пароля, и нигде больше.
Следует обратить внимание, что при формировании этих данных, используемых впоследствии для проверки правильности ввода пароля, библиотека RC5Simple не применяется.
Механизм запоминания пароля
В файле database.ini имеется еще один параметр:
middle_hash_check_data
Для чего он нужен? В MyTetra есть возможность "запомнить пароль", чтобы не вводить пароль при каждом запуске программы. Это небезопасная возможность, и пользователя об этом предупреждают. Данный параметр используется для проверки "запомненного пароля".
Фраза "запомнить пароль" не просто так взята в кавычки. На самом деле, запоминается не пароль, а Pbkdf2 хеш пароля, и запоминается этот хеш в файле конфигурации программы conf.ini, а не в файле конфигурации базы данных database.ini. (Поэтому при синхронизации через открытые хостинги надо синхронизировать только каталог /data, в котором лежат database.ini и mytetra xml, но не каталог выше). Этот хеш пароля записывается в параметр
passwordMiddleHash
файла conf.ini. Кроме того, в этом же файле параметр passwordSaveFlag устанавливается в истину:
passwordSaveFlag=true
Если похитить файл conf.ini у пользователя, который включил опцию "запомнить пароль", то его данные можно будет расшифровать. Единственное что невозможно будет сделать - это узнать сам пароль, потому что хранится не сам пароль а его хеш. Это страхует пользователя от того, что если он использует такой же пароль для других сервисов, то хотя бы доступ к этим сервисам не будет скомпрометирован.
Хеш для параметра passwordMiddleHash высчитывается следующим образом:
- Берутся символы пароля в кодировке UTF8
- Берется стандартная соль в виде байтового представления UTF-8 строки "^1*My2$Tetra3%_4[5]"
- количество раундов 1000
- итоговая длинна хеша 160 байт
Эти данные скармливаются алгоритму Pbkdf2.
Далее в параметр middle_hash_check_data файла database.ini записывается заранее известная строка "This string is used for checking middle hash", зашифрованная с использованием хеша passwordMiddleHash. Схему шифрации см. ниже.
Для использования "запомненного пароля", берется значение хеша passwordMiddleHash из файла conf.ini, на его основе создается ключ шифрования, с помощью него расшифровываются байты из параметра middle_hash_check_data файла database.ini. Если полученная строка совпадает с заранее известной строкой, то значит "запомненный пароль" (а на деле запомненный хеш пароля) правильный. Эта проверка нужна для сохранения консистенции между данными в базе и "запомненным паролем" (т. е. хешем пароля), сохраненном в conf.ini.
Схема шифрования
Шифрация/дешифрация данных происходит с помощью библиотеки RC5Simple. В ней поддерживаются ключи шифрования длинной 128-бит. Для получения ключа шифрования, вышеописанный Pbkdf2 хеш пароля пропускаются через алгоритм MD5.
Библиотека RC5Simple реализует шифрацию отдельных строк и файлов. Данная библиотека обеспечивает наличие в каждом зашифрованном элементе уникального инициализирующего вектора длинной 8 байт. Поэтому нет необходимости отдельно вычислять соль в момент шифрования. На шифрацию передается только ключ шифрования, полученный из пароля, и сами шифруемые данные.
Фомат хранения зашифрованных данных представлен на странице проекта RC5Simple:
https://webhamster.ru/db/data/articles/157/format_3_ru_580.png
Следует обратить внимание, что в файлах конфигурации предусмотрено версионирование, поэтому имеется возможность со временем изменить схему шифрования на более криптостойкую.