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.
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.
Any ideas? I read somewhere it might have to do with the expected size of encryptedData that is passed into RSA.Decrypt.
Thanks
}
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);
}
}
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.
There is a good, correct example here:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
RSA is 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 false
means you're using the old PKCS#1 v1.5 padding) and the length of your public key (2048 bits).
The right way to use RSA
with large object is to encrypt the large object with a symmetric key (e.g. a 256 bits AES
secret key) and the encrypt this small key with your RSA
public key.
You can find code to do such things on my blog.
I had same problem this was because I put this in my Global.asax file to convert Url into lowercase.
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
http://localhost:11430/orderpreview?orderID=t4RZrnefb2a%253d&price=27.9
Then on hitting the action the "Application_BeginRequest" converting it into
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.
Solution
Inside RouteConfig class RegisterRoutes method put this if you want the url in lowercase
routes.Canonicalize().Www();
routes.Canonicalize().Lowercase();
routes.Canonicalize().NoTrailingSlash();