HMACリクエスト署名
GETを含むすべての/v1/*にHMAC-SHA256署名が必要です。サーバーはタイミング攻撃を防ぐため定時間比較で検証します。
必須ヘッダー
先頭の4個のヘッダーは全リクエストで必須です。openapi.jsonのセキュリティ定義を参照しています。
| ヘッダー | 型 | 意味 |
|---|---|---|
X-TKE-Key | 全リクエスト | 公開key_id(tke_live_… / tke_test_… / tke_member_live_… / tke_member_test_…) |
X-TKE-Timestamp | 全リクエスト | UNIX時刻のミリ秒(整数文字列) |
X-TKE-Nonce | 全リクエスト | リクエストごとに固有のUUID v4またはv7 |
X-TKE-Signature | 全リクエスト | HMAC-SHA256の小文字16進数 |
Idempotency-Key | 5 エンドポイント | クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。 |
必須の操作:
Idempotency-KeyPOST
/v1/ordersPOST/v1/orders/bulkPOST/v1/esims/{id}/cancelPOST/v1/esims/{id}/change-planPOST/v1/esims/{id}/refund-requests署名の正規化式
HMAC-SHA256認証(§4)。X-TKE-Key(公開key_id)、X-TKE-Timestamp(エポックミリ秒)、X-TKE-Nonce(リクエストごとのUUID)、X-TKE-Signature(小文字16進数)の4ヘッダーを送信します。signing_string = method path timestamp nonce body_hash、body_hash = SHA256(raw_body)の16進数です。定数時間で比較します。pathにはクエリ文字列を含みます。
各部分を改行で連結します \n (LF)、署名対象は SHA256(raw_body) です。サーバーは受信した正確なバイトを再度ハッシュして検証します。
text
signing_string = method + "\n"
+ path + "\n" # クエリを含み、スキーム・ホストを除く
+ timestamp + "\n" # = header X-TKE-Timestamp (epoch ms)
+ nonce + "\n" # = header X-TKE-Nonce
+ body_hash # SHA256(raw_body) hex lowercase
signature = HMAC_SHA256(secret, signing_string) → hex lowercase GET、DELETEや空の本文では
raw_body = "" → body_hash = SHA256("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.HMAC署名コード例
secretとkey_idを置き換え、ハッシュしたバイトをそのまま送信します。署名後に再シリアライズしないでください。
bash
#!/usr/bin/env bash
# Yeu cau: openssl. Ky POST /v1/orders.
KEY_ID="tke_test_ab12cd34..."
SECRET="tke_secret_test_0123456789abcdef"
METHOD="POST"
PATH_Q="/v1/orders"
BODY='{"items":[{"package_code":"THAY-BANG-MA-GOI-CUA-BAN","quantity":2}]}'
TS="$(date +%s000)" # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'
'"$PATH_Q"$'
'"$TS"$'
'"$NONCE"$'
'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"
curl -sS "https://api.tongkhoesim.com$PATH_Q" -H "X-TKE-Key: $KEY_ID" -H "X-TKE-Timestamp: $TS" -H "X-TKE-Nonce: $NONCE" -H "X-TKE-Signature: $SIG" -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" --data-raw "$BODY"バックエンドのテストベクトル
バックエンドが生成したベクトルで署名実装を確認できます。
以下と同じ入力で署名して照合してください。不一致時はsigning_stringを比較します。
サンプルシークレット:
tke_secret_test_0123456789abcdefPOST /v1/orders
method
POSTpath
/v1/orderstimestamp
1720680000000nonce
11111111-1111-4111-8111-111111111111raw_body
{"items":[{"package_code":"VN_5GB_30D","quantity":2}]}body_hash
c197853f7fe46a9f2de1478e565c48ef9369d0152af5117434be8ccfa9391b31signing_string
POST
/v1/orders
1720680000000
11111111-1111-4111-8111-111111111111
c197853f7fe46a9f2de1478e565c48ef9369d0152af5117434be8ccfa9391b31signature(期待値)
97147afdebb5d15cf8441278ef524ce15c715ca95962ddb1cb2604a1672fc5d5GET /v1/wallet/balance
method
GETpath
/v1/wallet/balancetimestamp
1720680000000nonce
22222222-2222-4222-8222-222222222222raw_body
(空)body_hash
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855signing_string
GET
/v1/wallet/balance
1720680000000
22222222-2222-4222-8222-222222222222
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855signature(期待値)
ab16941884d407924c7b15dea008d6f1d8c0c1be96dca3745344218a99257dbe