기술 포스트
신용카드 데이터 복호화 방법, 1부
자주 제기되는 질문 중 하나는 다음과 같습니다: ID TECH 신용카드 리더기에서 수신한 트랙 데이터가 암호화되어 있습니다. 이 데이터를 어떻게 복호화할 수 있을까요?
답변은 다음과 같습니다: 해당 거래에 적합한 세션 키를 확보한 후, 그 키를 사용하여 데이터 페이로드를 Triple-DES (또는 AES, 상황에 따라 적절한 방식으로) 방식으로 복호화해야 합니다.
복호화 과정 자체는 기대와 달리 매우 단순합니다. TDES 또는 AES의 오픈소스 구현체 중 하나를 활용하면 되며(핵심 암호화 루틴을 직접 구현할 필요가 없습니다), CBC(Cipher Block Chaining) 모드로 동작하고 초기 벡터는 기본값인 모두 0바이트로 설정됩니다. 올바른 16바이트 복호화 키만 보유하고 있다면, 복호화 과정은 어렵지 않습니다.
까다로운 부분은 바로 키를 도출하는 과정입니다. 이를 위해서는 ANSI X9.24-1, 즉 DUKPT.
DUKPT의 세계에 오신 것을 환영합니다
신용카드 리더기에서는 각 거래마다 서로 다른 키로 데이터가 암호화된다는 점을 이해하는 것이 중요합니다. 이 키는 특정 거래에 고유하게 적용되며(따라서 DUKPT, 즉 '거래별 파생 고유 키'라는 약어가 사용됩니다), 동일한 키가 두 번 사용되는 일은 없습니다. 그 결과, 재전송 공격(replay attack)은 사실상 불가능합니다.
DUKPT의 작동 원리를 이해하려면 KSN(Key Serial Number), 즉 키 일련번호의 개념을 어느 정도 알아야 합니다. 핵심은 KSN이 10바이트 값으로, 하위 21비트가 카운터로 구성되어 있어 거래마다 값이 변경된다는 점입니다.
Key Serial Number 구조
기억하세요: 암호화된 카드 거래에는 항상 KSN이 포함됩니다. KSN의 길이는 항상 10바이트이며, 평문으로 전송됩니다. KSN 자체만으로는 민감한 정보가 노출되지 않지만, 세션 키를 파생하는 데 반드시 필요합니다.
카드 리더기는 공장에서 암호화 설정을 완료할 때, 16바이트 키와 10바이트의 초기 KSN이 주입됩니다. 주입되는 키는 BDK(Base Derivation Key), 즉 기본 파생 키라 불리는 최고 기밀 키로부터 파생되며, BDK 자체는 절대 주입되지 않습니다. (하나의 BDK에서 수많은 키를 파생할 수 있으므로, 단일 BDK로부터 고유한 키를 수백 또는 수천 개의 카드 리더기에 주입하는 것이 가능하며, 실제로도 일반적인 방식입니다.) 파생 과정 자체에는 KSN이 사용됩니다. KSN에는 기기의 일련번호 및 기타 다양한 '네임스페이스' 정보가 포함되어 있으므로, 특정 BDK+KSN 조합으로 생성된 해시(또는 키)는 사실상 해당 기기에 고유합니다. 또한, 암호학적으로 안전한 단방향 해시 방식이 사용되기 때문에, KSN을 알고 있더라도 원본 BDK를 역산하는 것은 불가능합니다.
거래가 발생할 때마다, 카드 리더기(사실상 오늘날의 모든 카드 리더기가 DUKPT를 지원합니다)는 현재 KSN 값과 IPEK(Initial PIN Encryption Key, 초기 PIN 암호화 키)를 기반으로 고유한 키를 생성합니다. 이렇게 생성된 일회용 세션 키는 거래 데이터의 민감한 부분을 암호화하는 데 사용됩니다.
일단 암호화된 거래 데이터는 카드 발급사 등 인가된 수신 대상에 도달하기 전까지 복호화되지 않습니다. 수신 측(예: 카드 발급사)은 자체적으로 보유한 BDK 사본과 거래 KSN을 활용하여 해당 거래의 세션 키를 재파생하고, 원본 거래 데이터를 복호화합니다. 이는 암호화 측과 복호화 측 모두 동일한 비밀(BDK)을 사전에 공유해야 한다는 점에서 '대칭(symmetric)' 방식이라고 합니다. 수신 측이 메시지를 복호화할 수 있도록, 사전에 필요한 비밀 정보를 제공해 두었다고 가정합니다.
IPEK
DUKPT 세션 키를 얻기 위한 출발점은 항상 IPEK, 즉 초기 키를 파생하는 것입니다. 이를 위해서는 원본 BDK와 KSN을 알아야 합니다. (이 단계에서는 카운터를 0으로 초기화하므로, 해당 기기의 어떤 KSN을 사용해도 무방합니다.)
초기 PIN 암호화 키(IPEK)를 파생하려면 다음 절차를 수행해야 합니다:
1. BDK의 크기가 16바이트인 경우, 이른바 EDE3 방식을 사용하여 24바이트로 확장합니다. 방법은 간단합니다: 키의 첫 8바이트를 키 끝에 복사하여, 처음과 마지막 8바이트가 동일한 24바이트 키를 만들면 됩니다.
원래 키(16진수)가 다음과 같은 형태라면:
최종적으로 다음과 같은 형태가 되어야 합니다:
2. 10바이트 초기 KSN에 16진수 값 0xFFFFFFFFFFFFFFE00000을 AND 연산하여 마스킹합니다. 이 결과값을 "마스킹된 KSN"이라고 합니다.
3. 마스킹된 KSN에서 앞쪽(즉, 가장 왼쪽) 8바이트만 남기고 나머지를 제거하여 8바이트 값을 생성합니다. 다시 말해, 오른쪽 끝의 두 바이트를 잘라냅니다.
4. 확장된 24바이트 BDK를 키로 사용하여, 3단계에서 얻은 마스킹된 KSN의 8바이트를 TDES로 암호화합니다. 이때 초기 벡터는 모두 0으로 설정합니다. (이 경우 데이터가 정확히 한 블록, 즉 8바이트이므로 암호 블록 체이닝은 의미가 없습니다.) 이 단계에서 얻은 8바이트 암호문을 보관하십시오. 이 값이 16바이트 IPEK의 왼쪽 절반이 됩니다.
5. IPEK의 오른쪽 절반을 구하려면, 먼저 원래 16바이트 BDK와 16진수 값 0xC0C0C0C000000000C0C0C0C000000000을 XOR 연산합니다. (대용량 정수 연산을 지원하는 프로그래밍 언어를 사용하는 경우 한 줄의 코드로 처리할 수 있습니다. 그렇지 않은 경우에는 두 값을 부분별로 나누어 순차적으로 XOR 연산해야 합니다.)
6. 5단계에서 얻은 16바이트 값을 EDE3 방식으로 확장하여 24바이트 키 값을 생성합니다.
7. 6단계에서 얻은 24바이트 키 값을 사용하여, 3단계에서 얻은 마스킹된 KSN의 8바이트를 TDES로 암호화합니다. 이 값이 IPEK의 오른쪽 절반이 됩니다.
8. IPEK의 왼쪽 절반과 오른쪽 절반을 연결합니다. 이로써 최종 16바이트 IPEK가 완성됩니다.
코드로 직접 구현하는 경우, 테스트 키 값 0123456789ABCDEFFEDCBA9876543210과 KSN 값 62994900000000000001을 사용하여 IPEK를 생성해 보십시오. 올바르게 구현되었다면 IPEK 결과값은 B5610650EBC24CA3CACDD08DDAFE8CE3이어야 합니다.
키 관리와 암호화 알고리즘
참고로, DUKPT에서는 Triple-DES(TDES)가 광범위하게 사용됩니다. 카드 리더기가 AES 암호화를 사용하도록 설정되어 있더라도, DUKPT 내부에서는 AES가 전혀 사용되지 않습니다. X9.24 표준은 TDES, 그리고 경우에 따라 일반 DES를 사용하도록 규정하고 있습니다. DUKPT 키 파생 프로세스와 거래 데이터 암호화/복호화 프로세스는 완전히 별개라는 점을 명확히 이해하시기 바랍니다. 전자는 키를 파생하는 과정이고, 후자는 그 키를 사용하여 TDES 또는 AES로 데이터를 인코딩하는 과정입니다. 어떤 암호화 루틴도 키의 출처나 키를 생성하는 데 사용된 알고리즘을 알거나 신경 쓰지 않습니다. 중요한 것은 오직 키 자체가 올바르게 동작하는가입니다. 따라서 복호화할 데이터가 AES로 암호화되었더라도, 해당 데이터를 복호화하는 데 사용하는 키는 내부적으로 TDES를 사용하는 DUKPT를 통해 파생됩니다.
소스 코드는 어디에 있나요?
이 포스트의 2부에서는 IPEK와 KSN을 사용하여 실제 DUKPT 세션 키를 도출하는 방법을 자세히 다룰 예정입니다. 직접 실습해볼 수 있도록 실제 소스 코드도 함께 살펴볼 것입니다. 다음 편을 기다리기 어려우시다면, 지금 바로 인기 있는 암호화/복호화 도구를 확인해 보세요. 이 도구에는 2부에서 다룰 DUKPT 알고리즘의 완전한 JavaScript 구현이 포함되어 있으며(오픈소스 TDES 및 AES 구현 포함), 모든 기능을 직접 사용해볼 수 있습니다. 이 도구를 활용하면 DUKPT 키 도출(PIN, Data, MAC의 3가지 변형 모두 지원), 데이터 암호화 및 복호화(TDES 또는 AES), 다양한 해시 생성 등 다양한 작업을 수행할 수 있습니다. 무엇보다도 이 도구는 단순한 웹 페이지 형태이므로 JavaScript를 지원하는 모든 브라우저(모든 플랫폼)에서 사용할 수 있습니다.
KSN과 IPEK를 사용하여 데이터 변형 DUKPT 세션 키를 도출하고 싶으신가요? 2부로 이동하기 에서 계속 이어집니다.
