결제 데이터 보안: 암호화와 해시의 차이
암호화와 해시의 차이부터 pktHash 원리까지. 개발자 도구로 금액을 조작당하지 않는 보안 개념 가이드.

"브라우저 개발자 도구로 금액을 바꿨는데 결제가 됐어요!"
보안 테스트 중 종종 발견되는 취약점인데요. 악의적인 사용자가 브라우저 개발자 도구로 결제 금액을 10000원에서 100원으로 바꿔서 PG사로 전송하는 거예요.
온라인 결제에서는 클라이언트(브라우저)를 거쳐 데이터가 전송되기 때문에 변조 위험이 항상 존재해요. 이런 보안 위협을 막기 위해 헥토파이낸셜은 암호화(Encryption) 와 해시(Hash) 기술을 이중으로 적용하고 있어요.
이번 아티클에서는 두 기술의 차이점과 실제 구현 방법을 알아볼게요.
암호화와 해시의 차이점
개발 현장에서 자주 혼용되는 두 용어인데요. 목적과 특징이 명확히 달라요.
| 구분 | 암호화 (Encryption) | 해시 (Hash) |
|---|---|---|
| 목적 | 데이터 기밀성 (숨기기) | 데이터 무결성 (검증) |
| 복호화 | 가능 (양방향) | 불가능 (단방향) |
| 비유 | 열쇠로 잠긴 금고 | 봉인 스티커 |
| 사용처 | 카드번호, 계좌번호 등 민감정보 | 주문정보 위변조 방지 |
| 헥토파이낸셜 적용 방식 | AES-256/ECB/PKCS5Padding | SHA-256 |
1. 암호화: 데이터를 감추는 기술
암호화는 데이터를 제3자가 알아볼 수 없는 형태로 변환하는 기술이에요. 암호화 키를 가진 당사자(PG사)만이 원본 데이터를 복원(복호화)할 수 있어요.
- 적용 대상: 카드번호, 유효기간, 비밀번호 등 민감한 개인정보
- 특징: 데이터가 유출되더라도 키가 없으면 내용을 알 수 없어요.
2. 해시: 데이터의 무결성을 검증하는 기술
해시는 데이터를 고정된 길이의 문자열로 변환하는 기술이에요. 입력값이 조금이라도 바뀌면 해시값은 완전히 달라져요.
- 적용 대상: 주문번호, 결제금액 등 위변조 여부 확인이 필요한 정보
- 특징: 복호화가 불가능하고, 원본 데이터가 변경되었는지 확인하는 용도로 사용돼요.
이중 보안 시스템의 원리
헥토파이낸셜은 왜 두 가지 방식을 모두 사용할까요? 각각의 방식만으로는 보안에 한계가 있기 때문이에요.
- 암호화만 할 경우: 공격자가 암호화된 문자열을 통째로 다른 값(예: 100원 결제 시의 암호문)으로 바꿔치기하는 '재전송 공격'에 취약해요.
- 해시만 할 경우: 데이터 내용이 평문으로 노출되어 개인정보가 유출될 수 있어요.
그래서 암호화로 내용을 숨기고, 해시로 위변조를 방지 하는 이중 보안 체계를 적용하고 있어요.
구현 예제 (Node.js)
실제 연동 시 사용되는 암호화 및 해시 생성 코드예요.
1. AES-256 암호화 (PKCS5 패딩)
민감한 카드번호 등을 암호화해요.
알고리즘: AES-256/ECB/PKCS5Padding
- AES-256: 256비트 키 길이를 사용하는 고급 암호화 표준
- ECB 모드: 각 블록을 독립적으로 암호화
- PKCS5 패딩: 데이터 길이가 블록 크기(16바이트)에 맞지 않을 때 빈 공간을 채우는 방식
const crypto = require('crypto');
function encryptAES256(text, key) {
// 키는 반드시 32byte여야 합니다
const cipher = crypto.createCipheriv('aes-256-ecb', key, null);
cipher.setAutoPadding(true); // PKCS5 패딩 자동 적용
let encrypted = cipher.update(text, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
}
// 사용 예시
const secretKey = 'pgSettle30y739r82jtd709yOfZ2yK5K'; // 32바이트
const cardNum = '1234567812345678';
const encryptedCardNum = encryptAES256(cardNum, secretKey);
console.log('암호화된 카드번호:', encryptedCardNum);
2. SHA-256 해시 (pktHash) - 신용카드 결제 기준
신용카드 결제 시 pktHash 생성 방법이에요. 정해진 순서대로 파라미터를 조합 하는 것이 중요해요.
조합 순서 (PG 신용카드 결제창 기준)
function generatePktHash(mchtId, method, mchtTrdNo, trdDt, trdTm, trdAmt, hashKey) {
// 정해진 순서로 조합 (PG 신용카드 결제창 기준)
const rawString = mchtId + method + mchtTrdNo + trdDt + trdTm + trdAmt + hashKey;
// SHA-256 해시 생성 후 Hex 인코딩 (소문자)
const hash = crypto.createHash('sha256').update(rawString, 'utf8').digest('hex');
return hash;
}
// 사용 예시 - 신용카드 결제
const mchtId = 'nx_mid_il'; // 상점 아이디
const method = 'CARD'; // 결제수단 (신용카드)
const mchtTrdNo = 'ORDER20231126001'; // 상점 주문번호
const trdDt = '20231126'; // 거래일자 (YYYYMMDD)
const trdTm = '153000'; // 거래시간 (HHMMSS)
const trdAmt = '10000'; // 거래금액 (평문)
const hashKey = 'ST1009281328226982205'; // 해시생성 인증키
const pktHash = generatePktHash(mchtId, method, mchtTrdNo, trdDt, trdTm, trdAmt, hashKey);
console.log('생성된 pktHash:', pktHash);
참고
두 가지만 기억하세요
결제 시스템의 보안은 타협할 수 없는 요소예요.
- 암호화(AES-256) 는 데이터를 안전하게 숨겨요.
- 해시(SHA-256) 는 데이터가 변조되지 않았음 을 증명해요.
이 두 가지 기술을 정확히 이해하고 구현하면, 고객의 소중한 정보를 보호하고 신뢰할 수 있는 결제 서비스를 제공할 수 있어요.
