Skip to the tool
MoveAheadPayments Toolbox

Why your PIN block decodes to the wrong PIN

The XOR carries no integrity check, so the wrong PAN produces a valid-looking length and four numeric digits. Here is why, and the one field that tells you it happened.

You have a clear PIN block, a PAN, and a PIN that comes back wrong. The obvious conclusion is that the block is corrupt — and it usually is not. An ISO 9564 format 0 block decoded against the wrong PAN does not fail, does not warn, and does not produce anything that looks unusual. It produces a different PIN.

Here is a real one, built and decoded by PIN block toolkit as this page was generated.

The same block, two PANs

PIN 1234 on PAN 4111111111111111 gives this block:

PIN field XOR PAN field
PIN field   041234FFFFFFFFFF
PAN field   0000111111111111
            ────────────────
block       041225EEEEEEEEEE

Decode it with the PAN it was built from and you get 1234, as you must. Decode the identical block with 5555555555554444 instead and you get 1270 — four digits, no error, nothing to suggest anything went wrong.

Why nothing catches it

A format 0 block is the PIN field XOR-ed with a field built from the PAN. XOR is reversible with any value, not only the right one — that is the entire mechanism. Feed a different PAN and every nibble changes by a different amount, but the result is still sixteen nibbles, and the parts a decoder checks are still shaped correctly.

Same block, decoded with the wrong PAN
block            041225EEEEEEEEEE
PAN field        0000555555555444   ← from 5555555555554444
                 ────────────────
result           041270BBBBBBBAAA
                 ││└─ digits: 1270
                 │└── length: 4
                 └─── format: 0

The padding is the only tell

Format 0 pads with F. A correctly decoded block therefore ends in a run of F nibbles, and that is the single piece of evidence available.

Padding, right PAN versus wrong
right PAN   FFFFFFFFFF
wrong PAN   BBBBBBBAAA   ← not F, so the PAN is wrong

If your decoder does not check that, it will hand you a plausible wrong PIN and let you spend an afternoon on it. That is why the tool on this site reports the decode as successful — the block genuinely does say that — while warning, in the same breath, that the padding says not to trust it.

The other way to get this wrong: which twelve digits

The PAN field is the rightmost twelve digits excluding the check digit, and the order of those two operations is where implementations go wrong. Drop the last digit first, then take twelve from what remains.

PAN 4532015112830366
correct   drop check digit → 453201511283036
          rightmost twelve → 201511283036

wrong     rightmost twelve of the whole PAN → 015112830366

What to do when the HSM says verification failed

The response is the same whether the PIN was wrong, the PAN was wrong, the format was wrong or the key was wrong. It cannot tell you, and it is not being unhelpful — it does not know either.

So work backwards from the clear block. Build the block you expect from the PIN and PAN you believe are in play, and compare it with the one you are sending. If they differ, the fault is in the formatting rather than the credential, and the two fields shown separately will say which half moved.

PIN block toolkit builds and decodes formats 0 to 3 in your browser, showing the PIN field, the PAN field and the XOR as separate lines. Nothing you type into it is transmitted anywhere — but use test PINs and test PANs regardless.

Check it against the tool

Frequently asked questions

Which twelve digits of the PAN go into a format 0 PIN block?
The rightmost twelve excluding the check digit, and the order of those two operations is what people get wrong. Drop the last digit first, then take twelve from what remains. Taking the rightmost twelve of the whole PAN shifts every digit by one position and produces a block that is wrong in a way nothing downstream can describe. A PAN shorter than thirteen digits is left-padded with zeros.
Why does decoding with the wrong PAN give a PIN instead of an error?
Because a format 0 block is just the PIN field XOR-ed with the PAN field, and XOR has no integrity check in it. Undo it with a different PAN and you still get sixteen nibbles: the first is still the format code, the second still reads as a length between four and twelve often enough to pass, and the digits after it are still digits. Nothing in the arithmetic knows the PAN was wrong.
How can I tell the PAN was wrong?
The padding. Format 0 pads with F, so a correctly decoded block ends in a run of F nibbles. If the padding is anything else, the PAN you decoded with is not the one the block was built with — and the PIN above it, however ordinary it looks, is not the cardholder's. This is the only signal available, which is why a decoder that does not check it is actively dangerous.
Does this affect format 1, 2 or 3?
Formats 1 and 2 carry no PAN at all, so there is nothing to get wrong — but that is a weakness rather than a feature: without the PAN binding, the same PIN produces the same block on every account. Format 3 folds the PAN in exactly like format 0 and has the same failure, with one difference: its padding is random within A to F, so a digit appearing in the padding is a signal, but F padding is not the expected shape and cannot be used as a check the same way.
The HSM says PIN verification failed. Is the block wrong or the PIN?
The HSM cannot tell you, and that is the whole problem — a wrong PIN, a wrong PAN, a wrong format and a wrong key all produce the same response. Working backwards from the clear block is the only way to separate them: build the block you expect from the PIN and PAN you think are in play, and compare it with the one you are sending. If they differ, the fault is in the formatting rather than the credential.