파일 업로드
  1. base64hub
  2. 키와 해시
  3. HMAC 생성기

HMAC 생성기 (Base64)

메시지와 비밀 키를 입력하면 HMAC 서명을 Base64, Base64URL, hex로 받습니다. 시크릿을 어디에도 보내지 않고 웹훅 서명과 API 요청 서명을 디버깅할 때 쓰세요.

무료 가입 없음, 제한 없음 로컬 업로드 없음 키 형식 텍스트, hex, Base64 바이트 업데이트 2026. 10. 27.

브라우저에서 처리됩니다. 이 페이지는 데이터를 어디로도 보낼 수 없습니다 – 확인 방법

Base64로 HMAC을 계산하는 방법

  1. HMAC 모드와 SHA-256이 선택되어 있습니다. API가 SHA-1, SHA-384, SHA-512, MD5를 쓴다면 알고리즘에서 다른 것을 고르세요.
  2. 비밀 키를 입력하고 키 형식을 설정하세요. 일반 시크릿 문자열이면 텍스트 (UTF-8), 키가 인코딩된 바이트로 주어졌다면 Hex나 Base64입니다.
  3. 텍스트에 메시지를 입력하거나 붙여넣으세요. 또는 입력을 파일로 바꾸고 정확한 페이로드 파일을 놓으세요.
  4. 서명을 Base64, Base64URL, hex로 복사하세요. 모든 알고리즘은 모든 해시로 계산한 HMAC을 한 번에 보여 주므로, 문서에 어떤 해시를 쓰는지 분명하지 않을 때 도움이 됩니다.

빈 키도 받아서 결과를 내지만, 그런 HMAC은 아무것도 보호하지 못한다는 안내가 표시됩니다.

예시 값

키 key와 메시지 The quick brown fox jumps over the lazy dog의 결과입니다.

알고리즘Base64 HMAC
HMAC-MD5gAcHE0Y+d0m5DC3CSRHidQ==
HMAC-SHA13nybhbi3iqa8ino29wqQcBydtNk=
HMAC-SHA25697yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=
HMAC-SHA512tCrwkFe6weLUFwjkipAuCbX/fxKrQopP6GZTxz3SSPuC+UilSfe3kaW0GRXuTR7Dk1NX5OIxclDQNyr6Lr7rOg==

HMAC-SHA256 값을 hex로 쓰면 f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8로, Wikipedia의 HMAC 문서에 나오는 익숙한 테스트 벡터입니다. 키 인코딩에 따라 결과가 달라집니다. 텍스트 a2V5를 키로 쓰면 5O+7AtpguFrgIRw1qXGU+m0OaTs1oV1kwRQ/hI1WAUE=가 나오지만, a2V5를 Base64로 읽으면 key의 바이트가 되어 다시 97yD9DBT…가 나옵니다.

웹훅 서명: Base64인가 hex인가

제공자들은 HMAC을 쓴다는 점에는 같지만, 출력 인코딩과 서명 대상은 다릅니다. 문서화가 잘된 몇 가지 예입니다.

제공자헤더알고리즘인코딩서명 대상
ShopifyX-Shopify-Hmac-Sha256HMAC-SHA256Base64원본 요청 본문
Standard Webhooks (Svix)webhook-signature: v1,…HMAC-SHA256Base64id.timestamp.body, 키는 whsec_ 뒤의 Base64
TwilioX-Twilio-SignatureHMAC-SHA1Base64URL과 정렬된 POST 파라미터
GitHubX-Hub-Signature-256: sha256=…HMAC-SHA256hex원본 요청 본문
StripeStripe-Signature: t=…,v1=…HMAC-SHA256hextimestamp.body

이 도구의 값이 hex로는 맞는데 코드는 Base64로 비교하고 있다면, 또는 그 반대라면, 계산은 맞고 인코딩만 다른 것입니다. 무엇을 서명하는지는 제공자 문서를 확인하세요. 타임스탬프 접두사는 오래된 요청의 재전송을 막기 위해 있습니다.

코드에서 서명 검증하기

원시 바이트를 상수 시간으로 비교하고, 받은 그대로의 본문을 해시하세요.

const crypto = require("crypto");

function verifyWebhook(rawBody, secret, signatureHeader) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest();
  const given = Buffer.from(signatureHeader, "base64");
  return given.length === expected.length && crypto.timingSafeEqual(given, expected);
}

rawBody에 여우 문장의 Buffer를, 시크릿에 key를, 표의 Base64 값을 넣으면 true를 돌려줍니다. 원본 본문 대신 JSON.stringify(JSON.parse(body))를 넣으면, 제공자의 JSON에 직렬화기가 지워 버리는 공백이 하나라도 있는 순간 false를 돌려줍니다. Express에서는 웹훅 경로에서 express.raw()로 본문을 읽어야 한다는 뜻입니다.

Python에서는 hmac.new(key, body, hashlib.sha256).digest()로 계산하고, Base64로 인코딩한 뒤 hmac.compare_digest로 확인합니다. 명령줄에서는 openssl dgst -sha256 -hmac 'key' -binary | base64가 같은 Base64를 출력하며, 키가 hex라면 -mac HMAC -macopt hexkey:…를 쓰세요. 강력한 키는 Base64 키 생성기의 HMAC 시크릿 프리셋이 무작위 32바이트를 만들어 줍니다. 서명된 요청이 아니라 서명된 토큰이 필요하다면 JWT 인코더를 참고하세요.

자주 묻는 질문

웹훅 HMAC이 일치하지 않는 이유는 무엇인가요?

서명은 요청 본문의 바이트 그대로를 대상으로 합니다. 프레임워크가 JSON을 파싱한 뒤 다시 직렬화한 사본을 해시하면 공백이나 키 순서가 바뀌어 결과가 달라집니다. 원본 본문을 해시하고, 제공자가 hex와 Base64 중 무엇을 기대하는지, 시크릿을 먼저 디코딩해야 하는지 확인하세요.

HMAC 시크릿은 텍스트인가요, Base64인가요?

제공자마다 다릅니다. 대부분은 UTF-8 텍스트로 쓰는 문자열을 줍니다. 일부는 whsec_ 같은 접두사 뒤에 Base64로 인코딩된 키를 주는데, 이는 쓰기 전에 바이트로 디코딩해야 합니다. 그에 맞게 키 형식을 설정하세요.

해시와 HMAC의 차이는 무엇인가요?

메시지의 SHA-256은 누구나 계산할 수 있으므로 해시는 우발적인 변경만 감지합니다. HMAC은 비밀 키를 섞기 때문에 키를 가진 사람만 올바른 값을 만들 수 있고, 그래서 서명이 됩니다.

HMAC-MD5나 HMAC-SHA1을 써도 되나요?

둘 다 오래된 API에서 아직 쓰이며, 충돌이 HMAC 위조로 이어지지 않기 때문에 그냥 MD5나 SHA-1보다 훨씬 강합니다. 새로 설계한다면 HMAC-SHA256을 고르세요.