如何使用先前使用RSACryptoServiceProvider加密的RSACng解密数据

问题描述 投票:2回答:1

我正在RSACng上迁移RSACryptoServiceProvider的新版本。但是,由于CAPI的RSACryptoserviceProvider使用Little Endian Architecture和CNAC API的RSACng正在使用Big Endian架构,问题是我如何使用之前使用RSACryptoService提供程序(CAPI)加密的CNG Api解密数据?

我已经尝试了Array.reverse(cypherText)并尝试使用CNG Api进行解密,但是它抛出了错误,'参数不正确'。

  1. 我还尝试了解密一半密文的方法,因为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 Provider(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;
            }

预期的结果应该是 - > plainText成功解密

实际结果 - >异常捕获 - >'参数不正确'。

cryptography endianness public-key-encryption rsacryptoserviceprovider cng
1个回答
1
投票

RSA密文定义为在PKCS#1中使用静态大小的无符号大端编码(其指定由大多数库实现的PKCS#1 v1.5 RSA加密和OAEP加密)。该函数称为I2OSP within that standard,密文应与密钥大小具有相同的大小(以字节为单位)。如果它不是大端,那么它就不符合RSA / OAEP,换句话说。

对于普通的ASN.1编码密钥也是如此:它们根据DER(区分编码规则)使用动态大小,带符号的大端编码。这些密钥在PKCS#1,PKCS#8和X.509标准中定义,但它们也可以嵌入PKCS#12兼容密钥存储区中 - 例如。有时,密钥也会被PEM编码,以使它们与需要文本而不是二进制的协议兼容。

因此,您永远不必反转使用标准编码之一的密文或密钥。计算是在小端(或不是)内部执行的,无关紧要。对于每个现代密码或其他加密原语都是如此;输入/输出只是以字节为单位定义,具有特定顺序,而不是数字。只有非常低级别的功能才可能在例如单词,这会混淆问题(但你不会在MS API中找到它)。

只有微软拥有专有(跛脚)密钥编码才可能使用小端。


bartonjs当然是correct in the comments;您需要匹配填充方法,并且用于OAEP的默认哈希(或者更确切地说,OAEP中的掩码生成功能MGF1)是SHA-1。还有许多其他缺陷需要避免,例如执行明文/密文的正确编码/解码。

© www.soinside.com 2019 - 2024. All rights reserved.