All Tools
Tools/UDK Calculator
🔑
CryptographyBeta

UDK Calculator

Derive EMV Unique Derived Keys (UDK) from an Issuer Master Key (IMK) and PAN/PAN Sequence Number — for EMV card personalisation and transaction key derivation.

Use test data only. All calculations run locally in your browser — PayProbe never sees, transmits, or stores your PAN, CVV, keys, PINs, or cryptographic inputs. How we handle data →

Algorithm (Visa/Mastercard UDK Derivation)

  1. Diversification data = PAN right 12 digits (excl. check) ∥ PAN Sequence Number (2 digits)
  2. Left half input = divData[0..13] ∥ F0 (padded to 8 bytes)
  3. Right half input = divData[0..13] ∥ 0F (padded to 8 bytes)
  4. Encrypt each half with 2TDEA under IMK
  5. UDK = left || right, with DES odd parity adjusted on each byte
</> Code Implementation
# EMV UDK Derivation — Visa/Mastercard method using 2TDEA
# Requires: pip install pycryptodome
from Crypto.Cipher import DES3

def adjust_parity(b: int) -> int:
    """Force DES odd parity on a byte."""
    bits = bin(b).count("1")
    return b ^ 1 if bits % 2 == 0 else b

def des3_encrypt(key: bytes, data: bytes) -> bytes:
    key24 = key[:16] + key[:8]
    return DES3.new(key24, DES3.MODE_ECB).encrypt(data)

def derive_udk(imk_hex: str, pan: str, pan_seq: str = "00") -> dict:
    imk      = bytes.fromhex(imk_hex)
    div_data = (pan[-13:-1] + pan_seq.zfill(2))[:14]
    # Left half: diversification data + F0
    left_data  = bytes.fromhex(div_data + "F0")
    # Right half: diversification data + 0F
    right_data = bytes.fromhex(div_data + "0F")
    left_enc   = des3_encrypt(imk, left_data)
    right_enc  = des3_encrypt(imk, right_data)
    udk_raw    = left_enc + right_enc
    udk        = bytes(adjust_parity(b) for b in udk_raw)
    return {
        "left":  left_enc.hex().upper(),
        "right": right_enc.hex().upper(),
        "udk":   udk.hex().upper(),
    }

# Example
imk = "0123456789ABCDEF0123456789ABCDEF"
pan = "4111111111111111"
result = derive_udk(imk, pan)
print(f"UDK Left  : {result['left']}")
print(f"UDK Right : {result['right']}")
print(f"UDK       : {result['udk']}")