Так и знал, что однажды я всё-таки напишу статью, за которую мне будет стыдно. Этой статьёй была предыдущая статья, в которой я описал довольно необычный алгоритм шифрования, его плюсы и недостатки.

Это - коротенькая статья, в которой я хочу подвести итоги касательно этой затеи. Изначально я хотел полностью снести ту статью и никогда больше не вспоминать об этом алгоритме, но не нашёл кнопки удаления подумал, что на своих ошибках нужно не только учиться самому, но и учить других. Так что для новичков в информационной безопасности - эти две статьи могут обладать интересной и полезной информацией.

Начнём с главной проблемы алгоритма, о которой писали вообще все, кто оставлял комментарии на прошлую статью: у алгоритма нет защиты от XOR зашифрованных данных. Признаюсь - я раньше не знал о такого рода уязвимости, хотя мог бы и догадаться, ведь это простейшая бинарная логика. (Если быть совсем откровенным - у меня совсем другое мышление, поэтому какие-то моменты я могу продумывать в самых точных деталях, а какие-то пропускать. Сложно описать как это работает, но так уж устроены люди)

В чём соль: представьте, что у вас есть один ключ шифрования и несколько файлов/сообщений. Если вы зашифруете их одним и тем же ключом шифрования, "проXORив" их - то подвергнете данные огромному риску. Ведь согласно бинарной логике:

(data1 XOR key) XOR (data2 XOR key) = data1 + data2

Да, получаются не совсем исходные данные, но что-то очень близкое к ним (их сумма), явно проявляется структура данных. Если у злоумышленника будет сотня таких файлов/сообщений, зашифрованных одним и тем же ключом - ему не составит трудности по структуре данных определить исходные данные и ключ.

Поэтому - НИКОГДА не шифруйте данные одним и тем же ключом шифрования или хэшем.

Но что тогда делать, если я хочу шифровать данные одной и той же парольной фразой? Просто добавь соль - она колоссально изменяет итоговый ключ шифрования, даже если используется та же парольная фраза. Получается - у вас может быть бесконечно много разных ключей шифрования из одной парольной фразы. Эту соль нужно сгенерировать случайным образом, и использовать вместе с парольной фразой. Чтобы её не терять - можно добавлять её к зашифрованным данным, например в начало. Да, её никак прятать не нужно, можно хоть злоумышленнику в лицо кинуть - суть в том, что она уже свою работу выполнила, защитив данные от уязвимости с XOR, и теперь нужна только для расшифровки, для которой ещё и ключ шифрования надо знать.

Я решил внести изменения в свой алгоритм шифрования, чтобы защитить его от уязвимости с XOR, а заодно и усложнив поиск "Main Key" - пускай "Main Key" генерируется при помощи, например, PBKDF2, соль генерируется случайно, и записывается в начало зашифрованного файла - первые 16 байт. Ещё 4 байта на количество итераций. Конечно, немножко обидно, что теперь размер файла будет увеличиваться на 20 байт при шифровании, но это не так уж и страшно.

Вот я обозначил новую версию, и всё вроде бы классно, две главные уязвимости побеждены... Но всё равно возникают мысли - "а нафига это всё нужно", ведь можно попытаться заставить PBKDF2 генерировать ключ огромных размеров, и использовать его для файлов, и тогда вся эта моя идея с чанками не нужна вовсе.

Во-первых, я уже говорил, что вся эта затея имеет около-развлекательный характер, и служит больше как корм для размышлений, чем реальная идея, которую можно и нужно применять.

Во-вторых, этот алгоритм может иметь большую стойкость благодаря некой защите чанков между собой. Хотя, с другой стороны, в глубине своих размышлений, мне кажется, что идея с одним большим ключом может быть лучше, потому что при расшифровке данных нельзя сказать точно - это точно расшифрованные данные, или совпадение? (Вообще, мне нравится идея о том, что при насильственной расшифровке данных путём брутфорса может получится что угодно, а не один единственный правильный вариант. Кто-нибудь, кто шарит, напишите в комментариях, существуют ли такие алгоритмы и хитрости, и используются ли где-нибудь).

Ещё, если развивать тему с этим алгоритмом - нужно уточнить ещё пару деталей, как минимум - идеальная длина парольной фразы (проблема хэширования и коллизий). Но мне лень этим заниматься, так что пускай кто-нибудь напишет в комментариях разбор этой темы.

Предыдущую реализацию на чистом Си я снёс от греха подальше, новую почти дописал, но возникли небольшие проблемы с segmentation fault, так что если когда-нибудь допишу - то выложу. Ну или кто-нибудь обгонит меня и напишет всё на Python. Зато на Python алгоритм будет работать очень медленно, а на Си быстро, ухахахаха.

В общем и целом - это некое послесловие к предыдущей статье, где я наговорил фигни, особенно в комментариях. Такое часто бывает, когда человек лезет в тему, в которой разбирается не очень хорошо. Но я исправился, узнал много нового, и, надеюсь, кому-нибудь это чем-нибудь поможет. Благодарю за прочтение.

Комментарии (5)


  1. SuperCat911
    28.05.2024 04:19
    +2

    Мне кажется, что ошибаться - это вполне норм. И где бы вы ещё получили такую обратную связь и консультации от разных профи? Если кто-то не ошибается, значит тот не работает.

    Даже если комментарии оказываются полезнее статьи, тоже ничего страшного. В этом случае статья становится триггером полезного контента от профи. А ты бы сидели знатоки и молчали.

    В общем, удачи в творчестве) Не опускайте руки.


  1. CitizenOfDreams
    28.05.2024 04:19
    +4

    Как там звучит первое правило криптографического клуба? "Don't roll your own crypto"?


    1. lrrr11
      28.05.2024 04:19

      ну а всем этим NIST и прочим ТК26 тогда что делать? Сухари сушить получается?

      Подобные фразы хороши для всяких начинающих программистов на wordpress, но давайте все-таки учитывать, что на хабр заходят и другие люди (хоть это и не его целевая аудитория)


  1. firegurafiku
    28.05.2024 04:19
    +2

    В продолжение моего комментария к первой части статьи.

    Теперь у вас получился (модифицированный) шифр из второй главы учебника. Он тоже стойкий, причём, в более широком смысле, и тоже, в конечном итоге, сводится к классической конструкции. И, само собой, по-прежнему непрактичен.

    Давайте посмотрим на ваш алгоритм:

    c_i = H(\mathrm{PBKDF2}(k, s) \mathbin\Vert i) \oplus m_i.

    Из тех же соображений, что приведены в моём первом комментарии, мы можем заменить его на эквивалентный по стойкости шифр

    c_i = \mathrm{PRF}(\mathrm{PBKDF2} (k, s) \mathbin\Vert i) \oplus m_i,

    где PRF — некая стойкая псевдослучайная функция. Однако, PBKDF2 — это тоже ни что иное, как стойкая псевдослучайная функция с настраиваемой степенью сложности. То есть, мы можем записать и так:

    c_i = \mathrm{PRF}(\mathrm{PRF2}(k, s), i) \oplus m_i.

    Композиция по ключу двух стойких псевдослучайных функций сама является стойкой псевдослучайной функцией, и мы можем дальше рассматривать одну функцию:

    c_i = \mathrm{PRF}' (k, (s, i)) \oplus m_i.

    Это выражение, в общем-то, ни что иное, как обобщённая схема блочного шифра в режиме работы со счётчиком и nonce. Она стойкая, если:

    • ключ k выбирается случайным образом,

    • для шифрования каждого нового сообщения используется уникальное значение величины s.

    Вообще говоря, тут от соли не требуется быть случайной, требуется только уникальность пары (k, s). Поэтому соль тут не вектор инициализации, как написано у вас, а именно nonce. Можно использовать простой счетчик сообщений, и это не повлияет на стойкость.

    Проблема с вашим шифром в том, что вы опять изобрели блочный шифр со счётчиком на основе алгоритмов, и так построенных на блочных шифрах. Кроме того, вам потребуется заново вычислять PBKDF2 (она очень медленная) после каждого сообщения, хотя если бы вы просто применили классическую схему, это нужно было бы делать только лишь при смене ключа.

    Рекомендую прекратить изобретать велосипеды и пройти уже, наконец, на курсере стенфордский онлайн-курс по криптографии. Он очень классный, странно, что ещё никто не порекомендовал.


    1. KOCTEP Автор
      28.05.2024 04:19

      Примерно таких хороших разборов я и хотел. Да, в процессе я уже понял, что SHA256 и PBKDF2 - и так почти что готовые решения для шифрования, и вроде бы уже упомянул это в статье. Ну, зато интересная в чём-то штука вышла, и новичкам будет полезно изучить