AlexMAS / GostCryptography

.NET driver for ViPNet CSP and CryptoPro CSP
MIT License
132 stars 42 forks source link

Шифрование файла по ГОСТ #7

Closed zlobkom closed 6 years ago

zlobkom commented 6 years ago

Александр, добрый день. Пытаюсь использовать вашу библиотеку в следующей задаче: PDF файл зашифровать через CryptoPro и сохранить полученный результат в БД.

Если использую код из примера:

var sharedKey = new Gost28147SymmetricAlgorithm();
var dataStream = new MemoryStream(Encoding.UTF8.GetBytes("Some data for encrypt..."));;

var encryptedDataStream = EncryptDataStream(sharedKey, dataStream);
var decryptedDataStream = DecryptDataStream(sharedKey, encryptedDataStream);

то dataStream совпадает с decryptedDataStream;

но если в dataStream кладу содержимое файла PDF,

dataStream = new MemoryStream(Convert.FromBase64String(obj.Content));

то дешифрованный результат не совпадает с исходным.

AlexMAS commented 6 years ago

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

Я думаю, что дело в размере данных и пример не совсем корректный. Попробуйте в методе шифрования, непосредственно после записи исходных данных в поток CryptoStream (см. L72) вызвать что-то типа CryptoStream.FlushFinalBlock(). Я думаю, что не все данные попали в encryptedDataStream, но могу ошибаться. Если получится, дайте знать. :)

var cryptoStream = new CryptoStream(encryptedDataStream, encryptor, CryptoStreamMode.Write);
dataStream.CopyTo(cryptoStream);
cryptoStream.FlushFinalBlock();

P.s. Вот тут также есть интересный комментарий.

zlobkom commented 6 years ago

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

Спасибо за помощь. Все заработало :)

zlobkom commented 6 years ago

Александр, помогите, еще раз, пожалуйста.

По моей задаче, мне файл надо зашифровать и сохранить в БД, потом его нужно расшифровать и показать пользователю.

если я создаю ключ через var key = new Gost28147SymmetricAlgorithm(); то он "живет" до конца выполнения блока. Т.к. мне не нужен уникальный ключ для каждого файла то я решил попробовать создавать ключ через var sharedKey = Gost28147SymmetricAlgorithm.CreateFromPassword(Encoding.ASCII.GetBytes("password")); Но наткнулся на то, что каждый вызов этой функции создает новый ключ.

Тогда решил, попробовать создать ключ, сохранить его в файл и использовать как общий ключ.

var sharedKey = Gost28147SymmetricAlgorithm.CreateFromPassword(Encoding.ASCII.GetBytes("password"));
var exportKey = sharedKey.EncodePrivateKey(new Gost28147SymmetricAlgorithm(), GostKeyExchangeExportMethod.GostKeyExport);
var newSharedKey =  exportKey.DecodePrivateKey(exportKey, GostKeyExchangeExportMethod.GostKeyExport);

но на последнем шаге падает Exception "Плохие данные".

Похоже, я делаю что-то не так :) но понять не могу

AlexMAS commented 6 years ago

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

AlexMAS commented 6 years ago

Получилось решить проблему?

zlobkom commented 6 years ago

Александр, простите, на радостях забыл отписаться.

Да, проблема решилась: создал сертификат 34.10-2001, а дальше по примеру. Была проблема не работы приложения в релизе... Долго разбирался, оказалось не хватает прав у пользователя IIS на доступ к ветке реестра.

Буду пробовать теперь на 2012 сертификат перевести. Думаю, все получится.

Еще раз большое спасибо за помощь )