C# RSA解密异常:要解密的数据长度对于此密钥的大小无效

C# RSA解密异常:要解密的数据长度对于此密钥的大小无效,c#,encryption,cryptography,aes,rsa,C#,Encryption,Cryptography,Aes,Rsa,我有一个Angular+Net核心应用程序,带有(RSA+AES)加密连接。 客户的所有请求都是通过POST发送的。(下面将为您提供一个示例 下面提供的脚本运行良好,但在5%的情况下会引发异常: 要解密的数据长度对于此密钥的大小无效 行中: 加密部分(前端) } 解密部分(C#后端) 示例,用户希望按id打开页面 前端: 1) 使用AES对请求Id进行加密 2) 使用RSA加密AES的密钥和iv 3) 发送到后端 后端: 1) 使用RSA解密AES的密钥和值在请求失败的情况下,Base64解码加

我有一个Angular+Net核心应用程序,带有(RSA+AES)加密连接。 客户的所有请求都是通过POST发送的。(下面将为您提供一个示例

下面提供的脚本运行良好,但在5%的情况下会引发异常:

要解密的数据长度对于此密钥的大小无效 行中:

加密部分(前端)

}

解密部分(C#后端)

示例,用户希望按id打开页面

前端:
1) 使用AES对请求Id进行加密 2) 使用RSA加密AES的密钥和iv 3) 发送到后端

后端:

1) 使用RSA解密AES的密钥和值在请求失败的情况下,Base64解码加密AES密钥的长度为255字节。对于2048位RSA密钥,它实际上应该是256个字节,对于其余数据也是如此

对于RSA encryption,使用了JSEncrypt,它有一个已知的错误,偶尔会导致密文太短,这可能是您的问题的原因,请参阅。此错误于2019年7月打开,尚未修复

在JSEncrypt中,正确处理过短的密文,因此不会发生错误。然而,跨平台的情况通常不是这样,因为太短的密文严格来说是无效的,因此一些编程语言将其识别为无效的,例如,显然C#是另一种

如果用
0x00
手动将太短的密文从左边填充到模数的长度,则该密文也应该可以在C代码中解密

更新:

  • 我已使用您的代码成功测试了建议的修复程序。密文可以固定在JavaScript或C代码中。JavaScript端的一个可能实现是,例如,键:

    encryptedKey = btoa(atob(encryptedKey).padStart(256, "\0"));
    
    其中,
    encryptedKey
    是由
    JSEncrypt\encrypt
    返回的Base64编码密文。为确保此更正不会应用于已具有正确长度的密文,长度检查非常有用:长度
    4*Math.ceil(256/3)
    的Base64编码密文不需要固定,因为它对应于长度为256字节的正确密文,请参阅

  • 为加密设置公钥时,请应用JSEncrypt部分中的方法
    setPrivateKey
    ,正确的方法是
    setPublicKey
    ,请参阅。然而,JSEncrypt似乎在内部解决了这个问题,因为它也可以工作。尽管如此,它还是应该改变,因为它具有误导性

  • 正如@kelalaka在评论中已经提到的,IV不是秘密,不需要加密


如果您想使用RSA传输密钥,您应该使用。不幸的是,RSA-KEM在C#+JavascriptWell、PKCS#1 v1.5版本中还没有得到很好的支持,开销至少为11字节。我们仍然可以使用所有可能的输入空间来输入HKDF的关键材料。这在密钥生成方面更好。+1不需要加密IV。它可以清楚地预先设置为密文+2人们应该更喜欢RSA-KEM.Topaco-你认为如果我手动将0x00添加到所有破解的加密密钥中,应该可以解决问题吗?是的,我希望填充原始密文(即Base64解码密文)如果将0x00值设置为正确的长度,则应该可以解决问题。@DenisEvseev-我已成功地使用您的代码测试了建议的修复,并在我的答案的更新部分描述了详细信息。非常感谢您,Topaco-我将在4小时内打50分
encrypt(requestObj:any):any {  
var rsaEncrypt = new JsEncryptModule.JSEncrypt();
var key = this.generateAesKey(32); //secret key
var iv = this.generateAesKey(16); //16 digit

var stringifiedRequest = CryptoJS.enc.Utf8.parse(JSON.stringify(requestObj));
var aesEncryptedRequest = CryptoJS.AES.encrypt(stringifiedRequest, 
CryptoJS.enc.Utf8.parse(key), 
{ 
  keySize: 128 / 8,
  iv: CryptoJS.enc.Utf8.parse(iv),
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC
 });

rsaEncrypt.setPrivateKey(this.publicPemKey);
var encryptedKey = rsaEncrypt.encrypt(key);
var encryptedIV  = rsaEncrypt.encrypt(iv);

var encryptedRequestObj = {
    k: encryptedKey,
    v: encryptedIV,
    r: aesEncryptedRequest.toString()
 };

return encryptedRequestObj;
var decryptedAesKey = Encoding.UTF8.GetString(rsaCng.Decrypt(Convert.FromBase64String(request.k), 
RSAEncryptionPadding.Pkcs1));
var decryptedAesIV = Encoding.UTF8.GetString(rsaCng.Decrypt(Convert.FromBase64String(request.v), RSAEncryptionPadding.Pkcs1));

byte[] encryptedBytes = request.r;
AesCryptoServiceProvider aes = new AesCryptoServiceProvider()
{
    Mode = CipherMode.CBC,
    Padding = PaddingMode.PKCS7,
    Key = Encoding.UTF8.GetBytes(decryptedAesKey),
    IV = Encoding.UTF8.GetBytes(decryptedAesIV)
};

ICryptoTransform crypto = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] secret = crypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
crypto.Dispose();

requestJson = Encoding.UTF8.GetString(secret);
{ "k":"L+ikMb/JGvFJmhBpADMGTVLFlkHOe69dZUVSQ5r7yHCvWSwY2x6KMR274ByflF0lDMYdCmywo+Nfq6JUybRctDqmAp8UFHXnhwBAv49d99mF5x2yGbJr/j0cn6EZyhweNK4p97i5yMM6MQtluZTIErpsUa22Cajtj8F+xl0jJPUMXIf8cs2X+ooFr5VP/p/vlbPmnEY3K/hMCRZRdXMkEqaCWoA5EnYMTQABtRXPZWgLSQwJpr4dqEAhGCBtga1AGsKF3dQCsKO92NYyst0ngkBiKwFNfy1QDwbk4SzKAKeBckaY17SHt526NMvpEv08BGV6btBxcM+ypsmpB4o0",
"v":"LIndJOjUgKHDlXqwpg7uSmDuut3oi5z9L/GKm2KgU7P2EXmf/JIpXM0JgpTXPJL7wUTndq3F9UMlMdU70JBOV56x/4uIBRbHbyvaG2JZYxbBZblwyYgdo1ZcK1OSE4k5oesQmMEGNEk9RVu+EZO4xAme6+mlyd2/Y/709jaC90PuiOG/k/4JMTTI/2q4s7tk6IgSxLBT8ZiOtgJVGdasSaAksEBMRHyUkzAIr5tSUw1VXedwJFPfwQT2nOD5dU2cxiNJKOwtO9uAYXly0U0FDoa/nkWskca8zaU+4EiPikJ6Km7phViH9JvwZFgHhBj+8FM6Jof+AdrY3q1dcMLFlg==",
"r":"OJnA3wFoKKG+iu4FciXyJg=="
}
{   "k":"uW8d7vIzlgkEkKTkDnHbBZeqKwdgoG+1BVZ/NUiC0pZ/LqZM9aUasQSx+qDg+X50ur30uRnEyAyIZXruYeHQb8cacx5mvr9LWLud+wueJXsOlEEdocD/4A1DfE9TDFdnTaVcMSIwhSVlLPUjO7ubJdANY9yK4S+vb0IyPbsrYpAT7ho01mDkvsH1rZsId/TmzQadmsGhThowu+mrQlz78rrdlN8nI5LnUQHXRNWMUgBvuteTpVBmyrfnIELIKoo/jI6Nj4rGPQBf7+2OOoZPs0Y1GtjXxUCTAt7madNLKSOdaPjdWjaOfGSwnymDNeEFyJQOmAwHZoOGYNd2B/UhQQ==",
"v":"IimiJFcKv5ZHWHljJixX0LUgV4I2GWAWPbk7dWHVhwmHEhTHA/hCdih/E1wiWFS+0KaL05ZobiZInyK7gCwYPHaz0aRCSQtVeBPiFg4f7L0gwfvk1GHwJ1wZjqNJZaYf0elXJzc2l5BwN+aXNWaNJDPA7M6kfK6UPkq84IV3ohCQcTuC8zPM7aMJHxpz9IudcrMmYIkeqrj9Do88CkTLv8yg5hk3EASPk9HqsUieuQixggv/8ZlHnp00iftc62LJlIuCkGn4WR3FkMdFdqpKXf6Ebj8PU1HOmokEtKtYJiOZ5JxieZO5Pnd+ez6sO7khIbdRFDhAQ20chsxKUypezw==",
"r":"2mbUgU44JFFDlWu8As2RIw=="
}
encryptedKey = btoa(atob(encryptedKey).padStart(256, "\0"));