首先,我只是为了学术目的而编写了以下代码。我说这个的原因是因为我没有将它放在生产环境中,因此我“绕过”了我需要做的一些开销,我只需要能够使用加密/解密字符串下面的代码。我能够做到这一点,但由于某种原因,我开始收到“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);
}
}
只在RSADecrypt调用上抛出此异常。
有什么想法吗?我在某处读到了可能与传入RSA.Decrypt的加密数据的预期大小有关。
由于 }
答案 0 :(得分:16)
使用字符串编码(即Encoding.Unicode
)来回转换明文。
使用Base-64(即Convert.[To/From]Base64String
)来回转换加密数据;
像这样:
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);
}
}
答案 1 :(得分:6)
http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx
不要通过字符串编码往返传输密文
人们在使用托管加密时犯的一个常见错误 类是他们试图存储加密的结果 通过使用其中一个Encoding类在字符串中操作。那 似乎有道理吗?毕竟,Encoding.ToString()需要一个 byte []并将其转换为一个完全相同的字符串 寻找。
...
相反,如果您想将密文转换为字符串,请使用 Base64编码。
...
每次都有效的代码结果,因为base 64编码是 保证能够准确表示任何输入字节序列。
这里有一个很好的正确例子: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
答案 2 :(得分:1)
RSA 并不意味着加密大型对象。如果你超过填充限制,你会得到例外。实际限制基于填充本身(使用false
表示您使用旧 PKCS#1 v1.5填充)和公钥长度(2048位)。
对大对象使用RSA
的正确方法是使用对称密钥(例如256位AES
密钥)加密大对象,并加密小使用RSA
公钥密钥。
您可以在blog上找到执行此类操作的代码。
答案 3 :(得分:0)
我遇到同样的问题,因为我把它放在我的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();
}
}
所以
示例强>
如果使用base64字符串编码加密
http://localhost:11430/orderpreview?orderID=t4RZrnefb2a%253d&price=27.9
然后点击动作“Application_BeginRequest”将其转换为
http://localhost:11430/orderpreview?orderID=t4rzrnefb2a%253d&price=27.9
你可以看到RZ被限制转换为小rz,这将使解密失败。
<强>解决方案强>
在RouteConfig类里面注册RegisterRoutes方法,如果你想要小写的网址
routes.Canonicalize().Www();
routes.Canonicalize().Lowercase();
routes.Canonicalize().NoTrailingSlash();