Project 3: Point-to-Point Encryption (P2PE) Simulator

Project 3: Point-to-Point Encryption (P2PE) Simulator

Project Overview

Attribute Value
Difficulty Level 4: Expert
Time Estimate 2-3 weeks
Programming Language C
Knowledge Area Payment Security / Key Management
Key Technologies DUKPT, HSM Simulation, 3DES/AES
Coolness Level Level 4: Hardcore Tech Flex
Business Potential 3. The โ€œService & Supportโ€ Model

Learning Objectives

By completing this project, you will:

  1. Understand P2PE architecture - Learn why encryption โ€œat the point of swipeโ€ is the gold standard
  2. Implement DUKPT key derivation - Master the Derived Unique Key Per Transaction algorithm
  3. Simulate HSM boundaries - Understand how trust boundaries work in payment systems
  4. Handle key injection ceremonies - Learn how devices get their initial keys
  5. Manage transaction counters - Understand key exhaustion and device lifecycle
  6. Apply defense-in-depth principles - See why multiple security layers matter

The Core Question Youโ€™re Answering

โ€œHow can card data travel through merchant systems without ever being decryptable by the merchant?โ€

This is the fundamental problem P2PE solves:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    THE P2PE SECURITY MODEL                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  WHAT THE MERCHANT SEES:                                                 โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                                                 โ”‚
โ”‚                                                                          โ”‚
โ”‚  Customer swipes card                                                    โ”‚
โ”‚        โ”‚                                                                 โ”‚
โ”‚        โ–ผ                                                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚  โ”‚   Card Reader       โ”‚                                                โ”‚
โ”‚  โ”‚   (P2PE Device)     โ”‚                                                โ”‚
โ”‚  โ”‚                     โ”‚                                                โ”‚
โ”‚  โ”‚  PAN: 4532...0366   โ”‚ โ† Encrypted inside the reader                  โ”‚
โ”‚  โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•   โ”‚                                                โ”‚
โ”‚  โ”‚  Output:            โ”‚                                                โ”‚
โ”‚  โ”‚  "A7F3B2C1D4E5..."  โ”‚ โ† Merchant only sees ciphertext               โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚             โ”‚                                                            โ”‚
โ”‚             โ–ผ                                                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚  โ”‚   Merchant POS      โ”‚  Passes encrypted blob                         โ”‚
โ”‚  โ”‚   System            โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ                             โ”‚
โ”‚  โ”‚                     โ”‚  CANNOT decrypt                                 โ”‚
โ”‚  โ”‚   Key? โŒ None!     โ”‚  (no key access)                               โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚             โ”‚                                                            โ”‚
โ”‚             โ–ผ                                                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚  โ”‚   Payment           โ”‚                                                โ”‚
โ”‚  โ”‚   Processor HSM     โ”‚                                                โ”‚
โ”‚  โ”‚                     โ”‚                                                โ”‚
โ”‚  โ”‚   Key: โœ“ Has DEK    โ”‚ โ† ONLY entity that can decrypt                 โ”‚
โ”‚  โ”‚   Decrypts inside   โ”‚                                                โ”‚
โ”‚  โ”‚   HSM boundary      โ”‚                                                โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚                                                                          โ”‚
โ”‚  RESULT: Even if merchant is completely compromised,                     โ”‚
โ”‚          attacker cannot recover card numbers from transaction logs      โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Why this is the โ€œgold standardโ€:

  1. Merchant systems NEVER touch plaintext card data
  2. Even with full network access, attackers see only ciphertext
  3. Unique key per transaction prevents mass compromise
  4. HSM boundary ensures keys never exist in regular memory

Deep Theoretical Foundation

1. What is P2PE?

Point-to-Point Encryption encrypts card data at the moment of capture (the โ€œpointโ€ of swipe/dip/tap) and keeps it encrypted until it reaches a secure decryption environment (the processorโ€™s HSM).

PCI P2PE Standard:

  • Defined by PCI Security Standards Council
  • Requires validated P2PE solutions
  • Dramatically reduces merchant PCI scope

The Security Chain:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      P2PE SECURITY CHAIN                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”‚
โ”‚  โ”‚   Card   โ”‚    โ”‚ Terminal โ”‚    โ”‚ Merchant โ”‚    โ”‚Processor โ”‚          โ”‚
โ”‚  โ”‚          โ”‚โ”€โ”€โ”€โ–บโ”‚ (P2PE)   โ”‚โ”€โ”€โ”€โ–บโ”‚ Network  โ”‚โ”€โ”€โ”€โ–บโ”‚  HSM     โ”‚          โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ”‚
โ”‚                                                                          โ”‚
โ”‚       โ”‚              โ”‚               โ”‚               โ”‚                   โ”‚
โ”‚       โ–ผ              โ–ผ               โ–ผ               โ–ผ                   โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”‚
โ”‚  โ”‚ Plaintextโ”‚  โ”‚  Encrypted   โ”‚ โ”‚  Encrypted   โ”‚ โ”‚  Plaintext   โ”‚       โ”‚
โ”‚  โ”‚ PAN      โ”‚  โ”‚  (DUKPT key) โ”‚ โ”‚  (passing    โ”‚ โ”‚  (inside HSM โ”‚       โ”‚
โ”‚  โ”‚          โ”‚  โ”‚              โ”‚ โ”‚   through)   โ”‚ โ”‚   only)      โ”‚       โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚
โ”‚                                                                          โ”‚
โ”‚  Trust Boundary: Card โ†’ Terminal (data enters protected channel)         โ”‚
โ”‚  Trust Boundary: Processor HSM (data exits protected channel)            โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

2. DUKPT: Derived Unique Key Per Transaction

DUKPT is THE algorithm that makes P2PE work. It generates a unique encryption key for every transaction from a base key.

The Problem DUKPT Solves:

  • If every terminal uses the same key โ†’ compromise one, compromise all
  • If terminals store individual keys โ†’ key distribution nightmare
  • If terminals derive keys โ†’ need secure derivation mechanism

DUKPT Solution: Inject a โ€œBase Derivation Keyโ€ (BDK) once. Terminal derives unique keys forever.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         DUKPT KEY HIERARCHY                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
โ”‚                      โ”‚ Base Derivation Key โ”‚  Known only to HSM          โ”‚
โ”‚                      โ”‚       (BDK)         โ”‚  128 bits (2-key 3DES)     โ”‚
โ”‚                      โ”‚                     โ”‚  or 256 bits (AES)         โ”‚
โ”‚                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚
โ”‚                                 โ”‚                                        โ”‚
โ”‚         Key Derivation          โ”‚  One-way function                      โ”‚
โ”‚         KSN[0:9] XOR mask       โ”‚                                        โ”‚
โ”‚                                 โ–ผ                                        โ”‚
โ”‚                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
โ”‚                      โ”‚ Initial PIN         โ”‚  Unique per terminal        โ”‚
โ”‚                      โ”‚ Encryption Key      โ”‚  Injected into device       โ”‚
โ”‚                      โ”‚     (IPEK)          โ”‚                             โ”‚
โ”‚                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚
โ”‚                                 โ”‚                                        โ”‚
โ”‚         Future Key Tree         โ”‚  21 "future keys" derived              โ”‚
โ”‚         (pre-computed)          โ”‚  from counter bits                     โ”‚
โ”‚                                 โ–ผ                                        โ”‚
โ”‚        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                 โ”‚
โ”‚        โ”‚                                              โ”‚                 โ”‚
โ”‚        โ–ผ              โ–ผ              โ–ผ                โ–ผ                 โ”‚
โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              โ”‚
โ”‚    โ”‚ FK[1] โ”‚      โ”‚ FK[2] โ”‚      โ”‚ FK[3] โ”‚ ...  โ”‚FK[21] โ”‚              โ”‚
โ”‚    โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜              โ”‚
โ”‚        โ”‚              โ”‚              โ”‚              โ”‚                   โ”‚
โ”‚        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                   โ”‚
โ”‚                                 โ”‚                                        โ”‚
โ”‚         Transaction Key         โ”‚  Derived from appropriate              โ”‚
โ”‚         Derivation             โ”‚  future key based on counter           โ”‚
โ”‚                                 โ–ผ                                        โ”‚
โ”‚                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
โ”‚                      โ”‚ Transaction Key     โ”‚  Unique per transaction     โ”‚
โ”‚                      โ”‚ (PIN or Data)       โ”‚  Used once, then forgotten โ”‚
โ”‚                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key Serial Number (KSN):

The KSN is a 10-byte identifier that tracks which key to use:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    KEY SERIAL NUMBER (KSN) FORMAT                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚
โ”‚  โ”‚   BDK ID (5B)    โ”‚  Device ID (4B)     โ”‚  Counter (21 bits) โ”‚        โ”‚
โ”‚  โ”‚                  โ”‚                     โ”‚                    โ”‚        โ”‚
โ”‚  โ”‚  Identifies      โ”‚  Identifies         โ”‚  Tracks which      โ”‚        โ”‚
โ”‚  โ”‚  which BDK       โ”‚  which terminal     โ”‚  transaction       โ”‚        โ”‚
โ”‚  โ”‚  was used        โ”‚                     โ”‚  (max 1M)          โ”‚        โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚
โ”‚                                                                          โ”‚
โ”‚  Example: FFFF 9876543210 00001                                         โ”‚
โ”‚           ^^^^ ^^^^^^^^^^ ^^^^^                                          โ”‚
โ”‚           BDK  Device     Counter=1 (first transaction)                  โ”‚
โ”‚                                                                          โ”‚
โ”‚  The KSN is sent WITH the encrypted data so the HSM knows               โ”‚
โ”‚  which key to derive for decryption!                                    โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

3. DUKPT Key Derivation Algorithm

Simplified DUKPT Derivation (the actual spec is in ANSI X9.24):

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    DUKPT DERIVATION STEPS                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  INITIAL KEY INJECTION (happens once at manufacturing):                  โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                 โ”‚
โ”‚                                                                          โ”‚
โ”‚  1. Extract device ID from KSN: FFFF 9876543210 00000                   โ”‚
โ”‚                                       ^^^^^^^^^^                         โ”‚
โ”‚  2. Create registration value: 9876543210 || 0000000 (padded)           โ”‚
โ”‚                                                                          โ”‚
โ”‚  3. IPEK = 3DES_encrypt(registration, BDK)                              โ”‚
โ”‚                                                                          โ”‚
โ”‚  4. Store IPEK in device's secure memory                                โ”‚
โ”‚     (BDK is NEVER stored in device!)                                    โ”‚
โ”‚                                                                          โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚                                                                          โ”‚
โ”‚  TRANSACTION KEY DERIVATION (happens per transaction):                   โ”‚
โ”‚  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                 โ”‚
โ”‚                                                                          โ”‚
โ”‚  Given: Counter = 0x00005 (binary: 0000 0000 0101)                      โ”‚
โ”‚                                                                          โ”‚
โ”‚  1. Find set bits in counter: bits 0 and 2                              โ”‚
โ”‚                                                                          โ”‚
โ”‚  2. Start with current_key = IPEK                                       โ”‚
โ”‚                                                                          โ”‚
โ”‚  3. For each set bit (from left to right):                              โ”‚
โ”‚     - Create key_register = counter with only this bit set              โ”‚
โ”‚     - current_key = derive_key(current_key, key_register)               โ”‚
โ”‚                                                                          โ”‚
โ”‚  4. Result: transaction_key for this counter                            โ”‚
โ”‚                                                                          โ”‚
โ”‚  derive_key():                                                           โ”‚
โ”‚     - XOR key_register into current_key_right_half                      โ”‚
โ”‚     - Encrypt with current_key_left_half                                โ”‚
โ”‚     - Result is new key                                                  โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Why this design?:

  1. Forward secrecy: Compromised key doesnโ€™t reveal past keys
  2. No reverse derivation: Canโ€™t derive IPEK from transaction key
  3. Efficient: Only 21 derivations needed for 1M transactions
  4. Stateless HSM: HSM derives key on-demand from KSN + BDK

4. Hardware Security Modules (HSMs)

An HSM is a dedicated cryptographic processor with physical security protections.

HSM Properties:

  • Tamper-resistant: Physical attacks destroy keys
  • FIPS 140-2/3 certified: Validated security
  • Key management: Keys generated, stored, and used inside HSM
  • Audit logging: All operations logged
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         HSM TRUST BOUNDARY                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚                         HSM                                      โ”‚    โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚              SECURE ENCLAVE                              โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                                                          โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚   BDK    โ”‚    โ”‚   KEK    โ”‚    โ”‚   Other  โ”‚         โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  Store   โ”‚    โ”‚  Store   โ”‚    โ”‚   Keys   โ”‚         โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                                                          โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚              CRYPTO ENGINE                         โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚                                                    โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  โ€ข 3DES / AES operations                          โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  โ€ข DUKPT key derivation                           โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  โ€ข PIN translation                                โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚                                                    โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  Keys NEVER leave this boundary in plaintext      โ”‚ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                                                          โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚    โ”‚
โ”‚  โ”‚                              โ”‚                                    โ”‚    โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                    API LAYER                                 โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                                                              โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  decrypt_with_dukpt(encrypted_data, ksn) โ†’ plaintext        โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  encrypt_with_dukpt(plaintext, ksn) โ†’ encrypted_data        โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  translate_pin_block(encrypted_pin, ksn) โ†’ translated_pin   โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚                                                              โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  Input: encrypted data goes IN                               โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  Output: plaintext comes OUT (or processed result)           โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  Keys: NEVER come out                                        โ”‚ โ”‚    โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚    โ”‚
โ”‚  โ”‚                                                                    โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                                                                          โ”‚
โ”‚  PHYSICAL SECURITY:                                                      โ”‚
โ”‚  โ€ข Tamper-evident seals                                                  โ”‚
โ”‚  โ€ข Intrusion detection (zeroizes keys if opened)                        โ”‚
โ”‚  โ€ข Environmental sensors (voltage, temperature)                         โ”‚
โ”‚  โ€ข FIPS 140-2 Level 3 or Level 4                                       โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

5. Transaction Counter and Key Exhaustion

The Counter Problem:

  • DUKPT counter is 21 bits โ†’ max 2,097,152 transactions
  • After exhaustion, device must be re-keyed

Counter Management:

Counter: 0x00000 โ†’ First transaction
Counter: 0x00001 โ†’ Second transaction
Counter: 0x00002 โ†’ Third transaction
...
Counter: 0x1FFFFF โ†’ Last transaction (key exhausted!)

What happens at exhaustion:

  1. Device refuses to encrypt
  2. Alert sent to management system
  3. Device must be returned for re-keying (new IPEK injection)

Project Specification

What Youโ€™ll Build

A P2PE simulator with:

  1. Simulated Terminal: Encrypts โ€œcard swipesโ€ using DUKPT
  2. Simulated HSM: Decrypts using BDK and KSN
  3. Trust Boundary Enforcement: Code that โ€œcannotโ€ access plaintext outside HSM
  4. Key Injection Ceremony: Initial device provisioning
  5. Transaction Flow Visualization: See encryption state at each step

Expected Output

# Initialize the system
$ ./p2pe init
[HSM] Generating Base Derivation Key...
[HSM] BDK created: FFFF (identifier)
[KEY CEREMONY] Starting key injection for terminal TRM001...
[KEY CEREMONY] Deriving IPEK from BDK + Device ID...
[TERMINAL TRM001] IPEK received and stored securely
[SYSTEM] P2PE system initialized

# Simulate a card swipe
$ ./p2pe swipe --terminal TRM001 --pan 4532015112830366

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘                       P2PE TRANSACTION FLOW                            โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘                                                                        โ•‘
โ•‘  STEP 1: CARD READ                                                     โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                                     โ•‘
โ•‘  Terminal TRM001 reads: 4532015112830366                              โ•‘
โ•‘  Track 2 data captured                                                 โ•‘
โ•‘                                                                        โ•‘
โ•‘  STEP 2: KEY DERIVATION (inside terminal)                              โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                             โ•‘
โ•‘  Current counter: 0x00017                                              โ•‘
โ•‘  KSN: FFFF9876543210000017                                            โ•‘
โ•‘  Deriving transaction key from IPEK...                                 โ•‘
โ•‘  Transaction key: [PROTECTED - inside terminal secure memory]          โ•‘
โ•‘                                                                        โ•‘
โ•‘  STEP 3: ENCRYPTION (inside terminal)                                  โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                  โ•‘
โ•‘  Plaintext:  4532015112830366                                         โ•‘
โ•‘  Algorithm:  3DES-CBC                                                  โ•‘
โ•‘  Output:     A7F3B2C1D4E5F687H9I0J1K2L3M4N5O6                         โ•‘
โ•‘              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                          โ•‘
โ•‘              This is all the merchant system sees!                     โ•‘
โ•‘                                                                        โ•‘
โ•‘  STEP 4: TRANSMISSION                                                  โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                                   โ•‘
โ•‘  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ•‘
โ•‘  โ”‚ TRANSACTION REQUEST                                      โ”‚          โ•‘
โ•‘  โ”‚ KSN: FFFF9876543210000017                                โ”‚          โ•‘
โ•‘  โ”‚ Encrypted Data: A7F3B2C1D4E5F687H9I0J1K2L3M4N5O6        โ”‚          โ•‘
โ•‘  โ”‚ Merchant: MERCH001                                       โ”‚          โ•‘
โ•‘  โ”‚ Amount: $50.00                                           โ”‚          โ•‘
โ•‘  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ•‘
โ•‘                                                                        โ•‘
โ•‘  STEP 5: HSM PROCESSING                                                โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                               โ•‘
โ•‘  [HSM] Received KSN: FFFF9876543210000017                             โ•‘
โ•‘  [HSM] Extracting BDK ID: FFFF                                        โ•‘
โ•‘  [HSM] Looking up BDK...found                                          โ•‘
โ•‘  [HSM] Deriving transaction key from BDK + KSN...                      โ•‘
โ•‘  [HSM] Decrypting inside secure boundary...                            โ•‘
โ•‘  [HSM] Plaintext recovered (inside HSM only): 4532015112830366        โ•‘
โ•‘  [HSM] Forwarding to issuer for authorization...                       โ•‘
โ•‘                                                                        โ•‘
โ•‘  STEP 6: RESPONSE                                                      โ•‘
โ•‘  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                                      โ•‘
โ•‘  Authorization: APPROVED                                               โ•‘
โ•‘  Auth Code: 123456                                                     โ•‘
โ•‘                                                                        โ•‘
โ•‘  Counter incremented: 0x00017 โ†’ 0x00018                                โ•‘
โ•‘  Remaining transactions: 2,097,128                                     โ•‘
โ•‘                                                                        โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

# Verify merchant cannot decrypt
$ ./p2pe merchant-view --transaction 12345

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘                    MERCHANT SYSTEM VIEW                                โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘                                                                        โ•‘
โ•‘  Transaction ID: 12345                                                 โ•‘
โ•‘  Terminal: TRM001                                                      โ•‘
โ•‘  Timestamp: 2024-01-15 14:32:17                                       โ•‘
โ•‘                                                                        โ•‘
โ•‘  Card Data: A7F3B2C1D4E5F687H9I0J1K2L3M4N5O6 (encrypted)             โ•‘
โ•‘  KSN: FFFF9876543210000017                                            โ•‘
โ•‘                                                                        โ•‘
โ•‘  โš ๏ธ  Decryption key: NOT AVAILABLE                                     โ•‘
โ•‘  โš ๏ธ  Plaintext PAN: NOT AVAILABLE                                      โ•‘
โ•‘                                                                        โ•‘
โ•‘  The merchant system has NO access to:                                 โ•‘
โ•‘  โ€ข The Base Derivation Key (BDK)                                      โ•‘
โ•‘  โ€ข The Initial PIN Encryption Key (IPEK)                              โ•‘
โ•‘  โ€ข Any transaction key                                                 โ•‘
โ•‘                                                                        โ•‘
โ•‘  Even with full database access, the card number cannot be recovered! โ•‘
โ•‘                                                                        โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Project Structure

p2pe_simulator/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ main.c                    # CLI entry point
โ”‚   โ”œโ”€โ”€ terminal/
โ”‚   โ”‚   โ”œโ”€โ”€ terminal.c            # Terminal simulation
โ”‚   โ”‚   โ”œโ”€โ”€ terminal.h
โ”‚   โ”‚   โ”œโ”€โ”€ dukpt_encrypt.c       # Encryption with DUKPT
โ”‚   โ”‚   โ””โ”€โ”€ secure_memory.c       # Simulated secure memory
โ”‚   โ”œโ”€โ”€ hsm/
โ”‚   โ”‚   โ”œโ”€โ”€ hsm.c                 # HSM simulation
โ”‚   โ”‚   โ”œโ”€โ”€ hsm.h
โ”‚   โ”‚   โ”œโ”€โ”€ dukpt_decrypt.c       # Decryption with DUKPT
โ”‚   โ”‚   โ”œโ”€โ”€ key_store.c           # BDK storage
โ”‚   โ”‚   โ””โ”€โ”€ trust_boundary.c      # Boundary enforcement
โ”‚   โ”œโ”€โ”€ key_management/
โ”‚   โ”‚   โ”œโ”€โ”€ key_ceremony.c        # Key injection
โ”‚   โ”‚   โ”œโ”€โ”€ dukpt_derive.c        # DUKPT algorithm
โ”‚   โ”‚   โ””โ”€โ”€ counter.c             # Transaction counter
โ”‚   โ”œโ”€โ”€ transport/
โ”‚   โ”‚   โ”œโ”€โ”€ message.c             # Transaction message format
โ”‚   โ”‚   โ””โ”€โ”€ protocol.c            # Simulated network
โ”‚   โ””โ”€โ”€ crypto/
โ”‚       โ”œโ”€โ”€ des3.c                # 3DES implementation
โ”‚       โ””โ”€โ”€ aes.c                 # AES for modern DUKPT
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ test_dukpt.c
โ”‚   โ”œโ”€โ”€ test_terminal.c
โ”‚   โ”œโ”€โ”€ test_hsm.c
โ”‚   โ””โ”€โ”€ test_vectors/             # ANSI X9.24 test vectors
โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ dukpt_explanation.md
โ”œโ”€โ”€ Makefile
โ””โ”€โ”€ README.md

Core API Design

// terminal.h
typedef struct {
    char terminal_id[16];
    unsigned char ipek[16];          // Initial PIN Encryption Key
    unsigned char ksn_base[10];      // KSN without counter
    uint32_t counter;                // Current transaction counter
} Terminal;

// Encrypt card data (happens inside terminal's secure boundary)
typedef struct {
    unsigned char ciphertext[64];
    size_t ciphertext_len;
    unsigned char ksn[10];           // Full KSN with counter
} EncryptedTrack;

EncryptedTrack terminal_encrypt(Terminal* term, const char* track_data);

// hsm.h
typedef struct {
    char hsm_id[16];
    // BDK is stored inside and NEVER exposed
} HSM;

// Initialize HSM (loads BDK from secure storage)
HSM* hsm_init(const char* bdk_path);

// Decrypt (plaintext only exists inside this function)
// Returns authorization result, NOT the plaintext
typedef struct {
    bool success;
    char auth_code[8];
    char error[64];
} AuthResult;

AuthResult hsm_process_transaction(HSM* hsm, const EncryptedTrack* track,
                                    const char* merchant_id, int amount_cents);

// key_ceremony.h
// Generate IPEK for a new terminal (happens in secure facility)
bool key_ceremony_inject(HSM* hsm, Terminal* term, const char* device_id);

Solution Architecture

System Design

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    P2PE SIMULATOR ARCHITECTURE                           โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚                        TERMINAL SIMULATOR                          โ”‚  โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                    SECURE ELEMENT (simulated)                โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                                                              โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”‚    IPEK    โ”‚    โ”‚  Counter   โ”‚    โ”‚  KSN Base  โ”‚       โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  (secret)  โ”‚    โ”‚  Manager   โ”‚    โ”‚            โ”‚       โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚         โ”‚                 โ”‚                 โ”‚               โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜               โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ”‚                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ–ผ                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  DUKPT Engine  โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  (key derive + โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚   encrypt)     โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                                                              โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  โ”‚
โ”‚  โ”‚                              โ”‚                                      โ”‚  โ”‚
โ”‚  โ”‚                              โ”‚ Encrypted output only                โ”‚  โ”‚
โ”‚  โ”‚                              โ–ผ                                      โ”‚  โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                    TERMINAL APPLICATION                      โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ€ข Receives encrypted blob                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ€ข Formats transaction message                              โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ€ข NO access to plaintext or keys                          โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                              โ”‚                                           โ”‚
โ”‚                              โ”‚ {KSN, Encrypted Data, Amount}            โ”‚
โ”‚                              โ–ผ                                           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚                     MERCHANT SYSTEM (simulated)                    โ”‚  โ”‚
โ”‚  โ”‚                                                                    โ”‚  โ”‚
โ”‚  โ”‚   โ€ข Stores encrypted transaction                                   โ”‚  โ”‚
โ”‚  โ”‚   โ€ข Forwards to processor                                          โ”‚  โ”‚
โ”‚  โ”‚   โ€ข CANNOT decrypt (no keys)                                       โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                              โ”‚                                           โ”‚
โ”‚                              โ”‚ {KSN, Encrypted Data, Amount}            โ”‚
โ”‚                              โ–ผ                                           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚                        HSM SIMULATOR                               โ”‚  โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                    SECURE BOUNDARY                           โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                                                              โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”‚    BDK     โ”‚    โ”‚  DUKPT     โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”‚  Storage   โ”‚โ”€โ”€โ”€โ–บโ”‚  Derive &  โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ”‚            โ”‚    โ”‚  Decrypt   โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ”‚                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ–ผ                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  PLAINTEXT     โ”‚  โ† Exists only here     โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  (in memory,   โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚   for auth)    โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ”‚                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                           โ–ผ                                  โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  Forward to    โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ”‚  Card Network  โ”‚                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                         โ”‚  โ”‚  โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  โ”‚
โ”‚  โ”‚                              โ”‚                                      โ”‚  โ”‚
โ”‚  โ”‚                              โ”‚ Auth result (no plaintext)           โ”‚  โ”‚
โ”‚  โ”‚                              โ–ผ                                      โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Trust Boundary Enforcement

How to simulate HSM trust boundary in software:

// trust_boundary.c

// All code that touches plaintext must be in this file
// This simulates "inside the HSM"

// Private - never expose
static unsigned char bdk[16];

// The ONLY function that can see plaintext
// Notice: it returns AuthResult, NOT the plaintext
static AuthResult process_inside_hsm(const EncryptedTrack* track) {
    // 1. Derive key from KSN
    unsigned char transaction_key[16];
    dukpt_derive_key(bdk, track->ksn, transaction_key);

    // 2. Decrypt
    char plaintext[64];
    des3_decrypt(track->ciphertext, transaction_key, plaintext);

    // 3. Process (send to card network)
    AuthResult result = send_to_issuer(plaintext);

    // 4. CRITICAL: Zero plaintext before returning
    explicit_bzero(plaintext, sizeof(plaintext));
    explicit_bzero(transaction_key, sizeof(transaction_key));

    // 5. Return only the auth result
    return result;
}

// Public API - what outside code can call
AuthResult hsm_process_transaction(HSM* hsm, const EncryptedTrack* track,
                                    const char* merchant_id, int amount_cents) {
    // Validate inputs
    // Log the request (without plaintext!)
    // Call the internal function
    return process_inside_hsm(track);
}

Implementation Guide

Phase 1: DUKPT Key Derivation

Goal: Implement the core DUKPT algorithm.

Start with test vectors from ANSI X9.24:

// Known test vectors
const char* BDK = "0123456789ABCDEFFEDCBA9876543210";
const char* KSN = "FFFF9876543210E00001";
// Expected IPEK: 6AC292FAA1315B4D858AB3A3D7D5933A
// Expected transaction key: depends on counter

Key derivation steps:

void dukpt_derive_ipek(const unsigned char* bdk,
                       const unsigned char* ksn,
                       unsigned char* ipek) {
    // 1. Mask KSN: zero out counter bits
    unsigned char masked_ksn[10];
    memcpy(masked_ksn, ksn, 10);
    masked_ksn[7] &= 0xE0;  // Clear counter bits
    masked_ksn[8] = 0x00;
    masked_ksn[9] = 0x00;

    // 2. Left half of IPEK
    unsigned char data[8];
    memcpy(data, masked_ksn, 8);
    des3_encrypt(data, bdk, ipek);  // Left 8 bytes

    // 3. Right half of IPEK
    unsigned char bdk_variant[16];
    xor_with_constant(bdk, 0xC0C0C0C000000000C0C0C0C000000000, bdk_variant);
    des3_encrypt(data, bdk_variant, ipek + 8);  // Right 8 bytes
}

Phase 2: Terminal Simulation

Goal: Build terminal that encrypts card data.

Terminal secure memory simulation:

typedef struct {
    unsigned char ipek[16];
    uint32_t counter;
    unsigned char ksn_base[10];
    bool initialized;
} SecureMemory;

// Simulated secure memory - in real terminal this is in hardware
static SecureMemory secure_mem;

// Initialize with key ceremony
void terminal_init(const unsigned char* ipek, const unsigned char* ksn_base) {
    memcpy(secure_mem.ipek, ipek, 16);
    memcpy(secure_mem.ksn_base, ksn_base, 10);
    secure_mem.counter = 0;
    secure_mem.initialized = true;
}

Phase 3: HSM Simulation

Goal: Build HSM that decrypts but enforces trust boundary.

Key insight: The HSM function should NEVER return plaintext.

// BAD - exposes plaintext
char* hsm_decrypt(const EncryptedTrack* track) {
    // This would violate the trust boundary!
    return plaintext;  // NEVER do this
}

// GOOD - processes but doesn't expose
AuthResult hsm_process(const EncryptedTrack* track) {
    char plaintext[64];
    decrypt_internally(track, plaintext);

    // Do something with plaintext (auth check)
    AuthResult result = authorize(plaintext);

    // Zero before return
    explicit_bzero(plaintext, 64);
    return result;  // Only return auth result
}

Phase 4: Key Injection Ceremony

Goal: Simulate initial device provisioning.

bool key_ceremony(HSM* hsm, Terminal* term, const char* device_id) {
    // In reality, this happens in a secure room with split knowledge

    // 1. Generate IPEK from BDK + device ID
    unsigned char ipek[16];
    unsigned char ksn_base[10];

    // Build KSN base from BDK ID + Device ID
    build_ksn_base(hsm->bdk_id, device_id, ksn_base);

    // Derive IPEK (happens inside HSM)
    hsm_derive_ipek(hsm, ksn_base, ipek);

    // 2. "Inject" IPEK into terminal
    // In reality: secure cable, no network, audited room
    terminal_inject_ipek(term, ipek, ksn_base);

    // 3. Zero the IPEK outside HSM
    explicit_bzero(ipek, 16);

    return true;
}

Phase 5: Transaction Flow

Goal: Full end-to-end transaction demonstration.

void demo_transaction(Terminal* term, HSM* hsm,
                      const char* pan, int amount_cents) {
    printf("=== P2PE Transaction Demo ===\n");

    // Step 1: Terminal encrypts
    printf("[TERMINAL] Encrypting PAN: %s\n", pan);
    EncryptedTrack encrypted = terminal_encrypt(term, pan);
    printf("[TERMINAL] KSN: ");
    print_hex(encrypted.ksn, 10);
    printf("[TERMINAL] Ciphertext: ");
    print_hex(encrypted.ciphertext, encrypted.ciphertext_len);

    // Step 2: "Send" to processor (just pass the struct)
    printf("[MERCHANT] Forwarding encrypted data (cannot decrypt!)\n");

    // Step 3: HSM processes
    printf("[HSM] Processing transaction...\n");
    AuthResult result = hsm_process_transaction(hsm, &encrypted,
                                                 "MERCH001", amount_cents);

    // Step 4: Show result
    if (result.success) {
        printf("[HSM] APPROVED - Auth code: %s\n", result.auth_code);
    } else {
        printf("[HSM] DECLINED - %s\n", result.error);
    }
}

Testing Strategy

DUKPT Test Vectors

Use ANSI X9.24 test vectors to verify your implementation:

// test_dukpt.c
void test_ipek_derivation() {
    // ANSI X9.24 test vector
    unsigned char bdk[] = {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,
                           0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10};
    unsigned char ksn[] = {0xFF,0xFF,0x98,0x76,0x54,0x32,0x10,0xE0,0x00,0x00};

    unsigned char ipek[16];
    dukpt_derive_ipek(bdk, ksn, ipek);

    unsigned char expected[] = {0x6A,0xC2,0x92,0xFA,0xA1,0x31,0x5B,0x4D,
                                0x85,0x8A,0xB3,0xA3,0xD7,0xD5,0x93,0x3A};

    assert(memcmp(ipek, expected, 16) == 0);
}

Trust Boundary Tests

// Verify plaintext never escapes HSM
void test_plaintext_not_exposed() {
    // Set up terminal and HSM
    // Process a transaction
    // Check that no function returned plaintext
    // Check that logs don't contain plaintext
}

Counter Management Tests

void test_counter_increments() {
    Terminal term;
    terminal_init(&term, test_ipek, test_ksn);

    assert(term.counter == 0);
    terminal_encrypt(&term, "4111111111111111");
    assert(term.counter == 1);
}

void test_key_exhaustion() {
    Terminal term;
    terminal_init(&term, test_ipek, test_ksn);
    term.counter = 0x1FFFFF;  // Max counter

    EncryptedTrack result = terminal_encrypt(&term, "4111111111111111");
    assert(result.ciphertext_len == 0);  // Should fail
}

Common Pitfalls & Debugging

Pitfall 1: Wrong Bit Ordering in KSN

Symptom: Derived keys donโ€™t match test vectors.

Cause: DUKPT uses big-endian for KSN, your system might be little-endian.

Debug: Print each step and compare with manual calculation.

Pitfall 2: Counter Bit Extraction

Symptom: Keys derive incorrectly for counters > 1.

Cause: Misunderstanding which bits to use for each derivation step.

Fix: Counter bits are used right-to-left, each set bit triggers a derivation.

Pitfall 3: Exposing Plaintext

Symptom: Your โ€œHSMโ€ returns decrypted data.

Cause: Wrong API designโ€”HSM should return auth result, not plaintext.

Fix: Refactor so all plaintext handling is inside one function.


Extensions & Challenges

Extension 1: AES-DUKPT

Implement the newer AES-based DUKPT (ANSI X9.24-3):

  • 256-bit keys
  • AES-128 block cipher
  • Different derivation algorithm

Extension 2: PIN Blocks

Implement PIN encryption and translation:

  • ISO Format 0/1/3 PIN blocks
  • PIN translation between zones

Extension 3: EMV Cryptograms

Simulate EMV chip card cryptogram generation:

  • Application Cryptogram (AC)
  • Authorization Request Cryptogram (ARQC)

Extension 4: Multi-HSM

Implement HSM clustering:

  • Key synchronization
  • Failover handling

Interview Questions This Prepares You For

  1. โ€œWhat is DUKPT and why is it used?โ€
    • Derived Unique Key Per Transactionโ€”enables unique encryption keys without distributing new keys
  2. โ€œHow does P2PE reduce PCI scope?โ€
    • Merchant never has access to plaintext or keys, so their systems are out of scope
  3. โ€œWhatโ€™s an HSM and why is it necessary?โ€
    • Hardware Security Moduleโ€”provides physical security for keys, ensures keys never exist in regular memory
  4. โ€œWhat happens when a DUKPT counter exhausts?โ€
    • Device can no longer encrypt, must be re-keyed (new IPEK injection)
  5. โ€œHow do you derive a transaction key from IPEK?โ€
    • Walk through the future key tree based on counter bits

Resources

Specifications

  • ANSI X9.24-1: DUKPT (2017 version)
  • ANSI X9.24-3: AES DUKPT
  • PCI P2PE Standard

Books

Topic Book Chapter
Key Derivation Serious Cryptography (Aumasson) Ch. 8: KDFs
HSM Concepts Security in Computing (Pfleeger) HSM section
Block Ciphers Practical Cryptography (Ferguson) Ch. 3-4

Articles

  • โ€œUnderstanding DUKPTโ€ - Thales blog
  • PCI P2PE Implementation Guide

Self-Assessment Checklist

  • DUKPT IPEK derivation matches test vectors
  • Transaction key derivation works for all counter values
  • Terminal encrypts without exposing keys
  • HSM decrypts without exposing plaintext
  • Counter management prevents key reuse
  • Key exhaustion is handled gracefully
  • Can explain the security model to others
  • Understand why merchant canโ€™t decrypt

Whatโ€™s Next?

You now understand card-present security. For e-commerce (card-not-present), move to Project 4: 3D Secure Authentication Flow to learn how online transactions add cardholder authentication.