AlexMAS / GostCryptography

.NET driver for ViPNet CSP and CryptoPro CSP
MIT License
128 stars 41 forks source link

Как расшифровать текст при помощи алгоритма ассиметричного ключа #51

Open IverCold opened 2 months ago

IverCold commented 2 months ago

Добрый день! Я не смог найти в примерах возможности расшифровки текста ассиметричным ключом. Как это можно сделать?

AlexMAS commented 2 months ago

Здравствуйте!

Полагаю, что вам подойдёт этот пример. Основную роль играют KeyExchangeFormatter/KeyExchangeDeformatter, экземпляры которых создаются на основе асимметричного ключа. Симметричный ключ может быть как постоянным (например, храниться в конфигурациионном файле приложения), так и случайным (если будет организован способ передачи параметров симметричного ключа от отправителя к получателю зашифрованных данных).

IverCold commented 2 months ago

Я пробовал реализовать этот пример. Дело в том, что я отправляю открытый ключ в Контур, и они возвращают мне строку, которую я должен расшифровать с помощью закрытой части сертификата. Это выглядит вот так:

            var encryptedStr = "здесь_длинная_полученная_строка";
            var encryptedBytes = Convert.FromBase64String(encryptedStr);
            var encryptedStream = new MemoryStream(encryptedBytes);
            var privateKeyAlgorithm = (GostAsymmetricAlgorithm)cert.GetPrivateKeyAlgorithm();

            var deformatter = privateKeyAlgorithm.CreateKeyExchangeDeformatter();
            using (var receiverSessionKey = deformatter.DecryptKeyExchangeAlgorithm(encryptedBytes))
            {
                var decryptedString = receiverSessionKey.ToString();
            }

Но на строке using код падает в ошибки: CryptographicException: ASN.1 encoded byte array contains invalid structure 'Gost_R3410_KeyTransport'. CryptographicException: ASN.1 decode error. SEQUENCE or SET is missing a required element. Offset: 2.

В чём тут может быть проблема?

AlexMAS commented 2 months ago

Вам нужно внимательней посмотреть на указанный пример.

Метод DecryptKeyExchangeAlgorithm() делает дешифрацию общего секретного ключа, т.е. на вход он получает зашифрованный симметричный ключ. Как я понял, вы передаете ему не ключ, а зашифрованные данные. Для шифрации/дешифрации данных используется поток CryptoStream.

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

IverCold commented 2 months ago

Я просто подумал, что есть вариант как-то выдернуть часть реализации расшифровки сообщения. Если я правильно понимаю, то речь идёт о расшифровке сообщения, зашифрованного открытым ключом сертификата. А значит его можно расшифровать закрытым ключом сертификата. Подобно объекту RSACryptoServiceProvider, в котором есть методы .Encrypt(byte[]), .Decrypt(byte[]).

AlexMAS commented 2 months ago

Да, действительно, RSA имеет методы Encrypt()/Decrypt(). Однако примечательно, что его нет среди методов базового класса AsymmetricAlgorithm. Судя по коду RSACryptoServiceProvider, внутри вызываются методы EncryptKey()/DecryptKey(), что наводит на мысль, что под данными подразумевается все-таки ключ (симметричного) шифрования, а не сами данные. Вам действительно не передают зашифрованный симметричный ключ, только зашифрованные данные? Если так, то я попробую изучить тему глубже, может что-то и получится. :)

AlexMAS commented 2 months ago

@IverCold Если вопрос решен, предлагаю поделиться решением и закрыть задачу. :)

IverCold commented 2 months ago

@AlexMAS Я лучше приложу инструкцию Контура, которую они мне дали. Нужно получить Access Token. Его можно получить по логину-паролю (как мы делаем сейчас), а можно по сертификату (так должно быть безопаснее). Чтобы получить токен по сертификату расшифровать случайный контент, который присылает Контур. Сам же инструкция вот здесь: https://developer.testkontur.ru/doc/openidconnect?about=2

IverCold commented 2 months ago

@IverCold Если вопрос решен, предлагаю поделиться решением и закрыть задачу. :)

Ну, я не настолько хорош, чтобы предложить решение в рамках вашей библиотеки = ) Но невероятная благодарность от меня за её существование. Без неё мы бы просто не взлетели - мы используем реализацию raw подписи для Контура/СФР как раз.

AlexMAS commented 2 months ago

Спасибо за обратную связь! :)

Понятно, то есть вам не удалось выполнить аутентификацию по сертификату. А можете прикрепить файл с base64 этого encrypted_key, я попробую посмотреть ее через ASN.1-редактор. Может что-то прояснится, что они присылают в ответ. :)

AlexMAS commented 2 months ago

@IverCold Здравствуйте! У вас нет примера encrypted_key? :)