Skip to main content

HmacSHA256(해쉬함수)

HMAC-SHA256Hash-based Message Authentication Code와 SHA-256 해시 알고리즘을 결합한 암호화 기술입니다.

결제 시스템에서는 주로 결제 데이터의 위변조를 방지(무결성 검증)하고, API 요청자가 정당한 가맹점인지 인증(Authentication)하기 위한 전자 서명(Signature) 생성에 사용됩니다.

🛡️ 왜 사용하는가?

결제 요청 시 악의적인 해커가 중간에서 데이터를 가로채 금액을 10,000원에서 100원으로 조작하여 서버로 보낸다면 심각한 문제가 발생합니다.

HMAC-SHA256을 사용하면 이 문제를 막을 수 있습니다.

  1. 가맹점과 Easypay는 서로만 아는 비밀 키(Secret Key)를 공유합니다.
  2. 가맹점은 주문정보 + 비밀키를 조합하여 HMAC-SHA256으로 암호화한 서명(Signature) 값을 함께 보냅니다.
  3. 데이터가 조금이라도 변경되면 생성되는 서명 값이 완전히 달라지므로, 서버는 이를 즉시 감지하고 결제를 거단할 수 있습니다.
일반 SHA-256과의 차이

일반 SHA-256은 단순히 메시지를 해싱하지만, HMAC비밀 키(Secret Key)를 함께 사용하여 해싱합니다. 따라서 비밀 키를 모르는 제3자는 유효한 서명 값을 절대 생성할 수 없습니다.


💻 언어별 구현 예제

주문 데이터 문자열(message)과 가맹점 비밀 키(secretKey)를 사용하여 HMAC-SHA256 서명(Hex String)을 생성하는 예제입니다.

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

public class HmacExample {
public static String generateSignature(String message, String secretKey) throws Exception {
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmacSha256.init(secretKeySpec);

byte[] hash = hmacSha256.doFinal(message.getBytes(StandardCharsets.UTF_8));

// Byte Array -> Hex String 변환
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}

Node.js

const crypto = require('crypto');

function generateSignature(message, secretKey) {
return crypto
.createHmac('sha256', secretKey)
.update(message)
.digest('hex'); // Hex String으로 출력
}

const message = "orderId=12345&amount=1000";
const secret = "my_secret_key";
console.log(generateSignature(message, secret));

Python

import hmac
import hashlib

def generate_signature(message, secret_key):
# 키와 메시지는 bytes 타입이어야 함
key_bytes = bytes(secret_key, 'utf-8')
message_bytes = bytes(message, 'utf-8')

signature = hmac.new(key_bytes, message_bytes, hashlib.sha256).hexdigest()
return signature

print(generate_signature("orderId=12345&amount=1000", "my_secret_key"))

PHP

<?php
$message = "orderId=12345&amount=1000";
$secret_key = "my_secret_key";

// true를 주면 binary, false(기본값)를 주면 hex string 반환
$signature = hash_hmac('sha256', $message, $secret_key);

echo $signature;
?>