J'ai cherché en ligne ce que cette exception signifie par rapport à mon programme, mais je ne parviens pas à trouver une solution ou la raison pour laquelle cela arrive à mon programme spécifique. J'ai utilisé l'exemple fourni avec mon msdn pour crypter et décrypter un XmlDocument à l'aide de l'algorithme Rijndael. Le cryptage fonctionne bien mais lorsque j'essaie de décrypter, j'obtiens l'exception suivante:
Le remplissage n'est pas valide et ne peut pas être supprimé
Quelqu'un peut-il me dire ce que je peux faire pour résoudre ce problème? Mon code ci-dessous est l'endroit où j'obtiens la clé et d'autres données. Si le cryptoMode est false, il appellera la méthode decrypt, qui est là où l'exception se produit:
public void Cryptography(XmlDocument doc, bool cryptographyMode)
{
RijndaelManaged key = null;
try
{
// Create a new Rijndael key.
key = new RijndaelManaged();
const string passwordBytes = "Password1234"; //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("SaltBytes");
Rfc2898DeriveBytes p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize/8);
key.Key = p.GetBytes(key.KeySize/8);
if (cryptographyMode)
{
Ecrypt(doc, "Content", key);
}
else
{
Decrypt(doc, key);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Clear the key.
if (key != null)
{
key.Clear();
}
}
}
private void Decrypt(XmlDocument doc, SymmetricAlgorithm alg)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("Doc");
if (alg == null)
throw new ArgumentNullException("alg");
// Find the EncryptedData element in the XmlDocument.
XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
// If the EncryptedData element was not found, throw an exception.
if (encryptedElement == null)
{
throw new XmlException("The EncryptedData element was not found.");
}
// Create an EncryptedData object and populate it.
EncryptedData edElement = new EncryptedData();
edElement.LoadXml(encryptedElement);
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml();
// Decrypt the element using the symmetric key.
byte[] rgbOutput = exml.DecryptData(edElement, alg); <---- I GET THE EXCEPTION HERE
// Replace the encryptedData element with the plaintext XML element.
exml.ReplaceData(encryptedElement, rgbOutput);
}
c#
cryptography
Amour brun
la source
la source
Réponses:
Rijndael / AES est un chiffrement par blocs. Il crypte les données en blocs de 128 bits (16 caractères). Le remplissage cryptographique est utilisé pour s'assurer que le dernier bloc du message est toujours de la bonne taille.
Votre méthode de décryptage attend quel que soit son remplissage par défaut et ne le trouve pas. Comme le dit @NetSquirrel, vous devez définir explicitement le remplissage pour le cryptage et le décryptage. Sauf si vous avez une raison de faire autrement, utilisez le remplissage PKCS # 7.
la source
alg.Padding = PaddingMode.PKCS7;
Assurez-vous que les clés que vous utilisez pour crypter et décrypter sont les mêmes . La méthode de remplissage, même si elle n'est pas explicitement définie, devrait toujours permettre un décryptage / cryptage correct (si elle n'est pas définie, elle sera la même). Toutefois , si pour une raison quelconque utilisez un autre jeu de clés pour le décryptage que celle utilisée pour le chiffrement , vous aurez obtenir cette erreur:
Si vous utilisez un algorithme pour générer dynamiquement des clés qui ne fonctionneront pas. Ils doivent être les mêmes pour le cryptage et le décryptage. Une manière courante consiste à demander à l'appelant de fournir les clés dans le constructeur de la classe des méthodes de chiffrement, pour éviter que le processus de chiffrement / déchiffrement ne participe à la création de ces éléments. Il se concentre sur la tâche à accomplir (cryptage et décryptage des données) et nécessite que
iv
etkey
soit fourni par l'appelant.la source
Pour les utilisateurs qui recherchent, il peut être utile de vérifier l'entrée en cours de déchiffrement. Dans mon cas, les informations envoyées pour le décryptage étaient (à tort) entrées sous forme de chaîne vide. Cela a entraîné une erreur de remplissage.
Cela peut être lié à la réponse de Rossum, mais cela vaut la peine d'être mentionné.
la source
Si la même clé et le même vecteur d'initialisation sont utilisés pour le codage et le décodage, ce problème ne vient pas du décodage des données mais du codage des données.
Après avoir appelé la méthode Write sur un objet CryptoStream, vous devez TOUJOURS appeler la méthode FlushFinalBlock avant la méthode Close.
La documentation MSDN sur la méthode CryptoStream.FlushFinalBlock indique:
"L' appel de la méthode Close appellera FlushFinalBlock ... "
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
C'est faux. L'appel de la méthode Close ferme simplement le CryptoStream et le Stream de sortie.
Si vous n'appelez pas FlushFinalBlock avant Close après avoir écrit des données à chiffrer, lors du déchiffrement des données, un appel à la méthode Read ou CopyTo sur votre objet CryptoStream lèvera une exception CryptographicException (message: "Le remplissage est invalide et ne peut pas être supprimé").
Cela est probablement vrai pour tous les algorithmes de chiffrement dérivés de SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), bien que je viens de vérifier cela pour AesManaged et un MemoryStream comme flux de sortie.
Ainsi, si vous recevez cette exception CryptographicException lors du déchiffrement, lisez la valeur de la propriété Stream Length de sortie après avoir écrit vos données à chiffrer, puis appelez FlushFinalBlock et relisez sa valeur. S'il a changé, vous savez que l'appel de FlushFinalBlock n'est PAS facultatif.
Et vous n'avez pas besoin d'effectuer de remplissage par programme ou de choisir une autre valeur de propriété de remplissage. Le remplissage est un travail de méthode FlushFinalBlock.
.........
Remarque supplémentaire pour Kevin:
Oui, CryptoStream appelle FlushFinalBlock avant d'appeler Close, mais il est trop tard: lorsque la méthode CryptoStream Close est appelée, le flux de sortie est également fermé.
Si votre flux de sortie est un MemoryStream, vous ne pouvez pas lire ses données après sa fermeture. Vous devez donc appeler FlushFinalBlock sur votre CryptoStream avant d'utiliser les données chiffrées écrites sur le MemoryStream.
Si votre flux de sortie est un FileStream, les choses sont pires car l'écriture est mise en mémoire tampon. La conséquence est que les derniers octets écrits peuvent ne pas être écrits dans le fichier si vous fermez le flux de sortie avant d'appeler Flush sur FileStream. Donc, avant d'appeler Close sur CryptoStream, vous devez d'abord appeler FlushFinalBlock sur votre CryptoStream, puis appeler Flush sur votre FileStream.
la source
Stream.Close()
appelsthis.Dispose(true)
. Le code pourCryptoStream.Dispose(bool)
est:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Un temps serval de combats, j'ai finalement résolu le problème.
(Remarque: j'utilise AES standard comme algorithme symétrique. Cette réponse peut ne pas convenir à tout le monde.)
RijndaelManaged
classe parAESManaged
une.KeySize
classe d'algorithme, laissez- les par défaut.(C'est l'étape très importante. Je pense qu'il y a un bogue dans la propriété KeySize.)
Voici une liste que vous souhaitez vérifier quel argument vous avez peut-être manqué:
(tableau d'octets, la longueur doit être exactement l'un des 16, 24, 32 octets pour différentes tailles de clé.)
(tableau d'octets, 16 octets)
(l'un des CBC, CFB, CTS, ECB, OFB)
(l'un des ANSIX923, ISO10126, Aucun, PKCS7, Zéros)
la source
KeySize
corrigé pour moi tout de suite. Oh les bizarreries de .NET :-(Mon problème était que le passPhrase du chiffrement ne correspondait pas au passPhrase du déchiffrement ... donc il a jeté cette erreur ... un peu trompeur.
la source
La solution qui a corrigé la mienne était que j'avais appliqué par inadvertance différentes clés aux méthodes de cryptage et de décryptage.
la source
Je suis tombé sur cette erreur en essayant de transmettre un chemin de fichier non chiffré à la méthode Decrypt.La solution était de vérifier si le fichier passé est chiffré avant d'essayer de déchiffrer
la source
Un autre scénario, toujours au profit des personnes qui recherchent.
Pour moi, cette erreur s'est produite lors de la méthode Dispose () qui masquait une erreur précédente sans rapport avec le chiffrement.
Une fois que l'autre composant a été corrigé, cette exception a disparu.
la source
J'ai rencontré cette erreur de remplissage lorsque je modifiais manuellement les chaînes cryptées dans le fichier (à l'aide du bloc-notes), car je voulais tester le comportement de la fonction de décryptage si mon contenu crypté était modifié manuellement.
La solution pour moi était de placer un
Comme je l'ai dit, mon erreur de remplissage était due au fait que je tapais manuellement sur le texte déchiffré à l'aide du bloc-notes. Peut-être que ma réponse peut vous guider vers votre solution.
la source
J'ai eu la même erreur. Dans mon cas, c'est parce que j'ai stocké les données cryptées dans une base de données SQL. La table dans laquelle les données sont stockées a un type de données binaire (1000). Lors de la récupération des données de la base de données, il décrypterait ces 1000 octets, alors qu'il y en avait en fait 400 octets. Donc, en supprimant les zéros de fin (600) du résultat, le problème a été résolu.
la source
J'ai eu cette erreur et je définissais explicitement la taille du bloc:
aesManaged.BlockSize = 128;
Une fois que j'ai supprimé cela, cela a fonctionné.
la source
J'ai eu le même problème en essayant de porter un programme Go vers C #. Cela signifie que de nombreuses données ont déjà été cryptées avec le programme Go. Ces données doivent maintenant être déchiffrées avec C #.
La solution finale était
PaddingMode.None
ou plutôtPaddingMode.Zeros
.Les méthodes cryptographiques de Go:
... et ...
Maintenant, décryptage en C #:
Comment expliquer le problème du rembourrage? Juste avant le chiffrement, le programme Go vérifie le remplissage:
La partie importante est la suivante:
Un nouveau tableau est créé avec une longueur appropriée, de sorte que la longueur soit un multiple de la taille du bloc. Ce nouveau tableau est rempli de zéros. La méthode de copie y copie ensuite les données existantes. Il est garanti que le nouveau tableau est plus grand que les données existantes. En conséquence, il y a des zéros à la fin du tableau.
Ainsi, le code C # peut utiliser
PaddingMode.Zeros
. L'alternativePaddingMode.None
ignore simplement tout remplissage, ce qui fonctionne également. J'espère que cette réponse est utile pour quiconque doit porter le code de Go vers C #, etc.la source
Je suis signalé la même erreur par le client. Je ne peux personnellement pas le reprocher. En regardant le code des méthodes Encrypt et Decrypt , les deux ont Padding défini sur PaddingMode.PKCS7 . Decrypt ressemble à ceci et je ne vois pas le problème avec ' FlushFinalBlock '. Quelqu'un pourrait-il s'il vous plaît faire la lumière là-dessus?
la source
J'ai eu la même erreur. Dans mon cas, le mot de passe donné est supérieur à 16 signifie qu'il est crypté, mais lors du décryptage, j'obtiens cette erreur. Chiffrement:
Décryptage:
la source