AlexMAS / GostCryptography

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

Совместная работа КриптоПро и ВипНет #15

Closed Uriel6575 closed 5 years ago

Uriel6575 commented 5 years ago

День добрый.

Просто хотелось бы уточнить: проверялась ли работа библиотеки при одновременной установке в системе обоих криптопровайдеров?

При следующем вызове:

using (var gost28147 = new Gost_28147_89_SymmetricAlgorithm(provider.ProviderType)) {
    var encryptedData = new GostEncryptedXml(provider.ProviderType).EncryptData(xmlElement, gost28147, false);
    var encryptedKey = GostEncryptedXml.EncryptKey(
        gost28147,
        (GostAsymmetricAlgorithm)receiverCertificate.GetPublicKeyAlgorithm()
    );
}

У меня возникает вот такая ситуация:

System.Security.Cryptography.CryptographicException : Плохой ключ. в GostCryptography.Native.CryptoApiHelper.ExportCspBlob(SafeKeyHandleImpl symKeyHandle, SafeKeyHandleImpl keyExchangeHandle, Int32 blobType) в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeAlgorithm.EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, Int32 keyExchangeExportAlgId) в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter3.CreateKeyExchangeInfo(SymmetricAlgorithm keyExchangeAlgorithm) в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter3.CreateKeyExchangeData(SymmetricAlgorithm keyExchangeAlgorithm)

Причём речь идёт только про КриптоПро. ВипНет работает без проблем. Если удалить ВипНет из системы, то начинает работать и КриптоПро. 2001 или 2012 ГОСТ значения не имеет.

AlexMAS commented 5 years ago

Здравствуйте. Вы можете установить желаемый тип криптопровайдера явно. См. #13.

UPDATE. Тогда не нужно передавать его в конструктор(ы).

Uriel6575 commented 5 years ago

Вот как. Значит плохо искал. Прошу прощения. Теперь оно работает, благодарю.

Но тогда мне всё равно немного непонятна суть проблемы. Да, нам нужно зашифровать на сертификат. В сертификате указан OID алгоритма публичного ключа. В системе у нас зарегистрировано два провайдера, которые могут это сделать. Логично, что нужно выбрать какой-то один. Но ведь выходит так, что с использованием ВипНета зашифровать на КриптоПрошный сертификат не получается, раз появляется эта ошибка "Плохой ключ". Зачем тогда эта свобода выбора? Или я не прав?

AlexMAS commented 5 years ago

Да, вы правы. Проблема в том, что некоторые классы .NET Framework, которые выполняют криптографические операции, плохо или совсем не раширяются. В сценарии, который вы описали, так и происходит, только нужный класс создается из "недр" .NET Framework с использованием reflection и нет никакого способа как-то повлиять на этот процесс. Поэтому в некоторых сценариях "свобода выбора" (явное указание криптопровайдера), к сожалению, не работает. В целом это было сделано по двум причинам: 1) чтобы избавиться от hardcoded идентификаторов криптопровайдеров; 2) на будущее :) Наконец, есть ряд отличий при работе с VipNet и CryptoPro, которые проявляются при работе с ключами.

Uriel6575 commented 5 years ago

В общем выяснилось, что ошибка "Плохой ключ" возникает только если явно передавать тип провайдера через конструкторы. При задании его в GostCryptoConfig'е всё без проблем шифруется обоими криптопровайдерами друг на друга по всем вариантам ГОСТов. Так что смешивать конфиг и явное задание типов нельзя.