DES vs 3DES vs AES — Smart Card Encryption Algorithms Compared
Three symmetric block ciphers have dominated smart card and payment system encryption for decades: DES (1977), 3DES (Triple DES, 1998), and AES (2001). DES is broken. 3DES is being sunset. AES is the modern standard. Yet in the smart card world, all three coexist — because billions of EMV cards still use 3DES, and migration to AES is slow. This guide explains the technical differences, where each is used, and which to choose for new systems.
Specs at a Glance
| Property | DES | 3DES (Triple DES) | AES |
|---|---|---|---|
| Standard | FIPS 46-3 (1977) | ANSI X9.52 / FIPS 46-3 | FIPS 197 (2001) |
| Block size | 64 bits | 64 bits | 128 bits |
| Key size | 56 bits (effective) | 112 or 168 bits | 128, 192, or 256 bits |
| Rounds | 16 | 48 (3 × 16) | 10, 12, or 14 |
| Security status | BROKEN — brute-forceable in hours | Deprecated — being sunset by 2023-2030 | Secure — no practical attack |
| Speed (software) | Fast (but insecure) | ~3× slower than DES | Fastest with AES-NI |
| Smart card usage | Legacy only (pre-2000 cards) | EMV SCP02, most payment cards | EMV SCP03, FIDO2, new cards |
| Recommended for new systems | No | No (transitional only) | Yes |
1. DES (Data Encryption Standard) — The Pioneer
DES was adopted as a US federal standard in 1977. It uses a 56-bit key (stored in 8 bytes, with 1 parity bit per byte) and a 64-bit block size, processing data through 16 rounds of Feistel network operations.
The problem: 56 bits is only 2^56 ≈ 7.2 × 10^16 possible keys. In 1998, the EFF built a DES cracker for $250,000 that brute-forced a key in 56 hours. Today, cloud computing can do it in hours for a few dollars. DES is categorically broken and must not be used for new systems.
2. 3DES (Triple DES) — The Workaround
3DES applies the DES algorithm three times with two or three different keys, using an encrypt-decrypt-encrypt (EDE) construction:
3DES Encrypt: C = E_K3(D_K2(E_K1(P)))
3DES Decrypt: P = D_K1(E_K2(D_K3(C)))
Where E = DES encrypt, D = DES decrypt, K1/K2/K3 = DES keys
Keying options:
Option 1 (3TDEA): K1 ≠ K2 ≠ K3 → 168-bit key (effective ~112 bits)
Option 2 (2TDEA): K1 = K3, K1 ≠ K2 → 112-bit key (effective ~80 bits)
Option 3 (backward-compat): K1 = K2 = K3 → equivalent to single DES
In smart cards, Option 2 (2TDEA, 16-byte key) is the most common. This is what EMV SCP02 uses for session key derivation and MAC computation. The effective security is ~80 bits (due to meet-in-the-middle attacks), which is below the 112-bit target.
Why 3DES Is Being Sunset
NIST SP 800-131A disallowed 3DES for new applications after 2023 and will disallow it for all applications by 2025-2030. The Sweet32 attack (2016) showed that 3DES's 64-bit block size is vulnerable to birthday attacks when encrypting large amounts of data (>32 GB with the same key). For payment systems processing millions of transactions, this is a real concern.
| 3DES in Smart Cards | Where | Status |
|---|---|---|
| EMV SCP02 session keys | Most issued EMV cards | Phasing out — new cards use SCP03 |
| EMV ARQC/ARPC cryptograms | Issuer host systems | Still common — migration ongoing |
| GlobalPlatform SCP02 | Card management | Legacy — SCP03 (AES) preferred |
| MIFARE Classic (Crypto-1) | Transit/access cards | Broken — not even 3DES, just proprietary |
| 3DES Retail MAC (ISO 9797-1) | EMV MAC computation | Replaced by AES-CMAC in SCP03 |
3. AES (Advanced Encryption Standard) — The Modern Standard
AES was selected by NIST in 2001 after a 4-year public competition. It uses a 128-bit block size and supports key sizes of 128, 192, or 256 bits. Unlike DES's Feistel network, AES uses a substitution-permutation network (SPN) with 10, 12, or 14 rounds depending on key size.
| AES Variant | Key Size | Rounds | Security Level | Recommended For |
|---|---|---|---|---|
| AES-128 | 128 bits | 10 | 128-bit security | Most applications (FIDO2, SCP03) |
| AES-192 | 192 bits | 12 | 192-bit security | Higher assurance (government) |
| AES-256 | 256 bits | 14 | 256-bit security | Long-term / quantum resistance |
AES is the default for:
- GlobalPlatform SCP03 — AES-128-CBC and AES-CMAC for secure channel
- FIDO2 / CTAP2 — AES-256 for resident key encryption
- EMV (new cards) — AES-128 for contactless and some contact cards
- Calypso / CIPURSE — AES-128 for transit payment cards
- Java Card 3.x — AES is natively supported in the API
4. Security Comparison
Key Space
| Attack | DES | 3DES | AES |
|---|---|---|---|
| Brute force | Feasible (hours) | Not feasible (2^112) | Not feasible (2^128+) |
| Known-plaintext (linear) | 2^43 known plaintexts | Not practical | Not practical |
| Birthday (block size) | 2^32 blocks = 32 GB | 2^32 blocks = 32 GB (Sweet32) | 2^64 blocks = impractical |
| Related-key | N/A | N/A | Theoretical only (AES-256) |
| Side-channel (timing/power) | Yes — if not constant-time | Yes | Yes — mitigated with AES-NI or masking |
5. Performance Comparison
| Metric | DES | 3DES | AES-128 |
|---|---|---|---|
| Software (no hardware accel) | ~50 MB/s | ~17 MB/s | ~120 MB/s |
| Software (AES-NI / ARM CE) | N/A | N/A | ~3000+ MB/s |
| Smart card (typical) | ~10 ms per block | ~30 ms per block | ~5 ms per block |
| Block size | 8 bytes | 8 bytes | 16 bytes |
| Throughput per block | Lower (fewer bytes per op) | 3× slower than DES | Best (larger blocks, fewer ops) |
6. Smart Card Usage: Which Algorithm Where?
| Context | Algorithm | Why |
|---|---|---|
| EMV SCP02 (legacy) | 3DES (2TDEA) | Designed in the 1990s when AES didn't exist |
| EMV SCP03 (modern) | AES-128 | GP card spec 2.3+, required for new deployments |
| EMV ARQC/ARPC (legacy) | 3DES-CBC MAC | Most issuer host systems still use 3DES |
| EMV ARQC/ARPC (new) | AES-CMAC | EMVCo pushing for AES migration in C-8 kernel |
| FIDO2 / WebAuthn | AES-256 | CTAP2 spec mandates AES-256-CBC for wrapping |
| MIFARE DESFire | 3DES or AES-128 | EV1 = 3DES; EV2/EV3 = AES-128 |
| MIFARE Plus | AES-128 | Upgraded from Classic's Crypto-1 to AES |
| Java Card applet encryption | AES or 3DES | Developer choice; AES preferred |
| GlobalPlatform key diversification | 3DES (SCP02) or AES (SCP03) | Matches the secure channel protocol |
7. When to Use Each (2026 Guidelines)
8. Migration Path: 3DES → AES
If you're maintaining a system that still uses 3DES, here's the migration path:
| Step | Action | Timeline |
|---|---|---|
| 1. Audit | Identify all 3DES usage points (SCP02 keys, MAC computation, card-personalization) | Immediate |
| 2. Dual-mode | Deploy SCP03 alongside SCP02; support both during transition | 3-6 months |
| 3. Issue AES cards | Personalize new cards with AES keys (SCP03) | 6-12 months |
| 4. Deprecate 3DES | Stop accepting SCP02 for new card issuance | 12-18 months |
| 5. Sunset | Remove 3DES code paths; only accept AES | 24 months |
Key Diversification Migration
When migrating from SCP02 (3DES) to SCP03 (AES), the key diversification changes:
// SCP02 (3DES) key diversification
card_key = 3DES_CBC(master_key, diversification_data)
// 16-byte 2TDEA key derived from master
// SCP03 (AES) key diversification
card_key = AES_CMAC(master_key, diversification_data)
// 16-byte AES-128 key derived from master
// Different algorithm, different S-MAC/S-ENC/S-DEK derivation
9. Code Examples
Python: AES-128-CBC Encryption
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import os
# AES-128-CBC encryption (recommended for new systems)
key = os.urandom(16) # 128-bit key
iv = os.urandom(16) # random IV
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
padder = padding.PKCS7(128).padder()
plaintext = b"EMV transaction data"
padded = padder.update(plaintext) + padder.finalize()
ciphertext = encryptor.update(padded) + encryptor.finalize()
print(f"Ciphertext: {ciphertext.hex()}")
JavaScript: AES-256-GCM with Web Crypto API
// AES-256-GCM authenticated encryption (in-browser)
async function aesEncrypt(plaintext, key256) {
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await crypto.subtle.importKey(
'raw', key256, { name: 'AES-GCM' }, false, ['encrypt']
);
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
new TextEncoder().encode(plaintext)
);
return { iv, ciphertext: new Uint8Array(ciphertext) };
}
Python: 3DES-CBC (for legacy EMV compatibility)
from Crypto.Cipher import DES3
from Crypto.Util.Padding import pad
import os
# 3DES-CBC encryption (legacy only - migrating to AES)
key = os.urandom(16) # 16 bytes = 2TDEA (K1=K3)
iv = os.urandom(8) # 64-bit IV for DES block size
cipher = DES3.new(key, DES3.MODE_CBC, iv=iv)
plaintext = b"Legacy EMV data"
ciphertext = cipher.encrypt(pad(plaintext, 8))
print(f"Ciphertext: {ciphertext.hex()}")
10. Summary — Which to Choose?
| If… | Use | Key Size | Mode |
|---|---|---|---|
| New smart card system | AES | 128 or 256 | GCM (auth) or CBC+HMAC |
| FIDO2 / WebAuthn | AES | 256 | CBC (per CTAP2 spec) |
| SCP03 secure channel | AES | 128 | CBC + CMAC |
| Legacy EMV (SCP02) | 3DES | 112 (2TDEA) | CBC + Retail MAC |
| MIFARE DESFire EV1 | 3DES | 112 | CBC (hardware) |
| Any new code using DES | — | — | STOP — use AES |