gchq/CyberChef · error · OperationError
IV mismatch
Error message
IV mismatch
What it means
The last step of RFC 3394 unwrap compares the recovered 8-byte integrity register A against the expected IV; a mismatch proves the data did not unwrap correctly (wrong KEK, wrong IV, or corrupted wrapped blob). This is an authenticated integrity failure — unlike a padding oracle, AES-KW gives a clean yes/no.
Source
Thrown at src/core/operations/AESKeyUnwrap.mjs:116
const aView = new DataView(aBuffer);
aView.setUint32(0, aView.getUint32(0) ^ cntUpper);
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
A = Utils.arrayBufferToStr(aBuffer, false);
decipher.start();
decipher.update(forge.util.createBuffer(A + R[i] + paddingBlock));
decipher.finish();
const B = decipher.output.getBytes();
A = B.substring(0, 8);
R[i] = B.substring(8, 16);
cntLower--;
if (cntLower < 0) {
cntUpper--;
cntLower = 0xffffffff;
}
}
}
if (A !== iv) {
throw new OperationError("IV mismatch");
}
const P = R.join("");
if (outputType === "Hex") {
return toHexFast(Utils.strToArrayBuffer(P));
}
return P;
}
}
export default AESKeyUnwrap;
View on GitHub (pinned to 4290ea7539)
Solutions
- Confirm the KEK is byte-identical to the one used during wrap (and its format option is correct).
- If the wrap used a non-standard IV, supply that exact 8-byte IV; otherwise use A6A6A6A6A6A6A6A6.
- Verify the wrapped input was not truncated or altered and that its format option matches.
- Re-wrap with the intended KEK/IV to produce a known-good blob for comparison.
Example fix
// before: unwrap with wrong KEK → 'IV mismatch' // after: supply the exact KEK used during AESKeyWrap (same bytes, same format option)
Defensive patterns
Strategy: try-catch
Validate before calling
function preflightUnwrap(kekBytes, ivBytes, wrappedBytes) {
if (![16,24,32].includes(kekBytes.length)) throw new Error('bad KEK length');
if (ivBytes.length !== 8) throw new Error('bad IV length');
if (wrappedBytes.length < 24 || wrappedBytes.length % 8 !== 0) throw new Error('bad wrapped length');
} Type guard
function unwrapParamsOk(kek, iv, wrapped) { return isAesKek(kek) && isWrapIv(iv) && isUnwrappable(wrapped); } Try / catch
try {
return aesKeyUnwrap(wrapped, kek, iv);
} catch (e) {
if (/IV mismatch/.test(e.message)) {
// integrity failure: wrong KEK, wrong IV, or corrupted blob — do not retry blindly
throw new Error('Key-wrap integrity check failed: verify KEK, IV, and wrapped data');
}
throw e;
} Prevention
- Confirm the KEK is byte-identical to the wrap-time KEK.
- Use the correct 8-byte IV (default A6A6… unless wrap used a custom one).
- Guard the wrapped blob against truncation/alteration in transit.
When it happens
Trigger: After the 6·n rounds complete, the recovered A != iv. Causes: KEK differs from the one used to wrap; the wrap used a non-default IV that was not supplied here; the wrapped bytes were altered/truncated/reordered; format-option mismatch silently changed bytes.
Common situations: Wrong KEK (most common); default IV A6A6A6A6… assumed but the wrap used a custom IV; copy-paste truncation of the wrapped blob; hex/base64 format mismatch on KEK or wrapped data.
Related errors
- Unable to decrypt input with these parameters.
- KEK must be either 16, 24, or 32 bytes (currently " + kek.le
- IV must be 8 bytes (currently " + iv.length + " bytes)
- input must be 8n (n>=3) bytes (currently " + inputData.lengt
- KEK must be either 16, 24, or 32 bytes (currently " + kek.le
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/94346198cb439849.
Report an issue: GitHub.