HMAC認証 (1.0)

はじめに

OPA APIはHMAC(Hash-based message authentication code)認証を使ってしており、マーチャントはHMAC認証を使用してこれらのAPIを呼び出す必要があります。 HMAC認証は、ハッシュ関数と組み合わせてキーを使用するメッセージ認証コードです。 HMACベースの認証の実装では、認証オブジェクトを構築するために要求全体が考慮されます。 クライアント(マーチャント)は、以下のドキュメントに基づいてHMAC認証コードを作成し、HTTP Authorizationリクエストヘッダーに設定します。 要求を受信すると、サーバー(OPA)はこの認証コードを再作成し、両方のコードが一致する場合は要求が正常に実行されます。一致しない場合は、不正な応答が返されます。

HMAC認証

HMAC認証フローに関するパラメータおよび生成ステップ

認証オブジェクトに必要なパラメータ

Value Description Example
API Key PayPayから発行されたAPI Key APIKeyGenerated
API Key secret PayPayから発行されたAPI Key Secret APIKeySecretGenerated
Request URI リクエストURL path /v2/codes
Request method HTTPメソッド POST
Epoch 現在のエポックタイムスタンプ(秒単位),
Note : サーバ時刻との差が2分未満である必要があります。
1579843452
Nonce ランダムに生成された文字列。
Note : 任意の文字列、length 8を推奨。
acd028
Request body リクエストで渡されるbody。

{"sampleRequestBodyKey1":"sampleRequestBodyValue1","sampleRequestBodyKey2":"sampleRequestBodyValue2"}

Request content type リクエストヘッダーで渡されるコンテンツタイプ。 application/json;charset=UTF-8;
hash (MD5(Request body, Request content type)) リクエストの本文とコンテンツタイプのハッシュ。以下に記載されているStep1で生成されます。 1j0FnY4flNp5CtIKa7x9MQ==

これらから生成されるサンプルHMAC Authヘッダーは以下の通りです。

hmac OPA-Auth:APIKeyGenerated:NW1jKIMnzR7tEhMWtcJcaef+nFVBt7jjAGcVuxHhchc=:acd028:1579843452:1j0FnY4flNp5CtIKa7x9MQ==

HMAC authヘッダーの生成ステップ

Step 1: MD5アルゴリズムを使用してbodyとcontent-typeをハッシュ化する

サンプルコード

private String requestBody;
private String contentType;

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(contentType.getBytes(StandardCharsets.UTF_8));
md.update(requestBody.getBytes(StandardCharsets.UTF_8));
String hash = new String(
          Base64.getEncoder().encode(md.digest()),
          StandardCharsets.UTF_8);

Note : HTTP GETメソッドの場合など、リクエストの本文がない場合、MD5を生成する必要はありません。代わりに、hashには"empty"がセットされます。

Step 2 : HMAC-SHA256でハッシュ化される文字列を生成します。

リクエストの署名には、以下のパラメータが必要です。

private String requestUrl; //Only the request URI Example: "/v2/codes/payments/dynamic-qr-test-00002"
private String httpMethod;
private String nonce; //Random string
private String epoch;
private String contentType;
private String hash; //Output of step 1
private static final String DELIMITER = "\n";

byte[] hmacData = new StringBuilder()
                    .append(requestUrl)
                    .append(DELIMITER)
                    .append(httpMethod)
                    .append(DELIMITER)
                    .append(nonce)
                    .append(DELIMITER)
                    .append(epoch)
                    .append(DELIMITER)
                    .append(contentType)
                    .append(DELIMITER)
                    .append(hash != null ? hash : "")
                    .toString()
                    .getBytes(StandardCharsets.UTF_8);

Note : HTTP GETメソッドの場合など、リクエストの本文がない場合、content-typeおよびhashには"empty"がセットされます。

Step 3 : Step2で生成された値と、Key secretを使用してHMACオブジェクトを生成します。

public final String toBase64HmacString() {
    private String apiKeySecret;
    private byte[] dataToSign; //Output from step 2
    try {
      SecretKeySpec signingKey = new SecretKeySpec(apiKeySecret.getBytes(StandardCharsets.UTF_8),
          "HmacSHA256");
      Mac sha256HMAC = Mac.getInstance("HmacSHA256");
      sha256HMAC.init(signingKey);
      byte[] rawHmac = sha256HMAC.doFinal(dataToSign);
      return java.util.Base64.getEncoder().encodeToString(rawHmac);
    } catch (GeneralSecurityException e) {
      LOGGER.error("Unexpected error while creating hash: " + e.getMessage());
      throw new IllegalArgumentException(e);
    }
  }

Step 4 : ヘッダーオブジェクトを生成します。

String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":" + hash;

Note: macDataはStep3で生成された値を使用してください。また、nonceとepochは、Step2で使用した値を渡す必要があります。

HTTP GETメソッドの場合などリクエストの本文がない場合、hash値は"empty"となるため、ヘッダーオブジェクトは下記の通りとなります。

String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":empty";

authHeaderの値を、HttpHeader.AUTHORIZATIONにセットして渡してください。
PayPay側で渡ってきたデータをデコードし、SHA256( "key"、requestParams)を再作成します。 再作成したmacDataとヘッダーで渡ってきた値が一致しているかを検証します。

変更履歴

ドキュメント更新日 リリース日 種別 セクション 変更箇所
2023.03.24 Released Documentation Fix 認証オブジェクトに必要なパラメータ Request URIの説明を修正しました。