Как расшифровать данные с помощью RSACng, который ранее был зашифрован с помощью RSACryptoServiceProvider - PullRequest
2 голосов
/ 19 апреля 2019

Я мигрирую на RSACng для выпуска новой версии от RSACryptoServiceProvider.Однако, поскольку RSACryptoserviceProvider, который является CAPI, использует архитектуру Little Endian, а RSACng, то есть API CNG, использует архитектуру Big Endian, вопрос заключается в том, как я могу расшифровать данные с использованием API-интерфейса CNG, который ранее был зашифрован с использованием поставщика RSACryptoService (CAPI)?

Я уже пробовал Array.reverse (cypherText) и пытался расшифровать, используя CNG Api, но выдает ошибку «Параметр неверен».

Я также попробовал подход расшифровки половины зашифрованного текста, потому что CNG API использует заполнение RSAEncryptionPadding.OaepSHA512, тогда как CAPI использует заполнение OAEP.

Мой класс RSACryptoServiceProvider выглядит следующим образом: -

 public static void EncryptWithSystemKeyRSACryptoService(byte[] 
 plainBytes, bool representsUnicodeString, out string cypherText)
 {
                CspParameters cp = new CspParameters();
                cp.KeyContainerName = regValue.ToString();
                cp.Flags = CspProviderFlags.UseMachineKeyStore;
                cp.KeyNumber = (int)KeyNumber.Exchange;
                byte[] encBlockData=null;
                using (RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider(cp))
                {
                    res = CryptResult.GeneralError;
                    int keysize = rsaCSP.KeySize;


                     //This encrypts data and uses FOAEP padding
                    encBlockData = rsaCSP.Encrypt(plainBytes, true);
                }
                    //Should i have to reverse the Byte order?
                    // I am doing Array.reverse for encrypted data as it follows little endian architecture and CNG Api follows Big Endian architecture
                    Array.Reverse(encBlockData);
                    cypherText = BitConverter.ToString(encBlockData );
                    cypherText = cypherText.Replace("-", "");
                    cypherText = cypherText.ToLower();
 }

Вот как я шифрую данные с помощью провайдера RSACryptoservice (CAPI) Мой класс RSACng выглядит следующим образом: -

           //I am calling this to use RSACng API to get private keys
           private static byte[] SetPrivateAndPublicKeysAndDecrypt(byte[] cyphertext)
           {
                cp.KeyContainerName = regValue.ToString();
                cp.Flags = CspProviderFlags.UseMachineKeyStore;
                cp.KeyNumber = (int)KeyNumber.Exchange;

             using (RSACryptoServiceProvider rsaCSP = new 
             RSACryptoServiceProvider(cp))
            {
                res = CryptResult.GeneralError;
                keysize = rsaCSP.KeySize;
                q = rsaCSP.ExportCspBlob(false);
                RSAp = rsaCSP.ExportParameters(true);

            }
          //created cngKey
            cngKey = CngKey.Import(q, CngKeyBlobFormat.GenericPublicBlob);
             //created RSACng instance
             RSACng rsacng = new RSACng(cngKey)
            {
              KeySize = keysize
            };
              rsacng.ImportParameters(RSAp);
             //Decrypt using RSACng API using OAEPSHA512 padding
               var plainText= crypto.Decrypt(cyphertext, RSAEncryptionPadding.OaepSHA512);
        return plainText;
            }

Ожидаемый результат должен быть -> обычный текст успешно расшифрован

Фактический результат-> Обнаружено исключение-> 'Параметр неверен'.

1 Ответ

1 голос
/ 20 апреля 2019

Зашифрованный текст RSA определен для использования статического размера, без знака, кодировки с прямым порядком байтов в PKCS # 1 (которая задает шифрование PKCS # 1 v1.5 RSA и OAEP, как это реализовано большинством библиотек).Функция называется I2OSP в этом стандарте , и зашифрованный текст должен иметь тот же размер (в полных байтах), что и размер ключа.Если он не является прямым порядком байтов, то он не соответствует RSA / OAEP, другими словами.

То же самое относится и к обычным кодированным ключам ASN.1: они используют динамическое кодирование со знаком и прямым байтовым кодированием в соответствии св DER (отличительные правила кодирования).Эти ключи определены в стандартах PKCS # 1, PKCS # 8 и X.509, хотя они также могут быть встроены в хранилище ключей, совместимое с PKCS # 12, например.Иногда ключи затем также кодируют PEM, чтобы сделать их совместимыми с протоколами, для которых требуется текст, а не двоичный код.

Так что вам никогда не придется возвращать зашифрованный текст или ключи, которые используют один из стандартныхкодировок.То, что вычисления выполняются внутренне в порядке байтов (или нет), не имеет значения.Это верно для каждого современного шифра или другого криптографического примитива;ввод / вывод просто определяется в байтах с определенным порядком, а не числами.Только функции очень низкого уровня могут работать, например, со словами, что запутывает проблему (но вы не найдете этого в MS API).

Только собственные фирменные (хромые) кодировки клавиш Microsoft могут использовать младший порядковый номер.


bartonjs, конечно, правильно в комментариях ;вам необходимо сопоставить методы заполнения, и для OAEP используется хэш по умолчанию (точнее, функция генерации маски MGF1 в OAEP) - SHA-1.Есть много других ловушек, которых следует избегать, таких как правильное кодирование / декодирование открытого текста / зашифрованного текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...