HMAC 생성 및 검증

API 호출 간 보안을 위한 검증 방식으로 HMAC을 사용합니다.

언어별로 아래 코드를 참조하여 HMAC 검증 부분을 구현합니다. DEV 환경에서는 "test_secret_key"를 사용하여 테스트 해주시면 됩니다. LIVE 환경의 SECRET_KEY는 연동 시작 시 전달해드립니다.

const moment = require('moment');
const qs = require('qs');
const crypto = require('crypto');

function HmacUtil () {

    this.algorithm = "sha256"
    this.secretKey = "test_secret_key"
    this.expiresIn = 2 * 60 * 1000 // 2minutes
 
    this.hmacDatetime = function() {
      return moment().format("YYYY-MM-DDTHH:mm:ssZ")
    }
    
    this.alphabeticalSort = function(a, b) {
      return a.localeCompare(b);
    }
    
    this.sortedQueryString = function(encodedQueryString) {
      let obj = qs.parse(encodedQueryString);
      return qs.stringify(obj, { sort: this.alphabeticalSort });
    }
    
    this.payloadHash = function(payload) {
      return crypto.createHash(this.algorithm).update(payload,'utf8').digest('hex');
    }
    
    this.stringToSign = function(method, uri, hmacDatetime, queryString, payload) {
      return method + "\n" + uri + "\n" + hmacDatetime + "\n" + this.sortedQueryString(queryString) + "\n" + this.payloadHash(payload)
    }
    
    this.sign = function(stringToSign) {
      rawHmac = crypto.createHmac(this.algorithm, this.secretKey).update(stringToSign).digest('hex');
      return Buffer.from(rawHmac).toString('base64');
    }
    
    this.signature = function(method, uri, hmacDatetime, queryString, payload) {
      return this.sign(this.stringToSign(method, uri, hmacDatetime, queryString, payload));
    }
    
    this.isValid = function(method, uri, hmacDatetime, queryString, payload, signature) {
      let sameSignature = this.signature(method, uri, hmacDatetime, queryString, payload) === signature
      let notExpired = (new Date() - new Date(hmacDatetime)) < this.expiresIn // 2.minutes
      return sameSignature && notExpired
    }
    
}
 

API 호출 시 검증에 필요한 값은 요청 헤더로 전달됩니다. 헤더에서 추출한 signature 와 API 호출 정보로 생성한 signature 가 동일한 경우 유효한 요청입니다.

signature 생성 예시

아래는 signature 생성에 사용 되는 데이터 예시입니다.

위 데이터로 signature 를 생성한 결과입니다. (secret_key 는 test_secret_key 사용) 직접 구현한 모듈로 테스트 시 동일한 signature 가 생성 되는지 확인해주세요.

payload로 만든 SHA256 해시값은 https://emn178.github.io/online-tools/sha256.html 등의 해시 생성 툴을 통해서도 확인할 수 있습니다.

StringToSign값의 개행 처리에 주의해서 Signature값을 생성해주세요.

샘플 코드

실제 signature 검증과 관련하여 아래의 샘플을 통해 확인하실 수 있습니다.

Last updated