EMV PIN Block Format Guide
When you enter a PIN at a payment terminal, the PIN doesn't travel over the network in plain text. Instead, it's encoded into a PIN block, encrypted with a symmetric key (DES, 3DES, or AES), and sent to the issuing bank for online verification. This guide explains every PIN block format used in EMV and payment systems.
1. Overview of PIN Block Formats
| Format | Standard | PIN Position | Fill | Key Type | Usage |
|---|---|---|---|---|---|
| Format 0 | ISO 9564 / ANSI X9.8 | Left | PAN-derived | 3DES / AES | Most common worldwide |
| Format 1 | ISO 9564 | Left | Random | 3DES / AES | ATMs, some terminals |
| Format 3 | ISO 9564 / DUKPT | Left | DUKPT-derived | DES/3DES (DUKPT) | US retail, DUKPT terminals |
| IBM 3624 | IBM proprietary | Right | Left-filled zeros | 3DES | Legacy IBM HSMs |
2. ISO Format 0 (ANSI X9.8) — The Standard
Format 0 is the most widely used PIN block format globally. It XORs the PIN field with a PAN-derived field to prevent identical PINs on different cards from producing the same ciphertext.
Step 1: Construct the PIN Field (16 hex digits = 8 bytes)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|02|PL|P1|P2|P3|P4|F1|F2|F3|F4|F5|F6|F7|F8|F9|FA|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
02— Format indicator (0x02 = Format 0)PL— PIN length (e.g.,04for 4-digit PIN)P1–P4— PIN digits (e.g., PIN1234→01 02 03 04)F1–FA— Fill digits:0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
Example: PIN = 1234 → 04 04 01 02 03 04 FF FF FF FF FF FF FF FF FF FF
Wait, let me correct — the fill for Format 0 is 0F repeated, not FF. Actually, the standard fill is each nibble = F.
So PIN 1234 (4 digits): 04 04 01 02 03 04 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
Step 2: Construct the PAN Field (16 hex digits = 8 bytes)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|A1|A2|A3|A4|A5|A6|A7|A8|A9|AA|AB|AC|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- Rightmost 12 digits of the PAN (excluding the check digit), right-aligned
- Left-padded with zeros
Example: PAN = 4111111111111111 → rightmost 12 of 411111111111111 (excluding last check digit) = 111111111111 → PAN field: 00 00 00 00 01 11 11 11 11 11 11 00 00 00 00 00
Actually the correct derivation: take the 12 rightmost digits of the PAN excluding the check digit. So for 4111111111111111 (16 digits, last is check), take digits 4–15: 111111111111 → 00 00 00 00 11 11 11 11 11 11 → as hex nibbles: 0000 0000 1111 1111 1111 — no, let me be precise.
Step 3: XOR the Two Fields
PIN block = PIN_field ⊕ PAN_field
Example:
PAN field: 00 00 00 00 11 11 11 11 11 11 00 00 00 00 00 00
PIN block: 04 04 01 02 12 15 1E 1E 1E 1E 0F 0F 0F 0F 0F 0F
Step 4: Encrypt
The 8-byte PIN block is encrypted with the PIN Encryption Key (PEK):
- 3DES (EDE): Most common —
C = 3DES_Enc(PEK, PIN_block) - AES: Growing adoption — AES-128/192/256, ECB mode on the 16-byte double block
3. ISO Format 1 — Random Fill
Format 1 uses random fill instead of PAN-derived data. It's simpler but requires the recipient to know the format indicator to extract the PIN correctly.
Structure
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|01|PL|P1|P2|P3|P4|R1|R2|R3|R4|R5|R6|R7|R8|R9|RA|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
01— Format indicator (0x01 = Format 1)PL— PIN lengthP1–P4— PIN digitsR1–RA— Random fill digits (0–9, A–F)
No PAN field is used. The receiver extracts the PIN based on the length field.
4. ISO Format 3 — DUKPT Variant
Format 3 is used with DUKPT (Derived Unique Key Per Transaction) key management, common in US retail environments. It's structurally similar to Format 1 but the fill is derived from the DUKPT process.
Structure
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|03|PL|P1|P2|P3|P4|D1|D2|D3|D4|D5|D6|D7|D8|D9|DA|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
03— Format indicator (0x03 = Format 3)PL— PIN lengthP1–P4— PIN digitsD1–DA— DUKPT-derived fill (from the DUKPT counter and encryption process)
5. IBM 3624 Format
The IBM 3624 format is a legacy format still found in some banking HSMs. Unlike ISO formats, the PIN starts from the right side of the block.
Structure
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|00|00|P1|P2|P3|P4|PL|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- Leftmost positions: zero-padded
P1–P4— PIN digits, right-alignedPL— PIN length (rightmost nibble)
Example: PIN 1234 → 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 04
EE command). Always check the HSM documentation.
6. PIN Block Encryption Keys
| Key Type | Algorithm | Usage | Key Management |
|---|---|---|---|
| PEK (PIN Encryption Key) | 3DES EDE / AES | Encrypts the PIN block for transmission | Shared between terminal acquirer and issuer HSM |
| BDK (Base Derivation Key) | 3DES / AES | Master key for DUKPT key derivation | Stored in HSM; injected into PIN pads |
| KSI (Key Serial ID) | — | Identifies the DUKPT device and counter | Embedded in the encrypted PIN block header |
| TPK/ZPK | 3DES | Zone PIN Key — used between acquirer and issuer | Exchanged via key management messages (0800/0810) |
7. Online PIN Verification Flow
1. Cardholder enters PIN at terminal
2. Terminal constructs PIN block (Format 0/1/3)
3. Terminal encrypts PIN block with PEK (or DUKPT-derived key)
4. Terminal sends encrypted PIN block in EMV ARQC/ARPC or ISO 8583 field 52
5. Acquirer HSM decrypts PIN block
6. Acquirer re-encrypts PIN with ZPK (Zone PIN Key) for issuer
7. Issuer HSM decrypts, extracts PIN, compares with stored PIN offset (IBM 3624) or PVV (PIN Verification Value)
8. Issuer returns approval/decline (ISO 8583 field 39)
8. Code Examples
8.1 Format 0 PIN Block Construction (Python)
def construct_format0_pin_block(pin: str, pan: str) -> bytes:
"""Construct ISO Format 0 PIN block."""
# Step 1: PIN field
pin_len = len(pin)
pin_field = bytes([(0x00 | pin_len)]) # format=0, length
pin_field += bytes([int(d) for d in pin]) # PIN digits
pin_field += b'\x0f' * (16 - 2 - pin_len) # pad with 0F
# pad to 8 bytes (16 nibbles)
pin_hex = (0x00 | pin_len).to_bytes(1, 'big')
for d in pin:
pin_hex += int(d).to_bytes(1, 'big')
# Better approach: construct as hex string
pin_str = f"0{pin_len}" + pin + "F" * (16 - 1 - 1 - pin_len)
# Actually let's be precise:
pin_field_hex = "04" + pin + "F" * (16 - 2 - len(pin))
# Step 2: PAN field
pan_digits = pan[:-1] # exclude check digit
pan_right12 = pan_digits[-12:].zfill(12)
pan_field_hex = "0000" + pan_right12
# Step 3: XOR
pin_int = int(pin_field_hex, 16)
pan_int = int(pan_field_hex, 16)
block_int = pin_int ^ pan_int
return block_int.to_bytes(8, 'big')
# Example
block = construct_format0_pin_block("1234", "4111111111111111")
print(block.hex()) # prints the 16-hex-digit PIN block
8.2 Format 1 PIN Block (Python)
import os
def construct_format1_pin_block(pin: str) -> bytes:
"""Construct ISO Format 1 PIN block (random fill)."""
pin_len = len(pin)
hex_str = "01" + f"{pin_len:01X}" + pin
# Fill remaining with random hex digits
remaining = 16 - len(hex_str)
for _ in range(remaining):
hex_str += format(os.urandom(1)[0] % 16, 'X')
block_int = int(hex_str, 16)
return block_int.to_bytes(8, 'big')
block = construct_format1_pin_block("1234")
print(block.hex())
9. Common Issues & Debugging
| Problem | Likely Cause | Fix |
|---|---|---|
| "PIN block format error" from HSM | Format mismatch between terminal and HSM | Verify terminal sends the format the HSM expects |
| Online PIN always declined | PAN derivation wrong (wrong 12 digits) | Check if check digit is excluded, rightmost 12 |
| Same ciphertext for different cards with same PIN | Using Format 1 instead of Format 0 | Switch to Format 0 which XORs with PAN |
| DUKPT key exhaustion | Counter reached end of key range (~1M) | Re-key the terminal with new BDK |
| 3DES decrypt fails | Key parity wrong or key variant incorrect | Check key check value (KCV) with HSM |
10. Summary
- Format 0 — Always use unless you have a specific reason not to. PIN ⊕ PAN, most secure.
- Format 1 — Use for ATMs or when PAN isn't available at PIN entry time.
- Format 3 — Use with DUKPT key management (US retail standard).
- IBM 3624 — Legacy, right-aligned PIN. Only for compatibility with IBM/Thales HSMs.