HMACを利用した安全なAPIキーの送受信

(更新日: 2018/02/14)

Webアプリケーションの機能をサービスとして提供する場合、ランダムな値の秘密のAPIキーを鍵とすることが多いです。

シンプルな方法で使いやすいですが、鍵となるAPIキーをそのまま使っているので鍵が漏洩する可能性があります。HMACやHKDFを使うと鍵となるAPIキーを直接使わないでAPIへのアクセスを認証できます。

HMACを使ったAPIキーによる認証

鍵となるAPIキーを直接GETやPOSTで渡さなければ、鍵が漏れる心配がなくなります。HMACを使う場合の例です。有効期限を付けないとAPIキーを直接使う場合と変わらないので、鍵に30秒の有効期限をつけています。普通は30秒もあれば十分すぎるでしょう。

 

HKDFの場合、鍵と追加情報が別パラメーターなので一度の関数呼び出しで処理できます。HKDFはHMACの拡張なので、上記の処理はHKDFによる鍵の導出と同等です。

 

まとめ

上記の方法を使うと秘密であるべきAPIキーをURLやPOSTリクエストの中に埋め込まずに認証できます。多少追加のCPUリソースが必要ですが、重要なAPIキーが漏洩しづらくなるメリットは大きいです。

直接APIキーを使う場合に比べ面倒に見えますが、この処理はAPI利用のクライアントライブラリで行えばユーザーから見るとAPIキーを直接使う場合と手間は変わりません。

この例では”salt”をユーザーが制御しています。ユーザーが”salt”($tmp_key)を制御できると、秘密のはずの$api_keyを解析されるリスクが高まります。この場合、そもそも正規ユーザーが自分の秘密鍵に対して”salt”を設定しているので、このリスクは考慮する必要がありません。1

ここで紹介した鍵導出方法はFS(Forward Secrecy)/PFS(Perfect Forward Secrecy)という概念です。

HKDF, HMACなどのハッシュ関数を使う場合に知っておくべきFS/PFS

性能を向上させる方法

ハッシュ関数の特性を利用して、結果をキャッシュすると性能を向上できます。

  • ハッシュ関数は入力値が同じであれば、必ず同じ結果を返す

つまり、最終的に生成される$keyは入力パラメーターである$_GET[‘tmp_key’]、$_GET[‘info’]が同じであれば変わりません。PHP配列のキーはバイナリセーフでどんなキーでも大丈夫なので、例えば

$_SESSION[‘key_cache’][$tmp_key . $info] = $key;

とキャッシュし、キャッシュした値と同じであるか比較するだけで十分です。このようにキャッシュするとハッシュ関数(HMAC/HKDF)によるオーバーヘッドはほとんど気にしなくても良い程度にまで軽減できます。

 


  1. 秘密鍵を知らない攻撃者が任意の”salt”を使って導出鍵を取得できる場合、秘密鍵を解析されるリスクが高まります。このような使い方はしてはなりません。 

Comments

comments