Так получилось, что я очень люблю использовать SQLite СУБД.  Программируя на ассемблере, я иногда нуждаюсь в полноценной СУБД. Мои программы редко превышают в размере несколько сотен килобайт. Понятно, что использовать с ним СУБД в несколько сотен мегабайт по меньшей мере просто смешно, а в конце концов, очень неудобно – сразу возрастают требования к оборудованию и сложности установки и настройки, а в итоге уменьшается надежность всей системы. SQLite совершенно другое дело. Во-первых, она маленькая – всего несколько сот килобайт, прекрасное дополнение к компактным программам на ассемблере. Во-вторых, это ультра-надежная система хранения данных. Никаких специальных установок и настроек ей не нужно. Ну и насчет быстродействия – не из последних.  К примеру, я использовал SQLite в моем движке форума AsmBB о котором уже писал на Хабре. (Кстати, после этого он так и не упал). С того времени проект медленно, но уверенно развивается. Появились новые функции, повысились безопасность и быстродействие.  И вот однажды я задумался как повысить и так неплохую безопасность проекта. И сразу подумал, что неплохо было бы сделать шифрование БД форума. Ведь если даже база и утечёт, то доступ к личным данным пользователей никто не получит. Быстрый поиск по Интернету показал, что есть несколько расширений SQLite для шифрования БД. К сожалению, официальное расширение SEE несвободно и вообще продается за деньги. Но, конечно, свято место пусто не бывает и я сразу наткнулся на расширение SQLeet. И в нем мне понравилось буквально все.  SQLeet использует алгоритм ChaCha20 для шифрования БД. Ключ шифрования вычисляется через PBKDF2-HMAC-SHA256, используя 16-байтовую соль и 12345 итераций хеширования. Для аутентификации используется Poly1305. И SQLeet и SQLite распространяются на условиях общественного достояния (public domain). Это удобно, так как не увеличивает лицензионный хаос в проекте. Еще SQLeet очень компактный. Весь код занимает только около полутора тысяч строк на C и не имеет внешних зависимостей.  Проект активно поддерживается и автор оперативно отвечает на вопросы и исправляет баги, если такие найдутся. SQLeet распространяется тем же самым образом, как и SQLite – в форме единственного исходного файла на C, который можно просто скомпилировать тем же самым образом как компилируется и SQLite.  К тому же, так как расширение никак не меняет код SQLite, то обновления основной СУБД можно делать очень просто – через замены файла sqlite3.c и пересоздание объединенного исходника. Так как в AsmBB я использую не совсем стандартную компиляцию (SQLite в AsmBB компилируется через MUSL libc), а я не являюсь C программистом, то для меня простота компиляции очень важна. Вот, например, баш код, который я использую, чтобы скачать последнюю версию SQLeet и создать и скомпоновать исходник: В результате получается файл sqlite3.c который можно вставить там, где раньше вставлялся оригинальный файл SQLite и использовать тем же образом. Использование расширения тоже никак не отличается от использования SQLite. Разница только в том, что если БД зашифрована, то сразу после открытия надо вызвать функцию sqlite3_key(), в которой указать пароль шифрования. Ну или даже лучше, просто исполнить SQL pragma key='%пароль%'. (Это лучше потому что API интерфейс к SQLite не меняется и
всегда можно заменить SQLeet на SQLite и обратно). Начальное шифрование БД, а также замена пароля, происходит через функцию sqlite3_rekey() или pragma командой pragma rekey='%NEW_PASSWORD%'.  И вот здесь у меня возник такой вопрос. Откуда вообще брать пароль? Ведь если пароль сохраняется на сервере в каком-нибудь файле, то потенциальный хакер сможет прочесть его.  Поэтому я решил сделать по-другому. Дело в том, что AsmBB является долгоживущим FastCGI приложением. Однажды запущенный на сервере, он работает месяцы и даже годы без необходимости в перезагрузке. А раз так, то пароль просто может ввести администратор через веб-интерфейс сразу после запуска AsmBB. Таким образом, пароль существует только в RAM и только во время исполнения POST-запроса во время запуска приложения. (Конечно, не надо забывать затирать нулями всю память, в которой пароль существовал во время исполнения POST-запроса.) Из заданного пароля SQLeet генерирует ключ шифрования через PBKDF2-HMAC-SHA256, и этот ключ тоже хранится только в RAM.  Конечно, такое решение несовершенно. Ключ шифрования, наверное, можно найти в RAM памяти, во время исполнения AsmBB, если у атакующего есть права администратора. Но даже если и так, то система все равно получается намного безопаснее, чем без шифровки. Например, теперь резервные копии БД можно хранить вообще повсюду и пересылать по открытым каналам, не опасаясь утечки данных.  Есть, кстати, и грабли, на которые можно наступить, применяя SQLeet (или другие криптографические расширения SQLite). И я на них, конечно, наступил. Проблема в размере страницы БД. В версиях SQLite более ранних, чем 3.12.0 (март 2016 года) дефолтный размер страницы был 1024 байта. В v3.12.0 его сделали 4096 байта. Этот размер, пользователь БД может менять из соображений производительности, а размер страницы записан в самой БД.  Но если БД зашифрована, то размер страницы нельзя прочесть, а для расшифровки этот размер нужен, потому что каждый блок зашифровывается отдельно.  Поэтому, если зашифровать БД с нестандартным размером страницы (для SQLeet стандарт 4096 байт), потом расшифровать не удастся, даже если задавать правильный пароль. Исправляется это просто – прежде, чем задавать пароль через sqlite3_key() или pragma key='%пароль%', надо задать правильный размер страницы через pragma page_size=%размер%.  Другая возможная проблема в том, что после шифровки ОС уже не сможет распознать, что файл является SQLite БД. Это (насколько я читал) иногда приводит к каким-то проблемам, в частности в iOS. Решение этой проблемы есть, просто не шифровать первые 32 байта файла, но в детали я не вдавался. И напоследок насчет производительности. SQLeet работает очень быстро. После шифрования я не заметил какого-либо замедления работы системы на фоне нормальных флуктуаций производительности VPS. Прецизионные измерения, возможно, покажут какое-нибудь замедление, но оно наверняка будет в пределах меньше чем 10% от скорости не зашифрованной БД. Конечно, есть и другие свободные расширения SQLite для шифрования. Например, SQLcipher. Мне оно не подошло потому что у него другая лицензия распространения (BSD), намного больше размер кода и имеются внешние зависимости.  Но, с другой стороны, SQLcipher намного старше и поэтому (возможно) более стабильный. Кому-то может и пригодится. Инженер автоматизации