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 가 동일한 경우 유효한 요청입니다.
헤더
설명
X-Hmac-Datetime
HMAC 생성 시간 (signature 생성시에도 포함되는 값)
X-Hmac-Signature
HMAC Signature
signature 생성 예시
아래는 signature 생성에 사용 되는 데이터 예시입니다.
데이터
값
method
(대문자)
POST
uri
/api/offerwall/reward
hmacDateTime
2020-06-08T16:56:34+09:00
queryString
(빈값)
payload
(raw body)
{"campaign_id":"1","uid":"test_uid","advertising_id":"d2ca81dc-e3bc-4449-aa8b-f7b0f62b76b8","platform":1,"reward":100,"reward_type":0,"ad_name":"테스트 광고명!","repeat_participate_type":0,"click_key":"MTU5MTYwMzA2OTA4ODo-PDp0ZXN0X3VpZDo-PDp1U0hIaE5wOTZQeGpGaDFOUjlRR2NiU0U"}
위 데이터로 signature 를 생성한 결과입니다. (secret_key 는 test_secret_key 사용) 직접 구현한 모듈로 테스트 시 동일한 signature 가 생성 되는지 확인해주세요.
처리결과
값
SHA256(payload)
04dd512aa6c17b5e1f38cc3c2d9f652ea22878d51e5ea483161852f20e85bde9
StringToSign
POST
/api/offerwall/reward
2020-06-08T16:56:34+09:00
04dd512aa6c17b5e1f38cc3c2d9f652ea22878d51e5ea483161852f20e85bde9
HMAC Signature
MDY4MzYwNzc2MWYxZmViMTcxNDczZmYyNzVjY2ZlODMzYTU2OWVmMmI0MzE0N2RkZDBmZGY1MTJlMmEzMjE0Nw==
StringToSign값의 개행 처리에 주의해서 Signature값을 생성해주세요.
샘플 코드
실제 signature
검증과 관련하여 아래의 샘플을 통해 확인하실 수 있습니다.
Last updated
Was this helpful?