C# “坏数据”加密异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9659898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Bad Data" CryptographicException
提问by TheJediCowboy
First, I have only written the code below for academic purposes. The reason I say this is because I am not putting this in a production environment, and therefor am "bypassing" some of the overhead that I would need to do if I was, I simply need to be able to encrypt/decrypt a string using the code below. I was able to do it a few time, but for some reason, I started receiving "CryptographicException Bad Data" and am not sure what might be causing the problem.
首先,我仅出于学术目的编写了以下代码。我这么说的原因是因为我没有把它放在生产环境中,因此我“绕过”了一些我需要做的开销,我只需要能够加密/解密一个字符串使用下面的代码。我能够做到几次,但由于某种原因,我开始收到“CryptographicException Bad Data”并且不确定是什么原因导致了问题。
private string RSAEncrypt(string value)
{
byte[] encryptedData = Encoding.Unicode.GetBytes(value);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = _rsaContainerName;
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048,cspParams))
{
encryptedData = RSA.Encrypt(encryptedData, false);
return Convert.ToBase64String(encryptedData);
}
}
private string RSADecrypt(string value)
{
byte[] encryptedData = Encoding.Unicode.GetBytes(value);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = _rsaContainerName;
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048,cspParams))
{
encryptedData = RSA.Decrypt(encryptedData,false);
return Convert.ToBase64String(encryptedData);
}
}
It is only throwing this exception on the RSADecrypt call.
它只是在 RSADecrypt 调用上抛出这个异常。
Any ideas? I read somewhere it might have to do with the expected size of encryptedData that is passed into RSA.Decrypt.
有任何想法吗?我在某处读到它可能与传递到 RSA.Decrypt 的加密数据的预期大小有关。
Thanks }
谢谢 }
采纳答案by Rasmus Faber
Convert the plaintext back and forth using a string-encoding (i.e.
Encoding.Unicode).Convert the encrypted data back and forth using Base-64 (i.e.
Convert.[To/From]Base64String);
使用字符串编码来回转换明文(即
Encoding.Unicode)。使用 Base-64 来回转换加密数据(即
Convert.[To/From]Base64String);
Like this:
像这样:
private string RSAEncrypt(string value)
{
byte[] plaintext = Encoding.Unicode.GetBytes(value);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = _rsaContainerName;
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048,cspParams))
{
byte[] encryptedData = RSA.Encrypt(plaintext, false);
return Convert.ToBase64String(encryptedData);
}
}
private string RSADecrypt(string value)
{
byte[] encryptedData = Convert.FromBase64String(value);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = _rsaContainerName;
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048,cspParams))
{
byte[] decryptedData = RSA.Decrypt(encryptedData,false);
return Encoding.Unicode.GetString(decryptedData);
}
}
回答by matthewk
http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx
http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx
Don't Roundtrip Ciphertext Via a String Encoding
One common mistake that people make when using managed encryption classes is that they attempt to store the result of an encryption operation in a string by using one of the Encoding classes. That seems to make sense right? After all, Encoding.ToString() takes a byte[] and converts it to a string which is exactly what they were looking for.
...
Instead if you want to convert the ciphertext into a string, use Base64 encoding.
...
Results in code that works every time, since base 64 encoding is guaranteed to be able to accurately represent any input byte sequence.
不要通过字符串编码来回密文
人们在使用托管加密类时犯的一个常见错误是,他们尝试使用 Encoding 类之一将加密操作的结果存储在字符串中。这似乎有道理吧?毕竟, Encoding.ToString() 接受一个 byte[] 并将其转换为一个字符串,这正是他们正在寻找的。
...
相反,如果要将密文转换为字符串,请使用 Base64 编码。
...
结果是每次都能运行的代码,因为 base 64 编码保证能够准确地表示任何输入字节序列。
There is a good, correct example here: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
这里有一个很好的正确示例:http: //msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
回答by poupou
RSAis not meant to encrypt large objects. You'll get exceptions is you go over the padding limit. The actual limit is based on the padding itself (using falsemeans you're using the oldPKCS#1 v1.5 padding) and the length of your public key (2048 bits).
RSA不是为了加密大对象。如果超过填充限制,您会得到例外。实际限制基于填充本身(使用false意味着您使用旧的PKCS#1 v1.5 填充)和公钥的长度(2048 位)。
The right way to use RSAwith large object is to encrypt the large object with a symmetric key (e.g. a 256 bits AESsecret key) and the encrypt this smallkey with your RSApublic key.
使用RSA大对象的正确方法是使用对称密钥(例如 256 位AES密钥)加密大对象,然后使用您的公钥加密这个小RSA密钥。
You can find code to do such things on my blog.
您可以在我的博客上找到执行此类操作的代码。
回答by TAHA SULTAN TEMURI
I had same problem this was because I put this in my Global.asax file to convert Url into lowercase.
我有同样的问题,这是因为我把它放在我的 Global.asax 文件中以将 Url 转换为小写。
protected void Application_BeginRequest(object sender, EventArgs e)
{
// Don't rewrite requests for content (.png, .css) or scripts (.js)
if (Request.Url.AbsolutePath.Contains("/Content/") ||
Request.Url.AbsolutePath.Contains("/Scripts/"))
return;
If uppercase chars exist, redirect to a lowercase version
var url = Request.Url.ToString();
if (Regex.IsMatch(url, @"[A-Z]"))
{
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
Response.AddHeader("Location", url.ToLower());
Response.End();
}
}
So
所以
Example
例子
If encryption is done with base64 string encode as
如果加密是用 base64 字符串编码完成的
http://localhost:11430/orderpreview?orderID=t4RZrnefb2a%253d&price=27.9
http://localhost:11430/orderpreview?orderID=t4RZrnefb2a%253d&price=27.9
Then on hitting the action the "Application_BeginRequest" converting it into
然后点击操作“Application_BeginRequest”将其转换为
http://localhost:11430/orderpreview?orderID=t4rzrnefb2a%253d&price=27.9
http://localhost:11430/orderpreview?orderID=t4rzrnefb2a%253d&price=27.9
You can see the RZ was captial converted into small rz this will fail the decryption.
你可以看到 RZ 被大写转换成小 rz 这将导致解密失败。
Solution
解决方案
Inside RouteConfig class RegisterRoutes method put this if you want the url in lowercase
如果您希望 url 为小写,则在 RouteConfig 类 RegisterRoutes 方法中放置它
routes.Canonicalize().Www();
routes.Canonicalize().Lowercase();
routes.Canonicalize().NoTrailingSlash();

