RijndaelManaged “Padding is invalid and cannot be removed” that only occurs when decrypting in production

霸气de小男生 提交于 2019-11-29 03:32:23

You will sometimes get a message about invalid padding when encryption and decryption for whatever reason have not used the same key or initialisation vector. Padding is a number of bytes added to the end of your plaintext to make it up to a full number of blocks for the cipher to work on. In PKCS7 padding each byte is equal to the number of bytes added, so it can always be removed after decryption. Your decryption has led to a string where the last n bytes are not equal to the value n of the last byte (hope that sentence makes sense). So I would double check all your keys.

Alternatively, in your case, I would suggest making sure that you create and dispose an instance of RijndaelManagedTransform for each encryption and decryption operation, initialising it with the key and vector. This problem could very well be caused by reusing this transform object, which means that after the first use, it is no longer in the right initial state.

I tend to explicitly call the FlushFinalBlock method on CryptoStream before closing it. That would mean doing the following in your encrypt method:

using (CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write))
{
    cs.Write(bytes, 0, bytes.Length);
    cs.FlushFinalBlock();        
}

If you don't do this, it may be that the encrypted data is being truncated - this would result in an "invalid padding" scenario. Padding is always present when using PKCS7, even if the data being encrypted is aligned to the block length of the cipher.

this results in character values that cannot be passed in a URL

Is there reason why you are using your own encoding, StrToByteArray, instead of Base64 encoding?

If you make these changes:

public string EncryptToString(string TextValue)
{
  return Convert.ToBase64String(Encrypt(TextValue));
}

public string DecryptToString(string TextValue)
{
  return Decrypt(Convert.FromBase64String(TextValue));
}

then things should work a lot better.

Edit:
Regarding problem with ToBase64String and QueryString:
If you do your own QueryString parsing then you need to make sure you only Split on the first =-sign.

var myURL = "http://somewhere.com/default.aspx?encryptedID=s9W/h7Sls98sqw==&someKey=someValue";
var myQS = myURL.SubString(myURL.IndexOf("?") + 1);
var myKVPs = myQS.Split("&");
foreach (var kvp in myKVPs) {
  // It is important you specify a maximum number of 2 elements
  // since the Base64 encoded string might contain =-signs.
  var keyValue = kvp.Split("=", 2);
  var key = keyValue[0];
  var value = keyValue[1];
  if (key == "encryptedID")
    var decryptedID = myAES.DecryptToString(value);
}

This way you don't need to replace any characters in your QueryString when it's Base64 encoded.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!