Fehlermeldung
OperationError: The operation failed for an operation-specific reason
WebCrypto crypto.subtle — browsers & Node
Was der Fehler bedeutet
Der absichtlich vage Sammelfehler von WebCrypto: Das Primitiv selbst ist gescheitert. Bei decrypt() mit AES-GCM heißt das, dass die Prüfung des Authentifizierungs-Tags fehlgeschlagen ist – falscher Schlüssel, falscher IV, falsche zusätzliche Daten oder ein verändertes Chiffrat. Die Spezifikation hält die Meldung generisch, damit Implementierungen nicht verraten, warum eine kryptografische Prüfung gescheitert ist. Bei sign() und deriveBits() deckt derselbe Name interne Fehler des Primitivs ab; die Operation in deinem Stacktrace sagt deshalb mehr als der Meldungstext.
Warum der Fehler auftritt
AES-GCM-Authentifizierung fehlgeschlagen
häufigEntschlüsseln mit einem anderen Schlüssel als beim Verschlüsseln, ein nicht passender IV, fehlende oder abweichende additionalData oder ein Chiffrat, das unterwegs sein angehängtes 16-Byte-Tag verloren hat. GCM ist authentifiziert: Jeder dieser Fälle lässt die gesamte Operation scheitern, statt Datenmüll zurückzugeben.
Chiffrat abgeschnitten oder neu kodiert
häufigUneinheitlich behandeltes Base64 (URL-sicheres oder Standardalphabet), eine Datenbankspalte, die Bytes abschneidet, oder Konvertierungen zwischen String und Binärdaten, die den Puffer beschädigen. Die Tag-Prüfung erkennt jede solche Änderung – genau das ist ihre Aufgabe.
Ableitungsparameter außerhalb des gültigen Bereichs
gelegentlichderiveBits/deriveKey mit einer unerfüllbaren Länge, PBKDF2 mit null Iterationen oder eine ECDH-Berechnung mit inkonsistenten Eingaben erscheint in mehreren Laufzeitumgebungen als OperationError.
So behebst du den Fehler
- 1.
IV und Chiffrat gemeinsam übertragen, auf beiden Seiten gleich dekodieren
Stelle den IV dem Chiffrat voran und trenne beides beim Entschlüsseln wieder, damit beide Seiten immer übereinstimmen; verwende überall dieselbe base64-Variante.
js // encrypt const iv = crypto.getRandomValues(new Uint8Array(12)); const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, data); const packed = new Uint8Array([...iv, ...new Uint8Array(ct)]); // decrypt const buf = packedFromWire; const pt = await crypto.subtle.decrypt( { name: "AES-GCM", iv: buf.slice(0, 12) }, key, buf.slice(12), ); - 2.
Als Integritätsbefund behandeln, nicht als Datenbeschädigung
Wirft decrypt einen OperationError, ist die richtige Antwort: „Dieses Chiffrat ist unter diesem Schlüssel nicht authentisch“ – lehne es ab. Versuche es nicht erneut mit verändertem Padding und weiche nicht auf nicht authentifizierte Modi aus; dass die Prüfung fehlschlägt, ist genau die Sicherheitsfunktion.
- 3.
Schlüssel auf beiden Seiten per Fingerabdruck vergleichen
Exportiere beide Schlüssel und bilde ihre Hashwerte; weichen die Digests voneinander ab, ist das Rätsel in einem Schritt gelöst.
js const raw = await crypto.subtle.exportKey("raw", key); const fp = await crypto.subtle.digest("SHA-256", raw); console.log(Buffer.from(fp).toString("hex").slice(0, 16)); // compare on both sides