Windows Vista взошла на трон в 2007-ом, но спустя буквально 1.5 года была с позором свергнута общественными критиками. Уныло шагая прочь, она с тоскою поглядывала на кричащее вслед сообщество, которое даже не успело должным образом оценить все её достоинства. Злую шутку с Вистой сыграл второпях наляпанный интерфейс, а ведь система подряжалась прийти к нам не с пустыми руками и хотела представить миру массу новых разработок, которые мы всё-таки взяли на вооружение, и пользуемся ими по сей день.
Одним из новшеств стала "криптография нового поколения" под названием CNG, или Cryptorgaphy Next Generation. Инфраструктура была призвана заменить отживший свой век на XP интерфейс CAPI (Crypto-API), оставив его лишь для совместимости. Входящими в состав CNG примитивами тут-же поспешили воспользоваться изголодавшиеся на тот момент сетевые протоколы SSL/TLS (Secure-Socket-Layer, и Transport-Layer-Secure), и как следствие весь зоопарк интернет-браузеров. На особом месте стоит и герой этой статьи – метод шифрования с аутентификацией, реализованный в современной линейке Win алгоритмом AES в режиме GCM. Предлагаю посмотреть на CNG и AES со-всевозможных ракурсов, а в некоторых случаях и под микроскопом.
Содержание:
1. Базовые сведения
Криптография является настолько объёмной наукой, что охватить всё направление в одной статье никак не получиться. По этой причине, придётся сделать акцент только на симметричных алгоритмах шифрования, как наиболее популярных с практической точки зрения. Есть ещё асимметричные алго, в которых применяются пара ключей – открытый и закрытый, в то время как симметричные функции требуют от нас только одного открытого ключа.
Все крипто-алгоритмы делятся на три генетических вида – вообще без ключей, с одним, и с двумя ключами. К примеру можно не передавать ключ функции шифрования, как это реализовано в генераторах случайных чисел RNG (RandomGen), или при хешировании данных алгоритмом SHA без соли. На рисунке ниже представлена зависимость функций от ключей:
Операционные системы начиная с Win7 вполне самодостаточны и не требуют для криптографии библиотек сторонних разработчиков. В то-же время, в некоторых компьюнити советуют использовать для этих целей левые модули типа OpenSSL, Crypto++, Sodium и прочие. Можно предположить, что подобные настроения возникают у программистов в большей степени из-за того, что они просто не могут разобраться с функциями библиотеки CNG bcrypt.dll, которая идёт в штатной поставке Win. И это не спроста, т.к. одни и те-же функции данной либы поддерживают работу как в пользовательском режиме, так и в режиме ядра. То-есть это библиотека низкого уровня и вести с ней диалог нужно только на лексиконе Unicode, поскольку ядро в упор не понимает строк ANSI. Благо всё уже прописано в сишном хидере bcrypt.h и нам остаётся лишь скопипастить его в свой инклуд (см.скрепку в подвале).
Эти и другие мелочи требуют особого внимания, за что система щедро отблагодарит нас мощной поддержкой шифрования, начиная от обычного DES и заканчивая современным AES/GCM с кодами аутентификации МАС. Если разобраться со-всеми нюансами, то можно будет с лёгкостью писать стиллеры паролей современных браузеров, расшифровывать перехваченные пакеты протоколов SSL/TLS, и многое другое. С приходом инфраструктуры CNG, алгоритм AES в режиме счётчика-Галуа (gcm) используется повсеместно, поскольку сочетает в себе как шифрование данных 32-байтным ключом (256-бит), так и проверку целостности этих данных на стороне получателя.
2. Симметричные и асимметричные алгоритмы
Нельзя утверждать, что симметричные алгоритмы предпочтительнее асимметричных хотя-бы потому, что у каждого из них своя область применения. В большей мере это зависит от того, какие цели мы преследуем. Основным недостатком симметричного шифрования является необходимость публичной передачи ключа, которым было зашифровано сообщение. Это не проблема, когда общаются двое, однако накладывает свой отпечаток на раздачу ключей нескольким пользователям в сети. В остальном, алго можно считать достаточно эффективным, особенно на фоне асимметричного шифрования.
Поставщики криптографических услуг Win-CSP (Cryptography Service Provider), реализуют симметричное шифрование посредством всего трёх алгоритмов – это AES, DES и RC2/4. Так выглядит типичная схема обмена зашифрованными сообщениями:
Здесь видно, что у каждого абонента должен быть свой симметричный ключ, который он передаёт в криптографическую функцию. Значение ключа и самой функции (в нашем случае AES), должно быть оговорено двумя сторонами заранее, чтобы на приёмном узле можно было расшифровать полученные данные. В этой схеме, главное в тайне согласовать с получателем ключ, а о том как решают эту проблему гиганты типа браузеров лиса и хром, мы поговорим в следующей части статьи.
Асимметричные-же алгоритмы имеют два ключа, что позволяет им без проблем распространять открытые ключи по сети. Не имея второго "приватного" ключа, пароль нельзя будет расшифровать, поэтому публичный ключ не представляет особой ценности (смотря для кого). На этом принципе работает сетевой протокол SSL – благодаря публичным ключам он устанавливает безопасное соединение с пользователем, т.к. закрытый ключ есть только на стороне сервера.
На подготовительном этапе, каждый из участников сети генерируют себе не один, а сразу пару ключей – приватный и публичный. Суть в том, что публичный ключ создаётся на основе приватного и гуляет по сети вместе с сообщением. После того-как ключи созданы, все юзеры выкладывают свои публичные ключи на всеобщее обозрение, чтобы при помощи них отправители шифровали послания получателям. Это можно сравнить с номером телефона в сотовой связи. В результате, ни один из участников сети не сможет расшифровать чужую корреспонденцию, поскольку для этого требуется приватный ключ того пользователя, публичным ключом которого было зашифровано сообщение.
На схеме ниже, комиссар со звездой во-лбу (С) пытается отправить зашифрованное асимметричным ключом письмо, своей зазнобе (А). Для этого, он берёт её публичный ключ из кеша (ну или запрашивает его напрямую, если кеша нет), и криптует полученным ключом свои данные. При этом ни приватный, ни публичный свой ключ он не использует – приватный нужен только для расшифровки входящих сообщений, а публичным ключом будут шифровать сообщения ему.
Теперь, не важно как (голубем, или по каналам связи) он отправляет письмо получателю, который расшифровывает его своим приватным (секретным) ключом. Исходя из того, что оба ключа юзера привязываются друг-к-другу на этапе их создания, расшифровать послание чужим приватным ключом не получится – нужна только конкретная пара. Приватные ключи все держат при себе, и хранят их как зеницу ока. Визуальная схема такого обмена выглядит примерно так:
Системные провайдеры Win из асимметричных поддерживают три алгоритма – это ECC (Elliptic Сurve Сryptosystem, крипт на эллиптических кривых), RSA и DH. Аббревиатуры двух последних взяты по именам их создателей (видимо сильно любили себя шельмы) – это Rivest-Shamir-Adelman, и Diffie-Hellman соответственно. Если посмотреть на реалии, то выходит, что для асимметричного шифрования используется только RSA, а остальные – для тайной передачи ключей на расстояния "Secret Agreement", и оформлении цифровой подписи данных "Signature".
Основной недостаток асимметричного шифрования упирается в низкую скорость работы функции, что обусловлено ресурсоёмкими внутренними операциями. Более того, имеется проблема защиты открытых ключей от фальсификации (джокер на рис.выше), ведь достаточно просто подставить свой публичный ключ вместо любого, чтобы снифать его сообщения открывая их своим приватным ключом. Впрочем, схема хранения и передачи ключей – тема отдельной статьи. Здесь-же достаточно запомнить, что симметричное шифрование используется гораздо чаще асимметричного, а потому остальная часть статьи будет посвящена исключительно симметричному крипту.
3. Примитивы CNG из библиотеки Вcrypt.dll
Подсистема криптографии CNG в современных ОС устроена так, что глобальным движком является библиотека BCRYPTPRIMITIVE.DLL (см.папку system32). Если заглянуть в её экспорт, можно обнаружить там всего шесть функций, при помощи которых она запрашивает соответствующие интерфейсы ядра (имена всех функций начинаются с префикса Get и заканчиваются суффиксом Interface). На более дружелюбном к юзеру высоком уровне расположилась либа Bcrypt.dll, в тушке которой сосредоточены уже сами функции на все случаи жизни. Поскольку они являются отдельными элементами глобальной системы криптографии, их назвали "примитивами". Не сказать, что таких примитивов много – в экспорте Bcrypt.dll на моей Win7 зарегистрировано всего 54 функций, большая часть из которых если и применяется, то только в клинических случаях.
4. Алгоритм шифрования AES, и режимы его работы
AES (Advanced Encryption Standard) – это расширенная версия устаревшего DES. Алгоритм представляет собой симметричный блочный шифр. Такое определение означает, что на вход процедуры шифрования данных, информация должна поступать блоками. Размер одного блока для AES всегда равен 16-байт, в виде матрицы 4х4. По этой причине, блочные шифры называют ещё "матричными". AES увеличивает кодируемую информацию и делает её кратным размеру блока. Однако при использовании режима "GCM" размер остаётся прежним – сколько байт забросим в печь, столько-же и получим с выхлопной трубы.
Чтобы после процедуры крипта была возможность обратно восстановить информацию, алгоритму требуется ключ-шифрования. Разрядность ключа указывается в названии алгоритма, например AES-128, 192 или 256 бит. Другие размеры ключей AES не поддерживает, так-что мы ограничены ключами: 128/8=16 байт, 192/8=24 байта, и 256/8=32 байта. Разница между зоопарком AES заключается только в размере ключа и кол-ве используемых повторений (раундов), но не в размере блока – блок всегда одинаковый 16-байт. Счётчик раундов составляет 10,12,14 итераций соответственно.
В наиболее простом и интуитивно понятном классическом режиме "ECB" (Electronic Codebook), сложным преобразованиям подвергается каждый блок данных, при этом такая операция повторяется над каждым блоком несколько раз, что подразумевает собой "раунд". Главный недостаток режима ЕСВ заключается в том, что одинаковые блоки исходных данных (например цепочка из 32-х и более нулей) при шифровании дадут одинаковые блоки шифротекста – это существенно содействует взлому. Поэтому режим ECB не рекомендуется использовать при шифровании текстов, по длине превышающих один 16-байтный блок.
Благодаря этой проблеме, на свет появился ещё один режим AES под кличкой "CBC" (Сipher Block Chaining). Здесь уже каждый последующий блок шифруется выходным значением предыдущего, что связывает блоки между собой образуя цепочку "Chain". При такой схеме возникает резонный вопрос: -"Если следующий блок кодируется предыдущим, то чем тогда кодировать самый первый блок, ведь у него нет предыдущего?".
Для этого, режим CBC требует на входе ещё одно значение, которое назвали "вектор инициализации" IV (Initialization Vector). В зависимости от режима работы (а кроме CBC есть ещё и масса других), размер IV может варьироваться в диапазоне от 12 до 16-байт, не превышая размер блока AES. Как-правило, его значение программист должен сгенерировать рандомно, на подготовительном этапе шифрования. Вот как выглядят эти режимы в графике (Plain открытый, Cipher зашифрованный текст):
Глядя на эту схему становится очевидно, что режим электронной книжки ECB отжил уже свой век, и на практике не рекомендуется к использованию. В случае со-вторым вариантом CBC, мы сталкиваемся с необходимостью передавать получателю вместе с зашифрованными данными ключ, и значение вектора IV – иначе декодер на приёмном узле просто не сможет расшифровать закодированную информацию. Думаю не имеет смысла упоминать о том, что будет, если по дороге "потеряется" какой-нибудь промежуточный блок – чинить уже будет нечего, т.к. все блоки связаны между собой неразрывными узами.
Алгоритм AES оказался настолько удачным, что разработчики начали комбинировать различные схемы. К примеру ещё одной вариацией режима CBC стал модернезированный "CFB" (Feed-Back, обратная связь). Здесь, сначала шифруется вектор IV, который на выходе складывается ксором
4.1. AES в режиме цепочки и счётчика
Следующим шагом к достижению гармонии было внедрение в алгоритм AES внутреннего счётчика – режим получил название "CTR" (Counter). Это самый распространённый вариант реализации AES из-за своей крипткостойкости ко взлому. Не смотря на то, что здесь нет связывания блоков между собой, каждый последующий блок всё-равно шифруется новым значением IV, поскольку при переходе к следующему блоку счётчик автоматически увеличивается на 1. Счётчик вектора IV имеет размер 4-байта, и на старте шифрования сбрасывается алгоритмом в нуль.
5. Практика – сбор информации о провайдерах CNG
Теперь, когда мы получили дозу фундаментальных основ, можно рассмотреть несколько функций из Bcrypt.dll. Начнём с того, что перечислим все поддерживаемые стандартным поставщиком Win-CNG алгоритмы, ведь должны-же мы знать, какие из них доступны нам для использования в своих программах. Для этого предусмотрена функция BCryptEnumAlgorithm() с таким прототипом:
Функция возвращает массив Unicode-строк с именами алгоритмов. Например, если хотим перечислить все алго симметричного шифрования, то передаём функции в первом аргументе константу(1) "BCRYPT_CIPHER_OPERATION". Если интересуют алго хеширования данных, то соответственно "BCRYPT_HASH_OPERATION" и т.д. Кол-во записей в полученном массиве функция возвращает в переменную, на которую указывает второй параметр.
Поскольку константы операций для первого аргумента имеют значение степени(2), это способствует организации цикла. То-есть отправляем в первый аргумент единицу, и на следующей итерации, сдвигом влево умножаем предыдущее значение на 2. Как видим, всего итераций в цикле должно быть 6 (последний с константой 40h моя семёрка не поддерживает). Далее просто берём из структуры "BCRYPT_ALGORITHM_IDENTIFIER" первое поле, и получаем указатель на цепочку имён алгоритмов.
Чтобы добавить в программу красок и повысить её инфо-нагрузку, можно вывести на консоль детали каждого из алгоритмов. От вызова предыдущей функции мы уже имеем имя алгоритма шифрования, и достаточно будет открыть его функцией BCryptOpenAlgorithmProvider(), после чего запросить требуемые свойства через BCryptGetProperty().
Вторая функция во-втором параметре ожидает указатель на имя свойства, которое мы планируем получить – это текстовые Unicode-строки (см.инклуд в скрепке). В данном случае речь идёт про симметричные алгоритмы, и меня будут интересовать всего три их свойства: (1) размер блока шифрования данных, (2) размер ключа, и прицепом (3) размер временного объекта. Объекты подобного рода, функции используют для своих производственных нужд и в некоторых случаях мы должны выделять под них память (например при хешировании). Так-что инфа об объектах явно не будет лишней.
Функция BCryptGetProperty() возвращает размер блока и размер временного объекта в виде значений DWORD. А чтобы получить свойства ключа шифрования, нужно подготовить структуру такого характера. Выше упоминалось, что ключи у алгоритмов могут быть разной разрядности, например для AES это: 128, 192 и 256 бит. В структуре ниже, этот диапазон хранится как мин/макс значение ключа, и шаг прироста в виде поля "Increment".
В своём примере, сначала я запрашиваю тип операции = "симметричное шифрование", после чего перечисляю все алгоритмы, которые способны осуществить эту операцию. На следующем этапе, меняю тип на "хеширование данных" (умножаю предыдущее значение на 2) и так-же перечисляю её алгоритмы. В коде таких повторов 6, по числу поддерживаемых поставщиком Win криптографических действий. В самом конце я опять возвращаюсь к первому пункту "симметричное шифрованию", и вывожу уже детали каждого из алгоритмов. Это поможет прояснить общую картину инфраструктуры CNG:
Таким образом нам удалось получить неплохую голограмму инфраструктуры CNG, и это данные лишь одной из операций – симметричное шифрование. Лог в очередной доказывает, что алгоритм AES имеет размер входного блока 16-байт, и поддерживает три типа ключей: 128, 192 и 256 бит.
Зато его предшественник DES всех мастей, оперирует блоками по 8-байт, с фиксированными размерами ключей. Если классический DES производит над каждым своим блоком всего одну операцию шифрования, то 3DES повторяет её трижды (см.раунды).
А вот алгоритмы RC2 и RC4 в корень отличаются друг от друга, хотя и посещают одну синагогу. RC2 это блочный симметричный шифр с диапазоном ключей от 40 до 128 бит (с шагом в байт), в то время как RC4 относится к потоковым шифрам, т.к. он оперирует не блоками данных, а процеживает информацию по-байтно, шифруя на уровне бит.
Алгоритмы SHA и MD для хеширования – это стандартная практика. А вот то-что появился для этих целей AES-GMAC – это уже гуд. Что это такое мы обсудим в следующей части статьи, но если-бы нам приспичило получить хеш AES/GMAC на системе Win-XP, то пришлось-бы звать на помощь библиотеки сторонних разработчиков, такие как Crypto++. Начиная-же с Win-Vista данный алгоритм уже включён в состав ОС, и необходимость грузить непонятно кем написанные либы сама-собой отпадает.
Из асимметричных алго маячит только RSA, а больше нам и не надо – в этом сегменте RSA занимает позицию лидера. Кроме того имеем широкий выбор для создания цифровых подписей "Signature", и базовую тройку для генерации случайных чисел – это RNG (RandomGen мастдая), алгоритм одобренный институтом FIPS (Federal Information Processing Standard Publication), и DUAL_EC_RNG, что подразумевает "детерминированный генератор случайных бит с двойной эллиптической кривой".
6. Заключение
Наука о криптографии, а тем-более практическая её реализация, затягивает не по-детски. Если подходить к ней осмысленно, она открывает двери в такие закоулки системы, о которых мы и не подозревали. Но как и любое начинание, сначала нужно разобраться с теорией, пусть и не на уровне конкретных примитивов.
В следующей части запланировано несколько пруфов, которые докажут всё выше сказанное. Мы более подробно разберём современный и широко распространённый вид шифрования с тегами аутентификации AES-256 в режиме "GCM", узнаем что такое AEAD и в каком виде передаются зашифрованные данные, чтобы их можно было расшифровать. К примеру браузеры Chrome версии 80 и выше шифруют пароли юзеров и кукисы именно в режиме AES/GCM и мы убедимся, как легко их можно будет поиметь.
В скрепку положил инклуд для работы с библиотекой CNG на фасме,
а так-же исполняемый файл для вывода лога системного поставщика. На этом занавес – пока!
Одним из новшеств стала "криптография нового поколения" под названием CNG, или Cryptorgaphy Next Generation. Инфраструктура была призвана заменить отживший свой век на XP интерфейс CAPI (Crypto-API), оставив его лишь для совместимости. Входящими в состав CNG примитивами тут-же поспешили воспользоваться изголодавшиеся на тот момент сетевые протоколы SSL/TLS (Secure-Socket-Layer, и Transport-Layer-Secure), и как следствие весь зоопарк интернет-браузеров. На особом месте стоит и герой этой статьи – метод шифрования с аутентификацией, реализованный в современной линейке Win алгоритмом AES в режиме GCM. Предлагаю посмотреть на CNG и AES со-всевозможных ракурсов, а в некоторых случаях и под микроскопом.
Содержание:
1. Базовые сведения;
2. Симметричные и асимметричные алгоритмы;
3. Примитивы CNG из библиотеки bcrypt.dll;
4. Алгоритм AES и режимы его работы;
5. Практика – сбор информации об алгоритмах CNG;
6. Заключение.
-------------------------------------------------------1. Базовые сведения
Криптография является настолько объёмной наукой, что охватить всё направление в одной статье никак не получиться. По этой причине, придётся сделать акцент только на симметричных алгоритмах шифрования, как наиболее популярных с практической точки зрения. Есть ещё асимметричные алго, в которых применяются пара ключей – открытый и закрытый, в то время как симметричные функции требуют от нас только одного открытого ключа.
Все крипто-алгоритмы делятся на три генетических вида – вообще без ключей, с одним, и с двумя ключами. К примеру можно не передавать ключ функции шифрования, как это реализовано в генераторах случайных чисел RNG (RandomGen), или при хешировании данных алгоритмом SHA без соли. На рисунке ниже представлена зависимость функций от ключей:
Операционные системы начиная с Win7 вполне самодостаточны и не требуют для криптографии библиотек сторонних разработчиков. В то-же время, в некоторых компьюнити советуют использовать для этих целей левые модули типа OpenSSL, Crypto++, Sodium и прочие. Можно предположить, что подобные настроения возникают у программистов в большей степени из-за того, что они просто не могут разобраться с функциями библиотеки CNG bcrypt.dll, которая идёт в штатной поставке Win. И это не спроста, т.к. одни и те-же функции данной либы поддерживают работу как в пользовательском режиме, так и в режиме ядра. То-есть это библиотека низкого уровня и вести с ней диалог нужно только на лексиконе Unicode, поскольку ядро в упор не понимает строк ANSI. Благо всё уже прописано в сишном хидере bcrypt.h и нам остаётся лишь скопипастить его в свой инклуд (см.скрепку в подвале).
Эти и другие мелочи требуют особого внимания, за что система щедро отблагодарит нас мощной поддержкой шифрования, начиная от обычного DES и заканчивая современным AES/GCM с кодами аутентификации МАС. Если разобраться со-всеми нюансами, то можно будет с лёгкостью писать стиллеры паролей современных браузеров, расшифровывать перехваченные пакеты протоколов SSL/TLS, и многое другое. С приходом инфраструктуры CNG, алгоритм AES в режиме счётчика-Галуа (gcm) используется повсеместно, поскольку сочетает в себе как шифрование данных 32-байтным ключом (256-бит), так и проверку целостности этих данных на стороне получателя.
2. Симметричные и асимметричные алгоритмы
Нельзя утверждать, что симметричные алгоритмы предпочтительнее асимметричных хотя-бы потому, что у каждого из них своя область применения. В большей мере это зависит от того, какие цели мы преследуем. Основным недостатком симметричного шифрования является необходимость публичной передачи ключа, которым было зашифровано сообщение. Это не проблема, когда общаются двое, однако накладывает свой отпечаток на раздачу ключей нескольким пользователям в сети. В остальном, алго можно считать достаточно эффективным, особенно на фоне асимметричного шифрования.
Поставщики криптографических услуг Win-CSP (Cryptography Service Provider), реализуют симметричное шифрование посредством всего трёх алгоритмов – это AES, DES и RC2/4. Так выглядит типичная схема обмена зашифрованными сообщениями:
Здесь видно, что у каждого абонента должен быть свой симметричный ключ, который он передаёт в криптографическую функцию. Значение ключа и самой функции (в нашем случае AES), должно быть оговорено двумя сторонами заранее, чтобы на приёмном узле можно было расшифровать полученные данные. В этой схеме, главное в тайне согласовать с получателем ключ, а о том как решают эту проблему гиганты типа браузеров лиса и хром, мы поговорим в следующей части статьи.
Асимметричные-же алгоритмы имеют два ключа, что позволяет им без проблем распространять открытые ключи по сети. Не имея второго "приватного" ключа, пароль нельзя будет расшифровать, поэтому публичный ключ не представляет особой ценности (смотря для кого). На этом принципе работает сетевой протокол SSL – благодаря публичным ключам он устанавливает безопасное соединение с пользователем, т.к. закрытый ключ есть только на стороне сервера.
На подготовительном этапе, каждый из участников сети генерируют себе не один, а сразу пару ключей – приватный и публичный. Суть в том, что публичный ключ создаётся на основе приватного и гуляет по сети вместе с сообщением. После того-как ключи созданы, все юзеры выкладывают свои публичные ключи на всеобщее обозрение, чтобы при помощи них отправители шифровали послания получателям. Это можно сравнить с номером телефона в сотовой связи. В результате, ни один из участников сети не сможет расшифровать чужую корреспонденцию, поскольку для этого требуется приватный ключ того пользователя, публичным ключом которого было зашифровано сообщение.
На схеме ниже, комиссар со звездой во-лбу (С) пытается отправить зашифрованное асимметричным ключом письмо, своей зазнобе (А). Для этого, он берёт её публичный ключ из кеша (ну или запрашивает его напрямую, если кеша нет), и криптует полученным ключом свои данные. При этом ни приватный, ни публичный свой ключ он не использует – приватный нужен только для расшифровки входящих сообщений, а публичным ключом будут шифровать сообщения ему.
Теперь, не важно как (голубем, или по каналам связи) он отправляет письмо получателю, который расшифровывает его своим приватным (секретным) ключом. Исходя из того, что оба ключа юзера привязываются друг-к-другу на этапе их создания, расшифровать послание чужим приватным ключом не получится – нужна только конкретная пара. Приватные ключи все держат при себе, и хранят их как зеницу ока. Визуальная схема такого обмена выглядит примерно так:
Системные провайдеры Win из асимметричных поддерживают три алгоритма – это ECC (Elliptic Сurve Сryptosystem, крипт на эллиптических кривых), RSA и DH. Аббревиатуры двух последних взяты по именам их создателей (видимо сильно любили себя шельмы) – это Rivest-Shamir-Adelman, и Diffie-Hellman соответственно. Если посмотреть на реалии, то выходит, что для асимметричного шифрования используется только RSA, а остальные – для тайной передачи ключей на расстояния "Secret Agreement", и оформлении цифровой подписи данных "Signature".
Основной недостаток асимметричного шифрования упирается в низкую скорость работы функции, что обусловлено ресурсоёмкими внутренними операциями. Более того, имеется проблема защиты открытых ключей от фальсификации (джокер на рис.выше), ведь достаточно просто подставить свой публичный ключ вместо любого, чтобы снифать его сообщения открывая их своим приватным ключом. Впрочем, схема хранения и передачи ключей – тема отдельной статьи. Здесь-же достаточно запомнить, что симметричное шифрование используется гораздо чаще асимметричного, а потому остальная часть статьи будет посвящена исключительно симметричному крипту.
3. Примитивы CNG из библиотеки Вcrypt.dll
Подсистема криптографии CNG в современных ОС устроена так, что глобальным движком является библиотека BCRYPTPRIMITIVE.DLL (см.папку system32). Если заглянуть в её экспорт, можно обнаружить там всего шесть функций, при помощи которых она запрашивает соответствующие интерфейсы ядра (имена всех функций начинаются с префикса Get и заканчиваются суффиксом Interface). На более дружелюбном к юзеру высоком уровне расположилась либа Bcrypt.dll, в тушке которой сосредоточены уже сами функции на все случаи жизни. Поскольку они являются отдельными элементами глобальной системы криптографии, их назвали "примитивами". Не сказать, что таких примитивов много – в экспорте Bcrypt.dll на моей Win7 зарегистрировано всего 54 функций, большая часть из которых если и применяется, то только в клинических случаях.
Код:
Disassembly of File: bcrypt.dll
Code Offset = 00000400, Code Size = 00012C00
Data Offset = 00013000, Data Size = 00000600
Number of Objects = 0004 (dec), Imagebase = 6D800000h
Object01: .text RVA: 00001000 Offset: 00000400 Size: 00012C00 Flags: 60000020
Object02: .data RVA: 00014000 Offset: 00013000 Size: 00000600 Flags: C0000040
Object03: .rsrc RVA: 00015000 Offset: 00013600 Size: 00000600 Flags: 40000040
Object04: .reloc RVA: 00016000 Offset: 00013C00 Size: 00000600 Flags: 42000040
+++++++++++++++++++ EXPORTED FUNCTIONS ++++++++++++++++++
Number of Exported Functions = 0054 (decimal)
Addr:6D8095B5 Ord: 1 (0001h) Name: BCryptAddContextFunction
Addr:6D809B9F Ord: 2 (0002h) Name: BCryptAddContextFunctionProvider
Addr:6D802391 Ord: 3 (0003h) Name: BCryptCloseAlgorithmProvider
Addr:6D8092D6 Ord: 4 (0004h) Name: BCryptConfigureContext
Addr:6D80985F Ord: 5 (0005h) Name: BCryptConfigureContextFunction
Addr:6D808ED7 Ord: 6 (0006h) Name: BCryptCreateContext
Addr:6D801B93 Ord: 7 (0007h) Name: BCryptCreateHash
Addr:6D8018B8 Ord: 8 (0008h) Name: BCryptDecrypt
Addr:6D809015 Ord: 9 (0009h) Name: BCryptDeleteContext
Addr:6D8055C9 Ord: 10 (000Ah) Name: BCryptDeriveKey
Addr:6D804A4B Ord: 11 (000Bh) Name: BCryptDeriveKeyCapi
Addr:6D8088EE Ord: 12 (000Ch) Name: BCryptDeriveKeyPBKDF2
Addr:6D801A5F Ord: 13 (000Dh) Name: BCryptDestroyHash
Addr:6D801F40 Ord: 14 (000Eh) Name: BCryptDestroyKey
Addr:6D805438 Ord: 15 (000Fh) Name: BCryptDestroySecret
Addr:6D80528E Ord: 16 (0010h) Name: BCryptDuplicateHash
Addr:6D8086A0 Ord: 17 (0011h) Name: BCryptDuplicateKey
Addr:6D80195C Ord: 18 (0012h) Name: BCryptEncrypt
Addr:6D807F9D Ord: 19 (0013h) Name: BCryptEnumAlgorithms
Addr:6D805C33 Ord: 20 (0014h) Name: BCryptEnumContextFunctionProviders
Addr:6D805823 Ord: 21 (0015h) Name: BCryptEnumContextFunctions
Addr:6D80913F Ord: 22 (0016h) Name: BCryptEnumContexts
Addr:6D808216 Ord: 23 (0017h) Name: BCryptEnumProviders
Addr:6D808E4E Ord: 24 (0018h) Name: BCryptEnumRegisteredProviders
Addr:6D8050BF Ord: 25 (0019h) Name: BCryptExportKey
Addr:6D805737 Ord: 26 (001Ah) Name: BCryptFinalizeKeyPair
Addr:6D801B44 Ord: 27 (001Bh) Name: BCryptFinishHash
Addr:6D802206 Ord: 28 (001Ch) Name: BCryptFreeBuffer
Addr:6D801E2E Ord: 29 (001Dh) Name: BCryptGenRandom
Addr:6D80568E Ord: 30 (001Eh) Name: BCryptGenerateKeyPair
Addr:6D801FBC Ord: 31 (001Fh) Name: BCryptGenerateSymmetricKey
Addr:6D80307D Ord: 32 (0020h) Name: BCryptGetFipsAlgorithmMode
Addr:6D801CA7 Ord: 33 (0021h) Name: BCryptGetProperty
Addr:6D801B0B Ord: 34 (0022h) Name: BCryptHashData
Addr:6D804302 Ord: 35 (0023h) Name: BCryptImportKey
Addr:6D804EB8 Ord: 36 (0024h) Name: BCryptImportKeyPair
Addr:6D802C72 Ord: 37 (0025h) Name: BCryptOpenAlgorithmProvider
Addr:6D80940A Ord: 38 (0026h) Name: BCryptQueryContextConfiguration
Addr:6D8099C9 Ord: 39 (0027h) Name: BCryptQueryContextFunctionConfiguration
Addr:6D80A06D Ord: 40 (0028h) Name: BCryptQueryContextFunctionProperty
Addr:6D8059DC Ord: 41 (0029h) Name: BCryptQueryProviderRegistration
Addr:6D80359F Ord: 42 (002Ah) Name: BCryptRegisterConfigChangeNotify
Addr:6D80A41D Ord: 43 (002Bh) Name: BCryptRegisterProvider
Addr:6D80970C Ord: 44 (002Ch) Name: BCryptRemoveContextFunction
Addr:6D809D34 Ord: 45 (002Dh) Name: BCryptRemoveContextFunctionProvider
Addr:6D8029C6 Ord: 46 (002Eh) Name: BCryptResolveProviders
Addr:6D80551A Ord: 47 (002Fh) Name: BCryptSecretAgreement
Addr:6D806009 Ord: 48 (0030h) Name: BCryptSetAuditingInterface
Addr:6D809EC5 Ord: 49 (0031h) Name: BCryptSetContextFunctionProperty
Addr:6D8020D4 Ord: 50 (0032h) Name: BCryptSetProperty
Addr:6D8084B3 Ord: 51 (0033h) Name: BCryptSignHash
Addr:6D804609 Ord: 52 (0034h) Name: BCryptUnregisterConfigChangeNotify
Addr:6D808D52 Ord: 53 (0035h) Name: BCryptUnregisterProvider
Addr:6D8060FA Ord: 54 (0036h) Name: BCryptVerifySignature
4. Алгоритм шифрования AES, и режимы его работы
AES (Advanced Encryption Standard) – это расширенная версия устаревшего DES. Алгоритм представляет собой симметричный блочный шифр. Такое определение означает, что на вход процедуры шифрования данных, информация должна поступать блоками. Размер одного блока для AES всегда равен 16-байт, в виде матрицы 4х4. По этой причине, блочные шифры называют ещё "матричными". AES увеличивает кодируемую информацию и делает её кратным размеру блока. Однако при использовании режима "GCM" размер остаётся прежним – сколько байт забросим в печь, столько-же и получим с выхлопной трубы.
Чтобы после процедуры крипта была возможность обратно восстановить информацию, алгоритму требуется ключ-шифрования. Разрядность ключа указывается в названии алгоритма, например AES-128, 192 или 256 бит. Другие размеры ключей AES не поддерживает, так-что мы ограничены ключами: 128/8=16 байт, 192/8=24 байта, и 256/8=32 байта. Разница между зоопарком AES заключается только в размере ключа и кол-ве используемых повторений (раундов), но не в размере блока – блок всегда одинаковый 16-байт. Счётчик раундов составляет 10,12,14 итераций соответственно.
В наиболее простом и интуитивно понятном классическом режиме "ECB" (Electronic Codebook), сложным преобразованиям подвергается каждый блок данных, при этом такая операция повторяется над каждым блоком несколько раз, что подразумевает собой "раунд". Главный недостаток режима ЕСВ заключается в том, что одинаковые блоки исходных данных (например цепочка из 32-х и более нулей) при шифровании дадут одинаковые блоки шифротекста – это существенно содействует взлому. Поэтому режим ECB не рекомендуется использовать при шифровании текстов, по длине превышающих один 16-байтный блок.
Благодаря этой проблеме, на свет появился ещё один режим AES под кличкой "CBC" (Сipher Block Chaining). Здесь уже каждый последующий блок шифруется выходным значением предыдущего, что связывает блоки между собой образуя цепочку "Chain". При такой схеме возникает резонный вопрос: -"Если следующий блок кодируется предыдущим, то чем тогда кодировать самый первый блок, ведь у него нет предыдущего?".
Для этого, режим CBC требует на входе ещё одно значение, которое назвали "вектор инициализации" IV (Initialization Vector). В зависимости от режима работы (а кроме CBC есть ещё и масса других), размер IV может варьироваться в диапазоне от 12 до 16-байт, не превышая размер блока AES. Как-правило, его значение программист должен сгенерировать рандомно, на подготовительном этапе шифрования. Вот как выглядят эти режимы в графике (Plain открытый, Cipher зашифрованный текст):
Глядя на эту схему становится очевидно, что режим электронной книжки ECB отжил уже свой век, и на практике не рекомендуется к использованию. В случае со-вторым вариантом CBC, мы сталкиваемся с необходимостью передавать получателю вместе с зашифрованными данными ключ, и значение вектора IV – иначе декодер на приёмном узле просто не сможет расшифровать закодированную информацию. Думаю не имеет смысла упоминать о том, что будет, если по дороге "потеряется" какой-нибудь промежуточный блок – чинить уже будет нечего, т.к. все блоки связаны между собой неразрывными узами.
Алгоритм AES оказался настолько удачным, что разработчики начали комбинировать различные схемы. К примеру ещё одной вариацией режима CBC стал модернезированный "CFB" (Feed-Back, обратная связь). Здесь, сначала шифруется вектор IV, который на выходе складывается ксором
XOR
со входным блоком данных. Весьма интересная схема, и вполне может занять своё место на практике:4.1. AES в режиме цепочки и счётчика
Следующим шагом к достижению гармонии было внедрение в алгоритм AES внутреннего счётчика – режим получил название "CTR" (Counter). Это самый распространённый вариант реализации AES из-за своей крипткостойкости ко взлому. Не смотря на то, что здесь нет связывания блоков между собой, каждый последующий блок всё-равно шифруется новым значением IV, поскольку при переходе к следующему блоку счётчик автоматически увеличивается на 1. Счётчик вектора IV имеет размер 4-байта, и на старте шифрования сбрасывается алгоритмом в нуль.
Важно! Обратите внимание, что в режимах без счётчика, значение вектора IV должно совпадать с размером 16-байтного блока AES. Это обязательное требование, иначе функция шифрования BCryptEncrypt() будет возвращать ошибку"INVALID_PARAMETR"
. При этом в стиле Microsoft, какой именно параметр из 10-ти возможных не указывается, что затрудняет поиск проблемы.
Если-же мы выбрали режим шифрования AES со-счётчиком (CTR, CCM, GCM), то вектор IV должен быть размером уже 12-байт, поскольку 4-байтный внутренний счётчик фактически является частью IV, занимая в нём младшие 4-байта из 16-ти. Не забывайте об этом!
5. Практика – сбор информации о провайдерах CNG
Теперь, когда мы получили дозу фундаментальных основ, можно рассмотреть несколько функций из Bcrypt.dll. Начнём с того, что перечислим все поддерживаемые стандартным поставщиком Win-CNG алгоритмы, ведь должны-же мы знать, какие из них доступны нам для использования в своих программах. Для этого предусмотрена функция BCryptEnumAlgorithm() с таким прототипом:
C-подобный:
NTSTATUS BCryptEnumAlgorithms ;//<---- 0 = OK!
dwAlgOperations dd 0 ;// тип операции
pAlgCount dd 0 ;// кол-во элементов в массиве ppAlgList
ppAlgList dd 0 ;// указатель на BCRYPT_ALGORITHM_IDENTIFIER
dwFlags dd 0 ;// резерв
;//********************************
;// Operations type flags
BCRYPT_CIPHER_OPERATION = 0x00000001 ;// алго симметричного шифрования
BCRYPT_HASH_OPERATION = 0x00000002 ;// хеширование
BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION = 0x00000004 ;// асимметричные
BCRYPT_SECRET_AGREEMENT_OPERATION = 0x00000008 ;// передача ключей
BCRYPT_SIGNATURE_OPERATION = 0x00000010 ;// цифровая подпись
BCRYPT_RNG_OPERATION = 0x00000020 ;// генератор случайных чисел (рандом)
BCRYPT_KEY_DERIVATION_OPERATION = 0x00000040 ;//<---- начиная с Win-8
;//********************************
struct BCRYPT_ALGORITHM_IDENTIFIER
pszName dd 0 ;// линк на Юникод-имя алгоритма
dwClass dd 0 ;// класс/ID алгоритма
dwFlags dd 0 ;// резерв
ends
Функция возвращает массив Unicode-строк с именами алгоритмов. Например, если хотим перечислить все алго симметричного шифрования, то передаём функции в первом аргументе константу(1) "BCRYPT_CIPHER_OPERATION". Если интересуют алго хеширования данных, то соответственно "BCRYPT_HASH_OPERATION" и т.д. Кол-во записей в полученном массиве функция возвращает в переменную, на которую указывает второй параметр.
Поскольку константы операций для первого аргумента имеют значение степени(2), это способствует организации цикла. То-есть отправляем в первый аргумент единицу, и на следующей итерации, сдвигом влево умножаем предыдущее значение на 2. Как видим, всего итераций в цикле должно быть 6 (последний с константой 40h моя семёрка не поддерживает). Далее просто берём из структуры "BCRYPT_ALGORITHM_IDENTIFIER" первое поле, и получаем указатель на цепочку имён алгоритмов.
Чтобы добавить в программу красок и повысить её инфо-нагрузку, можно вывести на консоль детали каждого из алгоритмов. От вызова предыдущей функции мы уже имеем имя алгоритма шифрования, и достаточно будет открыть его функцией BCryptOpenAlgorithmProvider(), после чего запросить требуемые свойства через BCryptGetProperty().
C-подобный:
NTSTATUS BCryptOpenAlgorithmProvider
phAlgorithm dd 0 ;// сюда вернётся дескриптор алгоритма
pszAlgId dd 0 ;// указатель на Unicode-имя алго (у нас он есть)
pszImplementation dd 0 ;// 0 (поставщик в дефолте)
dwFlags dd 0 ;// 0
NTSTATUS BCryptGetProperty ;//<---- 0 = OK!
hObject dd 0 ;// дескриптор алгоритма от fn.выше
pszProperty dd 0 ;// линк на Unicode-имя свойства
pbOutput dd 0 ;// адрес буфера, который получает значение свойства
cbOutput dd 0 ;// размер буфера pbOutput
pcbResult dd 0 ;// кол-во байтов, скопированных в буфер pbOutput
dwFlags dd 0 ;// резерв
Вторая функция во-втором параметре ожидает указатель на имя свойства, которое мы планируем получить – это текстовые Unicode-строки (см.инклуд в скрепке). В данном случае речь идёт про симметричные алгоритмы, и меня будут интересовать всего три их свойства: (1) размер блока шифрования данных, (2) размер ключа, и прицепом (3) размер временного объекта. Объекты подобного рода, функции используют для своих производственных нужд и в некоторых случаях мы должны выделять под них память (например при хешировании). Так-что инфа об объектах явно не будет лишней.
C-подобный:
;// BCryptGetProperty strings (Set только для CHAINING_MODE)
;// https://docs.microsoft.com/en-us/windows/win32/seccng/cng-property-identifiers
BCRYPT_ALGORITHM_NAME du 'AlgorithmName',0 ;// возвращает юникоде-имя алго
BCRYPT_AUTH_TAG_LENGTH du 'AuthTagLength',0 ;// тег аутентификации в структуру (только алгоритмы)
BCRYPT_BLOCK_LENGTH du 'BlockLength',0 ;// DWORD - только алгоритмы блочного шифрования
BCRYPT_BLOCK_SIZE_LIST du 'BlockSizeList',0 ;// массив DWORD, число элементов = /4
BCRYPT_CHAINING_MODE du 'ChainingMode',0 ;// режим алгоритма AES
BCRYPT_DH_PARAMETERS du 'DHParameters',0 ;// BCRYPT_DH_PARAMETER_HEADER struct (ключ Диффи-Хеллмана)
BCRYPT_DSA_PARAMETERS du 'DSAParameters',0 ;// BCRYPT_DSA_PARAMETER_HEADER struct
BCRYPT_EFFECTIVE_KEY_LENGTH du 'EffectiveKeyLength',0 ;// DWORD - длина ключа RC2
BCRYPT_HASH_BLOCK_LENGTH du 'HashBlockLength',0 ;// DWORD - применимо только к хеш-алгоритмам
BCRYPT_HASH_LENGTH du 'HashDigestLength',0 ;// DWORD - размер в байтах хеш-значения поставщика
BCRYPT_HASH_OID_LIST du 'HashOIDList',0 ;// BCRYPT_OID_LIST struct
BCRYPT_INITIALIZATION_VECTOR du 'IV',0 ;// содержит IV, применяется только к ключам
BCRYPT_KEY_LENGTH du 'KeyLength',0 ;// DWORD - размер в битах симметричного ключа
BCRYPT_KEY_LENGTHS du 'KeyLengths',0 ;// BCRYPT_KEY_LENGTHS_STRUCT - размеры ключей алгоритма
BCRYPT_KEY_STRENGTH du 'KeyStrength',0 ;// DWORD - размер ключа в битах
BCRYPT_MESSAGE_BLOCK_LENGTH du 'MessageBlockLength',0 ;// применимо к режиму CFB (=1 для 8-битного CFB)
BCRYPT_MULTI_OBJECT_LENGTH du 'MultiObjectLength',0 ;// BCRYPT_MULTI_OBJECT_LENGTH_STRUCT (найти размер буфера)
BCRYPT_OBJECT_LENGTH du 'ObjectLength',0 ;// DWORD - размер в байтах подобъекта поставщика
BCRYPT_PADDING_SCHEMES du 'PaddingSchemes',0 ;// схема заполнения алгоритма RSA
BCRYPT_PROVIDER_HANDLE du 'ProviderHandle',0 ;// DWORD - дескриптор создавшего объект поставщика
BCRYPT_SIGNATURE_LENGTH du 'SignatureLength',0 ;// DWORD - размер в байтах длины подписи ключа
Функция BCryptGetProperty() возвращает размер блока и размер временного объекта в виде значений DWORD. А чтобы получить свойства ключа шифрования, нужно подготовить структуру такого характера. Выше упоминалось, что ключи у алгоритмов могут быть разной разрядности, например для AES это: 128, 192 и 256 бит. В структуре ниже, этот диапазон хранится как мин/макс значение ключа, и шаг прироста в виде поля "Increment".
C-подобный:
struct BCRYPT_KEY_LENGTHS_STRUCT
dwMinLen dd 0 ;// мин.значение ключа в битах
dwMaxLen dd 0 ;// макс.значение ключа
dwIncrement dd 0 ;// шаг ключа в битах
ends
В своём примере, сначала я запрашиваю тип операции = "симметричное шифрование", после чего перечисляю все алгоритмы, которые способны осуществить эту операцию. На следующем этапе, меняю тип на "хеширование данных" (умножаю предыдущее значение на 2) и так-же перечисляю её алгоритмы. В коде таких повторов 6, по числу поддерживаемых поставщиком Win криптографических действий. В самом конце я опять возвращаюсь к первому пункту "симметричное шифрованию", и вывожу уже детали каждого из алгоритмов. Это поможет прояснить общую картину инфраструктуры CNG:
C-подобный:
format pe console
entry start
;//------------
section '.inc' data readable
include 'win32ax.inc'
include 'equates\bcrypt.inc'
;//------------
.data
algCount dd 0
operation dd 1 ;// начинаем с "BCRYPT_CIPHER_OPERATION = 1"
algHndl dd 0
pLen dd 0
objLen dd 0
pcbResult dd 0
align 16
algList BCRYPT_ALGORITHM_IDENTIFIER
keyLen BCRYPT_KEY_LENGTHS_STRUCT
buff db 0
;//------------
.code
start: invoke SetConsoleTitle,<'*** CNG Enum algo ***',0>
cinvoke printf,<10,' Enum CNG Algorithm',\
10,' ***************************',\
10,' Symmetric cipher....: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
shl [operation],1
cinvoke printf,<10,' Hash algorithm......: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
shl [operation],1
cinvoke printf,<10,' Asymmetric cipher...: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
shl [operation],1
cinvoke printf,<10,' Secret agreement....: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
shl [operation],1
cinvoke printf,<10,' Signature...........: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
shl [operation],1
cinvoke printf,<10,' Random generator....: ',0>
invoke BCryptEnumAlgorithms,[operation],algCount,algList,0
call GetAlgoName
;// *********************************************
cinvoke printf,<10,10,' Symmetric algo info',\ ;//<----- детали симметричных алгоритмов!
10,' ***************************',0>
invoke BCryptEnumAlgorithms,BCRYPT_CIPHER_OPERATION,algCount,algList,0
call GetAlgoProperty
@exit: cinvoke _getch
cinvoke exit,0
;//------------
;//----- ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ ------------//
proc GetAlgoName ;//<---- выводит на консоль массив имён алгоритмов
mov ecx,[algCount]
mov esi,[algList.pszName]
mov esi,[esi]
@@: push esi ecx
cinvoke printf,<'%ls, ',0>,esi
pop ecx esi
@01: lodsw
cmp ax,0
jne @01
loop @b
ret
endp
;//------------
proc GetAlgoProperty ;//<---- запрашивает свойства по имени
mov ecx,[algCount]
mov esi,[algList.pszName]
mov esi,[esi]
@cycle: push esi ecx esi
cinvoke printf,<10,10,' %ls *********',0>,esi
;// Открыть алгоритм по имени (указатель на имя лежит в ESI)
pop esi
invoke BCryptOpenAlgorithmProvider,algHndl,esi,0,0
;// Размер блока шифрования
invoke BCryptGetProperty,[algHndl],BCRYPT_BLOCK_LENGTH,pLen,4,pcbResult,0
cinvoke printf,<10,' Block size...: %d byte',0>,[pLen]
;// Диапазон размеров ключей (и их шаг)
invoke BCryptGetProperty,[algHndl],BCRYPT_KEY_LENGTHS,keyLen,12,pcbResult,0
mov eax,[keyLen.dwMinLen]
mov ebx,[keyLen.dwMaxLen]
mov ecx,[keyLen.dwIncrement]
cinvoke printf,<10,' Key length...: %03d...%03d bit, increment = %d bit',0>,\
eax,ebx,ecx
;// Размер временного буфера под данные
invoke BCryptGetProperty,[algHndl],BCRYPT_OBJECT_LENGTH,objLen,4,pcbResult,0
cinvoke printf,<10,' Temp object..: %d byte',0>,[objLen]
pop ecx esi
@@: lodsw
cmp ax,0
jne @b
dec ecx
jnz @f
jmp @stop
@@: jmp @cycle
@stop: ret
endp
;//------------
section '.idata' import data readable
library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll',bcrypt,'bcrypt.dll'
include 'api\kernel32.inc'
include 'api\msvcrt.inc'
include 'api\bcrypt.inc'
Таким образом нам удалось получить неплохую голограмму инфраструктуры CNG, и это данные лишь одной из операций – симметричное шифрование. Лог в очередной доказывает, что алгоритм AES имеет размер входного блока 16-байт, и поддерживает три типа ключей: 128, 192 и 256 бит.
Зато его предшественник DES всех мастей, оперирует блоками по 8-байт, с фиксированными размерами ключей. Если классический DES производит над каждым своим блоком всего одну операцию шифрования, то 3DES повторяет её трижды (см.раунды).
А вот алгоритмы RC2 и RC4 в корень отличаются друг от друга, хотя и посещают одну синагогу. RC2 это блочный симметричный шифр с диапазоном ключей от 40 до 128 бит (с шагом в байт), в то время как RC4 относится к потоковым шифрам, т.к. он оперирует не блоками данных, а процеживает информацию по-байтно, шифруя на уровне бит.
Алгоритмы SHA и MD для хеширования – это стандартная практика. А вот то-что появился для этих целей AES-GMAC – это уже гуд. Что это такое мы обсудим в следующей части статьи, но если-бы нам приспичило получить хеш AES/GMAC на системе Win-XP, то пришлось-бы звать на помощь библиотеки сторонних разработчиков, такие как Crypto++. Начиная-же с Win-Vista данный алгоритм уже включён в состав ОС, и необходимость грузить непонятно кем написанные либы сама-собой отпадает.
Из асимметричных алго маячит только RSA, а больше нам и не надо – в этом сегменте RSA занимает позицию лидера. Кроме того имеем широкий выбор для создания цифровых подписей "Signature", и базовую тройку для генерации случайных чисел – это RNG (RandomGen мастдая), алгоритм одобренный институтом FIPS (Federal Information Processing Standard Publication), и DUAL_EC_RNG, что подразумевает "детерминированный генератор случайных бит с двойной эллиптической кривой".
6. Заключение
Наука о криптографии, а тем-более практическая её реализация, затягивает не по-детски. Если подходить к ней осмысленно, она открывает двери в такие закоулки системы, о которых мы и не подозревали. Но как и любое начинание, сначала нужно разобраться с теорией, пусть и не на уровне конкретных примитивов.
В следующей части запланировано несколько пруфов, которые докажут всё выше сказанное. Мы более подробно разберём современный и широко распространённый вид шифрования с тегами аутентификации AES-256 в режиме "GCM", узнаем что такое AEAD и в каком виде передаются зашифрованные данные, чтобы их можно было расшифровать. К примеру браузеры Chrome версии 80 и выше шифруют пароли юзеров и кукисы именно в режиме AES/GCM и мы убедимся, как легко их можно будет поиметь.
В скрепку положил инклуд для работы с библиотекой CNG на фасме,
а так-же исполняемый файл для вывода лога системного поставщика. На этом занавес – пока!
Вложения
Последнее редактирование: