How to Verify Smart Card Checksums — CRC, LRC, CMAC, MAC Explained

Smart card protocols rely on checksums and MACs (Message Authentication Codes) at multiple layers: CRC-16 protects anti-collision bytes, Retail MAC authenticates APDU commands, CMAC secures SCP03 sessions, and XOR LRC validates ATR and data blocks. This guide covers all common smart card checksum algorithms with ready-to-use code for each.

1. CRC-16 Variants — Quick Reference

NamePolyInitRefIn/OutXorOutUsed In
CRC-16/CCITT0x10210xFFFFNo/No0x0000MIFARE, ISO 14443-3
CRC-16/XMODEM0x10210x0000No/No0x0000Bootloaders, T=0
CRC-16/ANSI0x80050xFFFFYes/Yes0x0000Modbus, some cards
CRC-16/ARC0x80050x0000Yes/Yes0x0000LHA, some NFC
CRC-16/KERMIT0x10210x0000Yes/Yes0x0000KERMIT protocol

2. CRC-16/CCITT — MIFARE and ISO 14443-3

This is the most common NFC/contactless CRC. All MIFARE and ISO 14443-3 commands append a 2-byte CRC:

def crc16_ccitt(data):
    """MIFARE / ISO 14443-3 CRC-16 (CCITT, polynomial 0x1021)."""
    crc = 0xFFFF
    for byte in data:
        crc ^= (byte << 8)
        for _ in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc

# Example: MIFARE REQA command = [0x26]
# CRC-16 = 0x4B 0x99 → transmitted as CRC[0]=0x4B, CRC[1]=0x99

# MIFARE authenticate command:
# [0x60, 0x00] → CRC = crc16_ccitt(bytes([0x60, 0x00])) → check against received CRC

3. XOR LRC — Longitudinal Redundancy Check

Simple XOR of all data bytes. Common in ATR historical bytes, EMV records, and proprietary card formats:

def xor_lrc(data):
    """XOR Longitudinal Redundancy Check."""
    lrc = 0x00
    for byte in data:
        lrc ^= byte
    return lrc

def verify_lrc(data, expected_lrc):
    """Verify LRC on data + LRC byte should be 0x00."""
    return (xor_lrc(data) ^ expected_lrc) == 0x00

# Example: data=[0x01, 0x02, 0x03], LRC=0x00 (1^2^3=0)
# Verify: xor all bytes including LRC → must be 0

4. 3DES Retail MAC — ISO 9797-1 Algorithm 3

The Retail MAC is the workhorse of smart card security: EMV GENERATE AC, SCP02 APDU authentication, M/Chip, and Visa CVV/CVC all use it:

from Crypto.Cipher import DES3

def retail_mac(key_16bytes, data):
    """ISO 9797-1 Algorithm 3 (Retail MAC).
    key = 16 bytes (2TDEA: k1=k2 for first 8, k3 for last 8)
    """
    k1 = key_16bytes[:8]   # DES key left
    k2 = key_16bytes[8:16] # DES key right
    k3 = k1                # Retail MAC: k3 = k1

    # Padding: ISO 9797-1 Method 2 (0x80 + 0x00...)
    pad_len = 8 - (len(data) % 8)
    padded = data + b'\x80' + b'\x00' * (pad_len - 1)

    # Step 1: DES-CBC encrypt with k1, IV=0x00...00
    cipher1 = DES3.new(k1 + k2, DES3.MODE_CBC, iv=b'\x00'*8)
    # Triple-DES first 8 bytes with k1+k2, rest with k1 only (Retail)
    encrypted = bytearray()
    for i in range(0, len(padded), 8):
        block = padded[i:i+8]
        # Triple-DES encrypt block using k1+k2
        c = DES3.new(k1 + k2, DES3.MODE_ECB)
        encrypted.extend(c.encrypt(block))

    # Step 2: Decrypt last block with k3 (k1 in Retail)
    last = encrypted[-8:]
    cipher_dec = DES3.new(k3, DES3.MODE_ECB)  # Single DES decrypt
    last_dec = cipher_dec.decrypt(last)

    # Step 3: Encrypt again with k1
    cipher_enc = DES3.new(k1, DES3.MODE_ECB)
    mac = cipher_enc.encrypt(last_dec)
    return mac  # 8 bytes MAC

5. AES-CMAC — NIST SP 800-38B (SCP03, DESFire)

from Crypto.Hash import CMAC
from Crypto.Cipher import AES

def aes_cmac(key, data):
    """AES-CMAC-128 per NIST SP 800-38B / RFC 4493."""
    mac = CMAC.new(key, ciphermod=AES)
    mac.update(data)
    return mac.digest()  # 16 bytes

# SCP03 command MAC: CMAC over (APDU header + data, padded)
# scp03_mac = aes_cmac(S_MAC_key, command_data)
# APDU: [CLA INS P1 P2 Lc Data MAC(8_bytes) Le]

6. When to Use Each Checksum/MAC

AlgorithmOutputSecurityUse Case
CRC-16/CCITT2 bytesError detection onlyAnti-collision, transport integrity
XOR LRC1 byteError detection onlyATR validation, record integrity
Retail MAC (3DES)8 bytesCryptographic authEMV, SCP02, CVV/CVC
AES-CMAC8-16 bytesCryptographic authSCP03, DESFire, FIDO2
ISO 7816-4 SM MAC8 bytesCommand authSecure Messaging APDU
Test this yourself: Our Crypto Checksum Verifier computes CRC-16 (CCITT/XMODEM/ANSI/ARC/KERMIT), XOR LRC, 3DES Retail MAC, and AES-CMAC in the browser. Paste hex data, pick algorithm, and get the checksum — no data leaves your device.

Related Tools

Crypto Checksum Verifier — Calculate all checksums in-browser | Key Diversification Calculator — Derive MAC keys | Session Key Visualizer — SCP02/SCP03 session keys | GP SCP02 vs SCP03 Guide