Skip to content

HMAC 요청 서명 ​

보호 API는 X-API-KEY, X-TIMESTAMP, X-NONCE, X-SIGNATURE를 요구합니다. 서명은 발급된 HMAC Key로 계산한 HMAC-SHA256을 Base64로 인코딩한 값입니다.

text
METHOD\n\nPATH_WITH_QUERY\n\nTIMESTAMP\n\nNONCE\n\nBODY_JSON

Node.js 예제 ​

js
import { createHmac, randomUUID } from 'node:crypto'

const hmacKey = process.env.WALLET_HMAC_KEY
if (!hmacKey) throw new Error('WALLET_HMAC_KEY is required')

const method = 'GET'
const pathQuery = '/networks?is_active=true&page=1&page_size=20'
const timestamp = String(Date.now())
const nonce = randomUUID()
const bodyJson = ''
const stringToSign = [method, pathQuery, timestamp, nonce, bodyJson].join('\n\n')
const signature = createHmac('sha256', hmacKey).update(stringToSign).digest('base64')

실제 전송하는 경로, 쿼리 순서, 인코딩, timestamp, nonce, 직렬화된 body를 그대로 서명합니다. 재시도할 때도 인증 값을 모두 새로 만듭니다.

GET·DELETE처럼 본문이 비어 있어도 nonce와 빈 본문 사이의 \n\n은 서명에 포함됩니다. 셸의 $(...)는 끝의 줄바꿈을 제거하므로 서명 대상 문자열을 중간 변수에 담지 않고 printf 출력을 HMAC 계산으로 직접 전달합니다. JSON 본문은 JSON.stringify 또는 jq -c로 공백 없이 직렬화해 그 문자열을 서명하고 전송합니다.

오류조치
MISSING_AUTH_HEADER누락 헤더 추가
INVALID_API_KEY환경과 키 확인
INVALID_TIMESTAMP시스템 시각 동기화
NONCE_REPLAYED새 nonce 생성
INVALID_SIGNATURE정규 문자열과 서명 재생성

HMAC Key나 전체 인증 컨텍스트를 로그에 남기지 않습니다.

POST body 예제 ​

js
const bodyJson = JSON.stringify({
  uid: 'user-001', account_type: 'USER', metadata: { source: 'onboarding' }
})
const canonical = ['POST', '/accounts', timestamp, nonce, bodyJson].join('\n\n')

HTTP client에는 object가 아니라 bodyJson 자체를 전달하며 두 번째 직렬화를 허용하지 않습니다.

Body 없는 GET, 순서가 있는 query의 GET, 중첩 JSON POST, Unicode metadata, 빈 object, 새로운 인증 값으로 수행하는 재시도를 테스트합니다. 고정 fixture key는 테스트에만 사용하고 운영 키를 서명 테스트에 복사하지 않습니다.

OOLIN은 BPMG가 제공하는 디지털자산 운영 인프라 제품입니다.