본문 바로가기

HMAC 생성기

메시지와 비밀키로 서명값을 만듭니다. 결제사 웹훅이나 API 요청이 진짜인지 확인할 때 씁니다.

로딩 중...

왜 만들었나요

쇼핑몰에 결제를 붙이면서 결제사 웹훅이 날아오기 시작했는데, 이게 정말 결제사가 보낸 건지 누가 흉내 내서 쏜 건지 서버 입장에선 구분할 방법이 없었습니다. 문서를 보니 "우리가 알려준 키로 본문을 HMAC SHA256으로 서명한 값"을 헤더에 같이 보낸다더군요. 그 값이 맞는지 확인하려고 만들었습니다.

Note

입력한 메시지와 비밀키는 서버로 전송되지 않습니다. 계산이 전부 브라우저 안에서 이뤄져, 운영 중인 실제 키를 넣어 확인해도 기기 밖으로 나가지 않습니다.


HMAC 생성기 사용 방법

  1. 위쪽 입력창에 서명할 메시지를 붙여넣고, 아래 칸에 비밀키를 입력합니다. 키가 Hex나 Base64 형태라면 왼쪽 토글로 형식을 바꿉니다.

    HMAC 생성기 입력창에 결제 성공 JSON을 넣고 아래 키 칸에 비밀키를 Text 형식으로 입력한 화면

  2. 알고리즘을 고릅니다. 결제·API 서명은 대부분 SHA256을 쓰기 때문에 기본값도 SHA256입니다. 목록은 SHA·MD·RIPEMD·DES·RC 다섯 묶음으로 나뉘어 있고 옆에 출력 길이(bit)가 함께 적혀 있습니다.

    알고리즘을 SHA256(256bit)으로 고르고 포맷 HEX, 비교할 서명 칸과 전체 비교·Convert 버튼이 놓인 줄

  3. 포맷에서 상대 시스템이 요구하는 출력 형식을 고르고 Convert 를 누릅니다. 검증할 서명이 있다면 비교 칸에 붙여넣으세요. MATCH · MISMATCH 가 바로 표시됩니다. 전체 비교 를 켜면 해시 8종 값이 한 번에 나열돼 상대가 어떤 알고리즘을 썼는지 되짚어 볼 수 있습니다.

    비교 칸에 붙여넣은 서명이 초록색 MATCH로 표시되고 아래에 SHA256 서명값이 나온 화면

이렇게 나옵니다

웹훅 본문과 비밀키를 넣으면 이렇게 나옵니다.

메시지  {"orderId":"A123","status":"paid"}
키      whsec_abc123
알고리즘 SHA256 / HEX
                    ↓
서명    74981fd42aa3b4dd3be3418987d4f048a54a7e24fedadbf9798e266214ab694e

이 값이 요청 헤더로 온 서명과 같으면 진짜 결제사가 보낸 요청입니다.

알아두면 좋은 것

해시와 뭐가 다른가요

해시는 아무나 계산할 수 있습니다. 메시지만 있으면 누구나 같은 값을 만들 수 있어서, 보낸 사람이 누구인지는 증명하지 못합니다.

HMAC은 여기에 비밀키를 섞습니다. 키를 아는 쪽만 올바른 값을 만들 수 있으므로, 값이 맞으면 "키를 가진 사람이 보냈고 내용도 안 바뀌었다"가 동시에 증명됩니다.

이럴 때 씁니다

  • 웹훅 검증 — 결제사·배송사가 보낸 요청이 진짜인지
  • API 요청 서명 — 요청이 중간에 변조되지 않았는지
  • 다운로드 링크 서명 — 만료 시각을 포함해 위조를 막을 때

알고리즘 묶음별 쓰임

묶음담긴 것쓰이는 곳
SHASHA1 · SHA224 · SHA256 · SHA384 · SHA512결제·API 서명 대부분. SHA256 이 기본값입니다
MDMD4 · MD5옛 시스템 대조용
RIPEMDRIPEMD160일부 금융·블록체인 규격
DESDES · DESEDE · DESEDE64 · DESEDE64WITHISO7816-4PADDING카드·금융 단말의 MAC 규격
RCRC2오래된 사내 규격 대조용

DES·RC2 계열은 해시가 아니라 블록 암호로 만드는 인증값(MAC) 이라 결과 길이가 32~64bit로 짧습니다. 전체 비교 목록에는 해시 8종만 들어가고, DES·RC2를 고른 경우에는 그 값이 목록 맨 아래에 함께 붙습니다.

이런 경우에는

서명이 계속 안 맞아요

대개 메시지가 조금 다른 경우입니다.

  • 본문을 그대로 써야 합니다. 정렬하거나 공백을 손대면 값이 달라집니다
  • 줄바꿈 문자가 다를 수 있습니다 (윈도우와 맥이 다름)
  • 키 형식을 확인하세요. 상대가 Hex 키를 줬는데 Text로 넣으면 다른 값이 나옵니다
  • 대소문자 — 출력이 HEX일 때 상대가 대문자를 쓰는지 소문자를 쓰는지

결과 아래에는 메시지와 키의 실제 바이트 수가 표시됩니다. 눈에 안 보이는 원인이 있으면 경고로 알려 줍니다 — 윈도우식 줄바꿈(CRLF), 끝에 붙은 줄바꿈, 파일 앞머리 표시(BOM), 앞뒤 공백. 상대가 알려 준 길이와 바이트 수부터 맞춰 보면 원인이 빨리 좁혀집니다.

이 바이트 수와 경고는 입력을 고치는 즉시 갱신되지만, 위쪽 서명값은 Convert 를 다시 누를 때까지 그대로입니다(입력할 때마다 계산하면 긴 본문에서 화면이 버벅여, 일부러 버튼 방식으로 두었습니다). 고친 뒤라 서명값이 옛 것일 때는 '고치기 전 값입니다' 라는 안내가 함께 뜹니다. 알고리즘·포맷·키 형식·전체 비교를 바꾼 경우는 버튼을 누르지 않아도 곧바로 다시 계산됩니다.

비교 칸은 HEX와 BASE64 중 어느 쪽을 붙여넣어도 알아서 맞춰 대조합니다. 지금 고른 출력 형식과 달라도 됩니다.

MD5·MD4로 만들어도 되나요

보안 목적이라면 쓰지 마세요. 오래된 방식이라 안전하지 않습니다. 옛 시스템과 맞춰야 할 때만 쓰고, 새로 만드는 것은 SHA256 으로 하세요.

키는 절대 공개되면 안 됩니다

HMAC의 안전성은 키를 상대와 나만 안다는 데서 나옵니다. 코드에 그대로 적어 두거나 저장소에 올리면 서명이 아무 의미가 없어집니다.

이 도구로는 안 되는 것

  • 파일은 받지 않습니다. 입력창에 붙여넣은 글자만 서명합니다
  • 서명을 검증해 통과·차단을 결정하지 않습니다. 붙여넣은 서명과 같은지 MATCH · MISMATCH 로 알려 주는 것까지만 합니다. 요청을 막는 판단은 서버가 해야 합니다
  • 비밀키를 만들어 주지 않습니다 — 상대가 발급한 키를 넣어 쓰세요

용어 설명

HMAC

메시지 + 비밀키로 만드는 서명값입니다. 키를 아는 쪽만 같은 값을 만들 수 있어서, 보낸 사람 확인과 위조 방지를 동시에 합니다.

웹훅

어떤 일이 일어났을 때 상대 서버가 내 서버로 먼저 보내는 알림입니다. 결제 완료·배송 시작처럼 실시간으로 알아야 하는 일에 쓰이며, 아무나 흉내 낼 수 있기 때문에 서명 검증이 필요합니다.

HMAC 생성기 자주 묻는 질문

HMAC과 일반 해시의 차이가 뭔가요?

일반 해시 H(message)는 메��지만 알면 누구나 계산할 수 있지만, HMAC은 비밀 키(Secret Key)를 함께 사용하여 키를 모르는 사람은 올바른 값을 생성할 수 없습니다. 이를 통해 메시지의 무결성(변조 여부)과 인증(발신자 확인)을 동시에 보장합니다.

Webhook 서명 검증에 HMAC을 어떻게 활용하나요?

GitHub, Stripe, Slack 등의 서비스는 Webhook 요청 시 헤더에 HMAC 서명을 포함합니다. 예를 들어 GitHub은 X-Hub-Signature-256 헤더에 HMAC-SHA256(secret, body) 값을 전달합니다. 수신 서버에서 동일한 방식으로 계산한 값과 비교하여 요청이 해당 서비스에서 온 것인지 검증합니다.

HMAC 키의 권장 길이는 얼마인가요?

HMAC 키는 최소한 사용하는 해시 함수의 출력 길이 이상이어야 합니다. HMAC-SHA256이면 32바이트(256비트) 이상, HMAC-SHA512이면 64바이트(512비트) 이상을 권장합니다. 충분히 무작위한 값으로 생성해야 하며, 예측 가능한 문자열은 사용하지 마세요.

비밀 키가 서버로 전송되나요?

아니요, 모든 HMAC 연산은 브라우저 안에서 끝납니다. SHA 계열과 MD5·RIPEMD160은 자바스크립트 해시 구현으로, MD4는 WebAssembly 모듈로, DES·3DES·RC2 계열 MAC은 자바스크립트 암호 라이브러리로 계산하며 어느 경우에도 입력한 메시지와 비밀 키가 외부 서버로 전송되지 않습니다.

Timing Attack이 뭔가요?

HMAC 검증 시 일반 문자열 비교(===)를 사용하면, 불일치 위치에 따라 응답 시간이 미세하게 달라집니다. 공격자가 이 시간 차이를 분석하여 한 바이트씩 올바른 HMAC 값을 추측할 수 있으며, 이를 Timing Attack이라 합니다. 서버 측 검증에서는 반드시 상수 시간 비교(Constant-time comparison)를 사용해야 합니다.

마지막 업데이트: