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

时间:2019-04-19 13:00:36

标签: cryptography endianness public-key-encryption rsacryptoserviceprovider cng

我正在从RSACngServiceProvider迁移到RSACng上以获取新版本。但是,由于CAPI的RSACryptoserviceProvider使用Little Endian体系结构,而CNG API的RSACng使用Big Endian体系结构,问题是我该如何使用以前使用RSACryptoService provider(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成功解密

Actual Resul->捕获到异常->'参数不正确'。

1 个答案:

答案 0 :(得分: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编码,以使其与需要文本而不是二进制的协议兼容。

因此永远不必颠倒使用标准编码之一的密文或密钥。无需在内部对little endian(或不进行)进行计算。对于每个现代密码或其他密码原语,都是如此。输入/输出只是以特定顺序的字节定义,而不是数字。只有非常低级的功能可能会在例如单词,这使问题变得混乱(但是您在MS API中找不到)。

只有Microsoft自己的专有(lam)键编码可以使用小尾数法。


bartonjs当然是correct in the comments;您需要匹配填充方法,并且用于OAEP的默认哈希(或者,OAEP中的掩码生成函数MGF1)为SHA-1。还有很多其他陷阱可以避免,例如对明文/密文执行正确的编码/解码。

相关问题