Как я могу использовать большой двоичный объект ключа, сгенерированный из Win32 CryptoAPI, в моем приложении .NET?
-
09-06-2019 - |
Вопрос
У меня есть существующее приложение, написанное на C ++ для Windows.Это приложение использует Win32 CryptoAPI для генерации сеансового ключа TripleDES для шифрования / дешифрования данных.Мы используем показатель одного трюка экспортировать ключ сеанса в виде большого двоичного объекта, что позволяет хранить большой двоичный объект где-либо в расшифрованном формате.
Вопрос в том, как мы можем использовать это в нашем .СЕТЕВОЕ приложение (C #).Фреймворк инкапсулирует / оборачивает большую часть того, что делает CryptoAPI.Частично проблема заключается в том, что CryptAPI утверждает, что алгоритм TripleDES для Microsoft Усовершенствованный Поставщик криптографических средств равен 168 битам (3 ключа по 56 бит).Однако в .NET Framework указано, что их ключи равны 192 битам (3 ключа по 64 бита).По-видимому, 3 дополнительных байта в .NET framework предназначены для обеспечения четности?
В любом случае, нам нужно прочитать ключевую часть из большого двоичного объекта и каким-то образом иметь возможность использовать это в нашем .СЕТЕВОЕ приложение.В настоящее время мы не получаем ожидаемых результатов при попытке использовать ключ в .NET.Расшифровка с треском проваливается.Мы были бы очень признательны за любую помощь.
Обновить:
Я работал над способами решения этой проблемы и придумал решение, которое я опубликую со временем.Тем не менее, все равно был бы признателен за любые отзывы от других.
Решение
Вступление
Наконец-то я добираюсь до публикации решения.Я надеюсь, что это окажет некоторую помощь другим людям, которые, возможно, занимаются подобными вещами.На самом деле не так много упоминаний о том, чтобы делать это в другом месте.
Предварительные условия
Для того чтобы многое из этого имело смысл, необходимо прочитать показатель одного трюка, который позволяет вам экспортировать сеансовый ключ в большой двоичный объект (хорошо известная байтовая структура).Затем можно делать с этим потоком байтов все, что угодно, но он содержит самый важный ключ.
Документация MSDN сбивает с толку
В этом конкретном примере я использую Microsoft Усовершенствованный Поставщик криптографических средств, с Тройным DES (CALG_3DES) алгоритм.Первое, что бросило меня в дрожь, был тот факт, что длина ключа указана в 168 битах при длине блока 64 бита.Как длина ключа может быть 168?Три ключа по 56 бит?Что происходит с другим байтом?
Итак, с этой информацией я начал читать в другом месте, что последний байт на самом деле равен четности, и по какой-то причине CryptoAPI удаляет это.Так ли это на самом деле?Кажется немного сумасшедшим, что они пошли бы на это, но ладно.
Использование ключа в .NET
Используя TripleDESCryptoServiceProvider ( Поставщик услуг Tripledescryptoservice ), Я заметил , что замечания в документах указывают на то , что:
Этот алгоритм поддерживает длину ключа от 128 до 192 бит с шагом в 64 бита.
Итак, если CryptoAPI имеет длину ключа 168, как я могу ввести это в.СЕТЬ, которая поддерживает только поддержку, кратную 64?Следовательно, .Сетевая часть API учитывает четность, в отличие от CryptoAPI.Как можно было себе представить... я был сбит с толку.
Итак, учитывая все это, я пытаюсь выяснить, как восстановить ключ на стороне .NET с надлежащей информацией о четности.Выполнимо, но не очень весело...давайте просто оставим все как есть.Как только я все это поставил на место, все закончилось полным провалом с БОЛЬШОЙ буквы F.
Все еще со мной?Хорошо, потому что я только что снова упал с лошади.
Электрические лампочки и фейерверки
Низко и вот, когда я просматриваю MSDN для получения каждого последнего бита информации, я нахожу конфликтующий фрагмент в Win32 Ключ CryptExportKey функция.Низко и вот я нахожу этот кусочек бесценной информации:
Для любой из перестановок ключей DES, использующих PLAINTEXTKEYBLOB, может быть экспортирован только полный размер ключа, включая бит четности.Поддерживаются следующие размеры клавиш.
Поддерживаемый алгоритмом размер ключа
CALG_DES 64 бита
CALG_3DES_112 128 бит
CALG_3DES 192 бита
Таким образом, он экспортирует ключ, кратный 64 битам!У-у-у!Теперь исправим код на стороне .NET.
Настройка кода импорта .NET
Порядок байтов важно иметь в виду при импорте потока байтов, содержащего ключ, который был экспортирован в виде большого двоичного объекта из CryptoAPI.Следовательно, два API не используют одинаковый порядок байтов, поскольку @nic-сильный указывает, что обращение массива байтов вспять необходимо перед фактической попыткой использования ключа.В остальном все работает так, как ожидалось.Просто решаемая:
Array.Reverse( keyByteArray );
Заключение
Я надеюсь, что это кому-то там поможет.Я потратил слишком много времени, пытаясь отследить это.Оставляйте любые комментарии, если у вас возникнут дополнительные вопросы, и я попытаюсь помочь вам уточнить любые детали.
Счастливой Криптографии!
Другие советы
Хорошо, забудьте последний ответ, который я не могу прочитать :) Вы работаете с ключами 3Des, а не с ключами RSA.
Я работал над кучей кода для обмена ключами между .NET, CryptoAPI и openssl.Здесь я нашел много хороших примеров кода для выполнения ключевых преобразований:
http://www.jensign.com/JavaScience/cryptoutils/index.html
В некоторых из этих примеров есть кое-что из 3des, но это было связано с openssl -> .NET iirc.
Я также только что просмотрел код ключа RSA, и одна вещь, которую я заметил, что я делаю, - это использование Array.Reverse() для всех ключевых частей ключа RSA (D, DP, DQ, InverseQ, Modulus, P, Q), я думаю, для преобразования конечного символа.Я помню, что это было неочевидно, когда я впервые взялся за решение проблемы.
Надеюсь, что-то из этого поможет.Удачи.