RijndaelManaged "Padding est invalide et ne peut pas être supprimé" qui se produit uniquement lors du décryptage en production
Je sais que d'autres questions ont été posées sur ce sujet, mais aucun à ce jour ont fourni une solution ou sont exactement le problème que j'ai.
La classe ci-dessous gère le chiffrement et le déchiffrement des cordes, la clé et le vecteur passé en sont TOUJOURS les mêmes.
Les chaînes cryptées et décryptées sont toujours des nombres, plus de travail, mais parfois on échoue lors du déchiffrement (mais uniquement sur le serveur de production). Je devrais mentionner que les locaux et les environnements de production sont en IIS6 sur Windows Server 2003, le code qui utilise la classe se trouve dans un .ashx gestionnaire. L'exemple qui échoue sur le serveur de production est "0000232668"
Le message d'erreur est
Système.De sécurité.La cryptographie.CryptographicException: Rembourrage est pas valide et ne peut pas être supprimé.
au Système.De sécurité.La cryptographie.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
Et pour le code
public class Aes
{
private byte[] Key;
private byte[] Vector;
private ICryptoTransform EncryptorTransform, DecryptorTransform;
private System.Text.UTF8Encoding UTFEncoder;
public Aes(byte[] key, byte[] vector)
{
this.Key = key;
this.Vector = vector;
//our encyption method
RijndaelManaged rm = new RijndaelManaged();
rm.Padding = PaddingMode.PKCS7;
//create an encryptor and decyptor using encryption method. key and vector
EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);
//used to translate bytes to text and vice versa
UTFEncoder = new System.Text.UTF8Encoding();
}
///Encrypt some text and return a string suitable for passing in a URL.
public string EncryptToString(string TextValue)
{
return ByteArrToString(Encrypt(TextValue));
}
///Encrypt some text and return an encrypted byte array.
public byte[] Encrypt(string TextValue)
{
//Translates our text value into a byte array.
Byte[] bytes = UTFEncoder.GetBytes(TextValue);
Byte[] encrypted = null;
//Used to stream the data in and out of the CryptoStream.
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write))
{
cs.Write(bytes, 0, bytes.Length);
}
encrypted = memoryStream.ToArray();
}
return encrypted;
}
///The other side: Decryption methods
public string DecryptString(string EncryptedString)
{
return Decrypt(StrToByteArray(EncryptedString));
}
///Decryption when working with byte arrays.
public string Decrypt(byte[] EncryptedValue)
{
Byte[] decryptedBytes = null;
using (MemoryStream encryptedStream = new MemoryStream())
{
using (CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write))
{
decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
}
decryptedBytes = encryptedStream.ToArray();
}
return UTFEncoder.GetString(decryptedBytes);
}
///Convert a string to a byte array. NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so).
// System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
// return encoding.GetBytes(str);
//However, this results in character values that cannot be passed in a URL. So, instead, I just
//lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100).
public byte[] StrToByteArray(string str)
{
if (str.Length == 0)
throw new Exception("Invalid string value in StrToByteArray");
byte val;
byte[] byteArr = new byte[str.Length / 3];
int i = 0;
int j = 0;
do
{
val = byte.Parse(str.Substring(i, 3));
byteArr[j++] = val;
i += 3;
}
while (i < str.Length);
return byteArr;
}
//Same comment as above. Normally the conversion would use an ASCII encoding in the other direction:
// System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
// return enc.GetString(byteArr);
public string ByteArrToString(byte[] byteArr)
{
byte val;
string tempStr = "";
for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
{
val = byteArr[i];
if (val < (byte)10)
tempStr += "00" + val.ToString();
else if (val < (byte)100)
tempStr += "0" + val.ToString();
else
tempStr += val.ToString();
}
return tempStr;
}
EDIT: Merci pour votre aide mais vos réponses ne onu-couvrir le problème, qui s'est avéré être quelque chose de simple. J'ai été de la génération d'une chaîne cryptée sur un serveur et de le remettre à un gestionnaire sur un autre serveur pour decrpytion et de traitement, mais il s'avère que les résultats de chiffrement diffèrent lorsqu'il est exécuté sur des serveurs différents, d'où le serveur de réception ne pouvait pas déchiffrer. L'une des réponses trébuché à travers l'allusion à cet effet par accident, c'est pourquoi j'ai accepté
source d'informationauteur Nick Allen
Vous devez vous connecter pour publier un commentaire.
Vous aurez parfois un message à propos des invalides remplissage lorsque le chiffrement et le déchiffrement pour quelque raison que ce soit n'ont pas utilisé la même clé ou vecteur d'initialisation. Le rembourrage est un nombre d'octets ajoutés à la fin de votre texte pour un nombre total de blocs de l'algorithme de chiffrement pour travailler sur. Dans PKCS7 remplissage de chaque octet est égal au nombre d'octets ajoutés, de sorte qu'il peut toujours être retiré après le décryptage. Votre décryptage a conduit à une chaîne où le dernier n octets ne sont pas égaux à la valeur n du dernier octet (espérons qu'phrase qui a du sens). Je voudrais donc vérifiez toutes vos clés.
Alternativement, dans votre cas, je suggère de faire en sorte que vous créer et de disposer d'une instance de
RijndaelManagedTransform
pour chacun de cryptage et de décryptage de l'opération, l'initialisation avec la clé et le vecteur. Ce problème pourrait très bien être causée par la réutilisation de cette transformation de l'objet, ce qui signifie que, après la première utilisation, il n'est plus dans le droit de l'état initial.J'ai tendance à appeler explicitement la FlushFinalBlock méthode sur CryptoStream avant de le fermer. Que signifierait, en procédant de la manière suivante dans votre chiffrer méthode:
Si vous ne le faites pas, il se peut que les données chiffrées sont tronqués - ce qui aurait pour résultat non valide "rembourrage" scénario. Le rembourrage est toujours présent lors de l'utilisation de PKCS7, même si les données chiffrées est aligné à la longueur du bloc de l'algorithme de chiffrement.
Est là raison pour laquelle vous utilisez votre propre codage,
StrToByteArray
au lieu de Base64 encodage?Si vous apportez ces modifications:
puis les choses devraient fonctionner beaucoup mieux.
Edit:
Concernant le problème avec ToBase64String et QueryString:
Si vous faites votre propre chaîne de Requête d'analyse, alors vous devez vous assurer que vous Split sur le premier =-signe.
De cette façon, vous n'avez pas besoin de remplacer tous les caractères dans votre QueryString quand il est encodé en Base64.