Skip to content
smallPict

HMAC-SHA256 인증 규격

암호학적 HMAC-SHA256 요청 서명을 사용하여 SmallPict API에 안전하게 인증하는 방법.

SmallPict API는 전송 계층의 보안을 위해 암호학적 HMAC-SHA256 요청 서명 메커니즘을 전면 적용하고 있습니다.

이 표준은 다음과 같은 보안성을 보장합니다:

  1. 페이로드 무결성 (Payload Integrity): 전송 도중 HTTP 메서드, 경로, Body 데이터가 위변조되지 않음을 보장.
  2. 재전송 공격 방어 (Anti-Replay Attack): 엄격한 타임스탬프 유효 윈도우를 통해 탈취된 요청의 재사용 차단.
  3. 비밀 키 유출 제로 (Zero Secret Exposure): Secret Key가 네트워크 통신망을 통해 전송되지 않음.

필수 HTTP 요청 헤더

인증이 필요한 모든 API 호출에는 다음 3개의 HTTP 헤더가 반드시 포함되어야 합니다:

HTTP
X-API-Key: sp_sdk_9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0bX-Timestamp: 1716301234X-Signature: 3a9f8b2c4d6e8a0f1b3c5d7e9f2a4b6c8d0e1f3a5b7c9d1e3f5a7b9c1d3e5f7a
헤더 필드데이터 타입상세 설명
X-API-KeyString고객 공개 API 키 (예: sp_sdk_..., sp_wp_..., sp_test_...)
X-TimestampInteger String요청 발송 시점의 초 단위 Unix 타임스탬프
X-SignatureHex StringSecret Key로 계산된 64자리 16진수 HMAC-SHA256 서명값

서명 생성 알고리즘

1단계: 표준 서명 대상 문자열 (String-To-Sign) 조합

줄바꿈 문자(\n)를 구분자로 하여 HTTP 메서드, 요청 경로, 타임스탬프 및 요청 바디의 SHA-256 해시를 순서대로 연결합니다:

TEXT
{HTTP_METHOD}\n{PATH}\n{TIMESTAMP}\n{BODY_SHA256_HEX}
  • {HTTP_METHOD}: 대문자 HTTP 동사 (예: POST, GET, DELETE).
  • {PATH}: 쿼리 파라미터를 제외한 정확한 요청 URI 경로 (예: /v1/optimize, /v1/quota).
  • {TIMESTAMP}: 요청 헤더의 X-Timestamp와 동일한 타임스탬프.
  • {BODY_SHA256_HEX}: 원본 요청 바디의 SHA-256 16진수 해시값. GET 요청이나 빈 바디의 경우 빈 문자열의 SHA-256 해시 사용: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

2단계: HMAC-SHA256 해시 연산

TEXT
Signature = hex(HMAC_SHA256(SecretKey, StringToSign))

공식 언어별 서명 구현 코드

Node.js (TypeScript)

TypeScript
import crypto from 'node:crypto';
export function signRequest(  method: string,  path: string,  secretKey: string,  bodyString: string = '') {  const timestamp = Math.floor(Date.now() / 1000).toString();  const bodyHash = crypto.createHash('sha256').update(bodyString).digest('hex');  const stringToSign = `${method.toUpperCase()}\n${path}\n${timestamp}\n${bodyHash}`;  const signature = crypto    .createHmac('sha256', secretKey)    .update(stringToSign)    .digest('hex');
  return { timestamp, signature };}

Python 3

Python
import hmacimport hashlibimport time
def sign_request(method: str, path: str, secret_key: str, body_bytes: bytes = b"") -> tuple[str, str]:    timestamp = str(int(time.time()))    body_hash = hashlib.sha256(body_bytes).hexdigest()    string_to_sign = f"{method.upper()}\n{path}\n{timestamp}\n{body_hash}"    signature = hmac.new(        secret_key.encode("utf-8"),        string_to_sign.encode("utf-8"),        hashlib.sha256    ).hexdigest()    return timestamp, signature

Go

Go
package main
import (	"crypto/hmac"	"crypto/sha256"	"encoding/hex"	"fmt"	"strconv"	"time")
func SignRequest(method, path, secretKey string, body []byte) (timestamp string, signature string) {	ts := strconv.FormatInt(time.Now().Unix(), 10)	h := sha256.Sum256(body)	bodyHash := hex.EncodeToString(h[:])	stringToSign := fmt.Sprintf("%s\n%s\n%s\n%s", method, path, ts, bodyHash)
	mac := hmac.New(sha256.New, []byte(secretKey))	mac.Write([]byte(stringToSign))	return ts, hex.EncodeToString(mac.Sum(nil))}

타임스탬프 허용 오차 범위 (±300초)

재전송 공격을 방지하기 위해 SmallPict 게이트웨이는 서버 시간과 클라이언트 시간의 오차를 ±300초(5분) 이내로 엄격히 제한합니다.

|server_time - X-Timestamp| > 300인 요청은 즉시 401 Unauthorized (ERR_TIMESTAMP_DRIFT)로 거부됩니다. 서버의 NTP 시간 동기화를 확인하세요.