CryptoPro / libcore

44 stars 0 forks source link

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

Closed sentaniel closed 5 months ago

sentaniel commented 5 months ago
    using var gost = new Gost28147CryptoServiceProvider();
    using var keyGen = new GostRngCryptoServiceProvider();
    var key = new byte[32];
    keyGen.GetBytes(key);
    gost.Key = key;

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

Fasjeit commented 5 months ago

Добрый день.

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

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

sentaniel commented 5 months ago

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

/// <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);
Fasjeit commented 5 months ago

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

sentaniel commented 5 months ago

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

Fasjeit commented 5 months ago

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

т.е.

Fasjeit commented 5 months ago

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

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

sentaniel commented 5 months ago

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

Fasjeit commented 5 months ago

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

sentaniel commented 5 months ago

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

            using var gost = new Gost3410_2012_256CryptoServiceProvider();
            gost.ImportCertificatePublicKey(cert.GetPublicKey());
            gost.Encrypt(Convert.FromBase64String(request.Data));
Fasjeit commented 5 months ago

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

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

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

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

sentaniel commented 5 months ago

Я видел эти примеры и именно так и реализовал. Но возникает проблема, что в плагине и в коде серверном на 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 использовать тоже?

Fasjeit commented 5 months ago

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

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