Ich habe online gesucht, was diese Ausnahme in Bezug auf mein Programm bedeutet, kann aber anscheinend keine Lösung finden oder den Grund, warum es mit meinem spezifischen Programm passiert. Ich habe das Beispiel meiner msdn zum Ver- und Entschlüsseln eines XmlDocument mit dem Rijndael-Algorithmus verwendet. Die Verschlüsselung funktioniert einwandfrei, aber wenn ich versuche zu entschlüsseln, erhalte ich die folgende Ausnahme:
Das Auffüllen ist ungültig und kann nicht entfernt werden
Kann mir jemand sagen, was ich tun kann, um dieses Problem zu lösen? In meinem Code unten erhalte ich den Schlüssel und andere Daten. Wenn der cryptoMode false ist, wird die Entschlüsselungsmethode aufgerufen, bei der die Ausnahme auftritt:
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
Braune Liebe
quelle
quelle
Antworten:
Rijndael / AES ist eine Blockverschlüsselung. Es verschlüsselt Daten in 128-Bit-Blöcken (16 Zeichen). Durch kryptografisches Auffüllen wird sichergestellt, dass der letzte Block der Nachricht immer die richtige Größe hat.
Ihre Entschlüsselungsmethode erwartet, was auch immer die Standardauffüllung ist, und findet sie nicht. Wie @NetSquirrel sagt, müssen Sie die Auffüllung sowohl für die Verschlüsselung als auch für die Entschlüsselung explizit festlegen. Verwenden Sie PKCS # 7-Polsterung, sofern Sie keinen Grund haben, etwas anderes zu tun.
quelle
alg.Padding = PaddingMode.PKCS7;
Stellen Sie sicher , dass die Schlüssel Sie verwenden verschlüsseln und entschlüsseln sind die gleichen . Die Auffüllmethode sollte auch dann, wenn sie nicht explizit festgelegt wurde, eine ordnungsgemäße Entschlüsselung / Verschlüsselung ermöglichen (wenn sie nicht festgelegt ist, sind sie gleich). Wenn Sie jedoch aus irgendeinem Grund einen anderen Schlüsselsatz zur Entschlüsselung verwenden als zur Verschlüsselung, wird folgende Fehlermeldung angezeigt:
Wenn Sie einen Algorithmus verwenden, um dynamisch Schlüssel zu generieren, die nicht funktionieren. Sie müssen für die Ver- und Entschlüsselung gleich sein. Eine übliche Methode besteht darin, dass der Aufrufer die Schlüssel im Konstruktor der Klasse der Verschlüsselungsmethoden bereitstellt, um zu verhindern, dass der Verschlüsselungs- / Entschlüsselungsprozess bei der Erstellung dieser Elemente eine Rolle spielt. Es konzentriert sich auf die jeweilige Aufgabe (Ver- und Entschlüsseln von Daten) und erfordert, dass das
iv
undkey
vom Anrufer bereitgestellt wird.quelle
Für die Suche kann es sich lohnen, die entschlüsselte Eingabe zu überprüfen. In meinem Fall wurden die zur Entschlüsselung gesendeten Informationen (fälschlicherweise) als leere Zeichenfolge eingegeben. Dies führte zu einem Auffüllfehler.
Dies mag sich auf Rossums Antwort beziehen, hielt es aber für erwähnenswert.
quelle
Wenn für die Codierung und Decodierung derselbe Schlüssel und der gleiche Initialisierungsvektor verwendet werden, liegt dieses Problem nicht bei der Datendecodierung, sondern bei der Datencodierung.
Nachdem Sie die Write-Methode für ein CryptoStream-Objekt aufgerufen haben, müssen Sie IMMER die FlushFinalBlock-Methode vor der Close-Methode aufrufen.
In der MSDN-Dokumentation zur CryptoStream.FlushFinalBlock-Methode heißt es:
"Durch Aufrufen der Close-Methode wird FlushFinalBlock aufgerufen ... "
https://msdn.microsoft.com/de-DE/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
Das ist falsch. Durch Aufrufen der Close-Methode werden nur der CryptoStream und der Ausgabestream geschlossen.
Wenn Sie FlushFinalBlock nicht vor dem Schließen aufrufen, nachdem Sie zu verschlüsselnde Daten geschrieben haben, löst ein Aufruf der Read- oder CopyTo-Methode für Ihr CryptoStream-Objekt beim Aufschlüsseln eine CryptographicException-Ausnahme aus (Meldung: "Auffüllen ist ungültig und kann nicht entfernt werden").
Dies gilt wahrscheinlich für alle von SymmetricAlgorithm abgeleiteten Verschlüsselungsalgorithmen (Aes, DES, RC2, Rijndael, TripleDES), obwohl ich dies gerade für AesManaged und einen MemoryStream als Ausgabestream überprüft habe.
Wenn Sie diese CryptographicException-Ausnahme bei der Entschlüsselung erhalten, lesen Sie den Wert Ihrer Ausgabestream-Length-Eigenschaft, nachdem Sie Ihre zu verschlüsselnden Daten geschrieben haben. Rufen Sie dann FlushFinalBlock auf und lesen Sie den Wert erneut. Wenn es sich geändert hat, wissen Sie, dass das Aufrufen von FlushFinalBlock NICHT optional ist.
Außerdem müssen Sie kein Auffüllen programmgesteuert durchführen oder einen anderen Wert für die Padding-Eigenschaft auswählen. Das Auffüllen ist ein FlushFinalBlock-Methodenjob.
.........
Zusätzliche Bemerkung für Kevin:
Ja, CryptoStream ruft FlushFinalBlock auf, bevor Close geschlossen wird, aber es ist zu spät: Wenn die CryptoStream Close-Methode aufgerufen wird, wird auch der Ausgabestream geschlossen.
Wenn Ihr Ausgabestream ein MemoryStream ist, können Sie seine Daten nach dem Schließen nicht mehr lesen. Sie müssen also FlushFinalBlock in Ihrem CryptoStream aufrufen, bevor Sie die im MemoryStream geschriebenen verschlüsselten Daten verwenden können.
Wenn Ihr Ausgabestream ein FileStream ist, sind die Dinge schlechter, weil das Schreiben gepuffert ist. Die Folge ist, dass zuletzt geschriebene Bytes möglicherweise nicht in die Datei geschrieben werden, wenn Sie den Ausgabestream schließen, bevor Sie Flush in FileStream aufrufen. Bevor Sie Close in CryptoStream aufrufen, müssen Sie zuerst FlushFinalBlock in Ihrem CryptoStream aufrufen und dann Flush in Ihrem FileStream aufrufen.
quelle
Stream.Close()
Anrufethis.Dispose(true)
. Der Code fürCryptoStream.Dispose(bool)
ist:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Nach mehreren Kämpfen löste ich endlich das Problem.
(Hinweis: Ich verwende Standard-AES als symmetrischen Algorithmus. Diese Antwort ist möglicherweise nicht für alle geeignet.)
RijndaelManaged
Klasse durchAESManaged
eine.KeySize
Algorithmusklasse nicht explizit fest, sondern belassen Sie sie als Standard.(Dies ist der sehr wichtige Schritt. Ich denke, es gibt einen Fehler in der KeySize-Eigenschaft.)
Hier ist eine Liste, in der Sie überprüfen möchten, welches Argument Sie möglicherweise übersehen haben:
(Byte-Array, Länge muss für unterschiedliche Schlüsselgrößen genau 16, 24, 32 Byte betragen.)
(Byte-Array, 16 Byte)
(einer von CBC, CFB, CTS, EZB, OFB)
(Einer von ANSIX923, ISO10126, None, PKCS7, Zeros)
quelle
KeySize
es für mich sofort behoben. Oh die Macken von .NET :-(Mein Problem war, dass die passPhrase der Verschlüsselung nicht mit der passPhrase der Entschlüsselung übereinstimmte ... also warf es diesen Fehler ... ein wenig irreführend.
quelle
Die Lösung, die meine behoben hat, war, dass ich versehentlich verschiedene Schlüssel auf Verschlüsselungs- und Entschlüsselungsmethoden angewendet hatte.
quelle
Ich bin auf diesen Fehler gestoßen, als ich versucht habe, einen unverschlüsselten Dateipfad an die Entschlüsselungsmethode zu übergeben. Die Lösung bestand darin, zu überprüfen, ob die übergebene Datei zuerst verschlüsselt ist, bevor versucht wird, sie zu entschlüsseln
quelle
Ein weiteres Szenario, wiederum zum Nutzen der Suchenden.
Für mich trat dieser Fehler während der Dispose () -Methode auf, die einen früheren Fehler maskierte, der nicht mit der Verschlüsselung zusammenhängt.
Sobald die andere Komponente behoben war, verschwand diese Ausnahme.
quelle
Ich habe diesen Auffüllfehler festgestellt, als ich die verschlüsselten Zeichenfolgen in der Datei manuell bearbeitet habe (mit dem Editor), weil ich testen wollte, wie sich die Entschlüsselungsfunktion verhält, wenn mein verschlüsselter Inhalt manuell geändert wird.
Die Lösung für mich war, eine zu platzieren
Wie ich bereits sagte, war mein Auffüllfehler darauf zurückzuführen, dass ich den entschlüsselten Text manuell mit dem Editor eingegeben habe. Vielleicht führt Sie meine Antwort zu Ihrer Lösung.
quelle
Ich hatte den gleichen Fehler. In meinem Fall lag es daran, dass ich die verschlüsselten Daten in einer SQL-Datenbank gespeichert habe. Die Tabelle, in der die Daten gespeichert sind, hat einen binären Datentyp (1000). Beim Abrufen der Daten aus der Datenbank werden diese 1000 Bytes entschlüsselt, während dort tatsächlich 400 Bytes vorhanden sind. Durch Entfernen der nachgestellten Nullen (600) aus dem Ergebnis wurde das Problem behoben.
quelle
Ich hatte diesen Fehler und stellte explizit die Blockgröße ein:
aesManaged.BlockSize = 128;
Sobald ich das entfernt habe, hat es funktioniert.
quelle
Ich hatte das gleiche Problem beim Versuch, ein Go-Programm nach C # zu portieren. Dies bedeutet, dass viele Daten bereits mit dem Go-Programm verschlüsselt wurden. Diese Daten müssen jetzt mit C # entschlüsselt werden.
Die endgültige Lösung war
PaddingMode.None
oder eherPaddingMode.Zeros
.Die kryptografischen Methoden in Go:
... und ...
Jetzt Entschlüsselung in C #:
Wie kann das Problem mit der Polsterung erklärt werden? Kurz vor der Verschlüsselung überprüft das Go-Programm die Auffüllung:
Der wichtige Teil ist folgender:
Ein neues Array mit einer geeigneten Länge wird erstellt, sodass die Länge ein Vielfaches der Blockgröße beträgt. Dieses neue Array ist mit Nullen gefüllt. Die Kopiermethode kopiert dann die vorhandenen Daten hinein. Es wird sichergestellt, dass das neue Array größer als die vorhandenen Daten ist. Dementsprechend befinden sich am Ende des Arrays Nullen.
Somit kann der C # -Code verwendet werden
PaddingMode.Zeros
. Die AlternativePaddingMode.None
ignoriert einfach jede Polsterung, die auch funktioniert. Ich hoffe, diese Antwort ist hilfreich für alle, die Code von Go to C # usw. portieren müssen.quelle
Ich habe den gleichen Fehler vom Kunden gemeldet. Ich persönlich kann es nicht tadeln. Mit Blick auf den Code von Encrypt und Decrypt Methoden, beide haben Padding Satz PaddingMode.PKCS7 . Das Entschlüsseln sieht so aus und ich kann das Problem damit in Bezug auf ' FlushFinalBlock ' nicht erkennen. Könnte jemand bitte etwas Licht ins Dunkel bringen?
quelle
Ich hatte den gleichen Fehler. In meinem Fall ist das angegebene Passwort größer als 16, was bedeutet, dass es verschlüsselt ist, aber während der Entschlüsselung erhalte ich diesen Fehler. Verschlüsselung:
Entschlüsselung:
quelle