CryptoPro / libcore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Не устанавливается не извлекатся ключ на симметричном алгоритме шифрования

sentaniel opened this issue · comments

    using var gost = new Gost28147CryptoServiceProvider();
    using var keyGen = new GostRngCryptoServiceProvider();
    var key = new byte[32];
    keyGen.GetBytes(key);
    gost.Key = key;

пытаюсь установить ключ чтобы его в дальнейшем использовать для расшифровки публичного ключа сертификата. При записи и чтении свойства gost.Key возвращает всегда null

Добрый день.

Для секретных ключей в настоящий момент запрещён экспорт и импорт ключей в "сыром" виде. Для долгосрочного хранения симметричных ключей часто используют их экспорт на долговременном асимметричном ключе. Подробнее можно посмотреть в документации.

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

Добрый день.
Задача следующая.
Реализовать метод симметричным алгоритмом шифрующий публичный ключ сертификата. Который возвращает следующую модель

/// <summary>
/// Параметры для SymmetricAlgorithm
/// </summary>
public class SymmetricAlgorithmParams
{
    /// <summary>
    /// Ключ
    /// </summary>
    public string Key{ get; set; }
    /// <summary>
    /// данные о диверсификации ключа
    /// </summary>
    public string DiversData{ get; set; }
    /// <summary>
    /// вектор инициализации
    /// </summary>
    public string Iv{ get; set; }
}

соответсвенно с помощью этих данных в дальнешем необходимо уметь шифровать и расшифровывать какие-то данные

Task<byte[]> EncryptSymmetric(byte[] content, SymmetricAlgorithmParams algorithmParams);
Task<byte[]> DecryptSymmetric(byte[] content, SymmetricAlgorithmParams algorithmParams);

Зачем изначально шифровать открытый ключ сертификата на симметричном ключе?

Для предотвращения утечки данных третьим лицам, чтобы не светить ключ сертификата открытый

Симметричные ключи можно экспортировать только на асимметричном ключе, или другом симметричном ключе.
Примеры есть по ссылки в доке выше.

т.е.

  • генерируете симметричный ключ (создаёте объект Gost28147CryptoServiceProvider) или импортируете на долговременном асимметричном ключе
  • используете ключ для шифрования\расшифровывания
  • экспортируете ключ для долговременного хранения на долговременном асимметричном ключе (в случае надобности)

Альтернативно можно посмотреть в сторону PrfGostXXXX, в котором можно указать сырой ключ для prf и получить симметричный ключ через метод DeriveKey.

Подробнее об алгоритме выработки и параметрах см Р 50.1.113-2016

А подскажите в какой версии библиотеки можно PrfGost3411_2012_256 найти? В релизной последней версии LibCore.Windows 2024.1.10.1 не нашел такого класса и других аналогичных ему.

См последний пре-релиз.
https://github.com/CryptoPro/libcore/releases/tag/v2024.4.17

Спасибо, еще один вопрос для Gost3410_2012_256CryptoServiceProvider вижу убрали метод Encrypt который ранее был не реализованным. Есть где-то пример как можно зашифровать на основе публичного ключа сертификата этим алгоритмом? Ранее пытался таким кодом реализовать шифровку данных:

            using var gost = new Gost3410_2012_256CryptoServiceProvider();
            gost.ImportCertificatePublicKey(cert.GetPublicKey());
            gost.Encrypt(Convert.FromBase64String(request.Data));

Асимметрично зашифровать в сторону открытого ключа можно только другой ключ.

Если вам необходимо зашифровать данные в сторону открытого ключа, то вам нужно

  • создать сессионный симметричный ключ
  • зашифровать данные на симметричном ключе
  • зашифровать симметричный ключ в сторону открытого ключа

Примеры можно посмотреть в документации и в старый тестах

Альтернативно можно воспользоваться CMS или XML шифрованием.

Я видел эти примеры и именно так и реализовал. Но возникает проблема, что в плагине и в коде серверном на Php (который собственно пытаемся переписать на .Net) с использование библиотеки CryptoPro используется еще дополнительно по мимо сессионого ключа и вектора DiversData. Нашли ссылку на форум 4х летней давности https://www.cryptopro.ru/forum2/default.aspx?g=posts&t=18740 с аналогичным вопросом для старой версии библиотеки Sharpei. И в ответе там сказано что надо использовать Crypto-Pro CAdES 1.0 Type Library

// читаем сертификат с ключом из хранилища по отпечатку
var oStore = new CAPICOM.Store();
oStore.Open(CAPICOM.CAPICOM_STORE_LOCATION.CAPICOM_CURRENT_USER_STORE);
var certificates = (CAPICOM.Certificates)oStore.Certificates;
var cadesCert = certificates.Find(CAPICOM.CAPICOM_CERTIFICATE_FIND_TYPE.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, "<Отпечаток>", false)[1];
oStore.Close();

// импортируем симметричный ключ
var rSymAlgo = new CAdESCOM.SymmetricAlgorithm();
rSymAlgo.ImportKey(ExportedKey, cadesCert);
rSymAlgo.DiversData = DiversData;

// получаем сессионный ключ
var rSesKey = rSymAlgo.DiversifyKey();
rSesKey.IV = oSesKeyIV;
rSesKey.DiversData = DiversData;
var decryptedData = rSesKey.Decrypt(EncryptedData, true);

И приведен такой код. Подскажите пожалуйста можно ли средствами текущими библиотеки реализовать такую функциональность? Или надо CAdESCOM использовать тоже?

Если нужна совместимость с cades то пока единственный вариант использовать p/invoke + cades. В libcore не реализована диверсификация, используемая в cades и работа с блобами типа PUBLICKEYBLOBEX.

Если задача сделать что то похожее то можно использовать PRF + KeyExchange, как было указано выше.