あるSEのつぶやき・改

ITやシステム開発などの技術に関する話題を、取り上げたりしています。

OpenSSLでHMAC-SHA256の秘密鍵を生成し署名する方法

Google Apps Script で JWT の仕組みを作ろうと思って、HMAC-SHA256 を使用する際の秘密鍵の生成方法と署名方法を調べました。

本当は独自実装なんてしたくないのですが、ないものは仕方ですからね。。

まず HMAC-SHA256 の秘密鍵のサイズなのですが、RCF によるとハッシュのサイズと同じかそれ以上となっています。

SHA256であれば256ビット、32バイトということですね。

key of the same size as the hash output (for instance, 256 bits for "HS256") or larger MUST be used with this algorithm.

https://www.rfc-editor.org/rfc/rfc7518#section-3.2

ただし、IBM さんによると、秘密鍵の長さが32バイトより長くしても強度を上げることにはならないようです。しかも、64バイトを超えるとハッシュ化されてしまうようです。

An SHA-256 key is used for HMAC operations. The minimum length for an SHA-256 HMAC key is 32 bytes. A key longer than 32 bytes does not significantly increase the function strength unless the randomness of the key is considered weak. A key longer than 64 bytes will be hashed before it is used.

Generate Keystore File Entry (GENCKMKSFE) - IBM Documentation

https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/cl/genckmksfe.htm

色々調べたところ、HMAC-SHA256 の秘密鍵は32バイトのバイト形式 であると言えそうです。

OpenSSL で32バイトのバイト形式の秘密鍵を生成するには以下のようにします。

$ openssl rand 32
?R-??'???ѥ `a???B????  ??????

ただ、上記だとバイナリになって内容を確認できないので、以下のように HEX で出力します。

$ openssl rand -hex 32
ad4c96714d2a6289ed1731742ecfb1959430469ab30d7b2c4c212124153c23bf

この秘密鍵を使って OpenSSL で署名をするには以下のようにします。

$ echo -n "value" | openssl dgst -sha256 -mac hmac -macopt hexkey:ad4c96714d2a6289ed1731742ecfb1959430469ab30d7b2c4c212124153c23bf
0c824a49fbc5e5ffd51770e2b9b4bcad5855c4eb363c1d90c476d3c86b983e2c

これが正しい HMAC-SHA256 の秘密鍵の生成と署名方法だと思うのですが、Google Apps Script では秘密鍵をバイト形式で署名する方法がないのですよね。正確にはない訳ではないのですが、署名対象もバイト形式に変換しなくてはならないのでちょっと厳しい。

仕方ないので、他のサイトを色々調べた結果、32バイト以上の文字列でもよいと判断できたので、32バイトの文字列で秘密鍵を生成します。

$ openssl rand -hex 16
5711dd4d96d88f5a130758950206a8e1

署名方法は以下のようになります。

$ echo -n "value" | openssl dgst -sha256 -hmac "5711dd4d96d88f5a130758950206a8e1"
aa90ccc09462fa1f2cda6f109b9293f417a9d3bddb1c7dcae798b3ad308de590

署名が正しいかは以下のサイトで確認できます。

しかし、HMAC-SHA256 の秘密鍵の作成方法の情報が少なすぎでしょう。

他にも以下のサイトを参考にさせていただきました。