我正在从RSACngServiceProvider迁移到RSACng上以获取新版本。但是,由于CAPI的RSACryptoserviceProvider使用Little Endian体系结构,而CNG API的RSACng使用Big Endian体系结构,问题是我该如何使用以前使用RSACryptoService provider(CAPI)加密的CNG Api解密数据?
我已经尝试过Array.reverse(cypherText)并尝试使用CNG Api进行解密,但是它引发了错误,“参数不正确”。
我的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->捕获到异常->'参数不正确'。
答案 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。还有很多其他陷阱可以避免,例如对明文/密文执行正确的编码/解码。