HEARTBEATS

こんにちは、技術開発室の滝澤です。

前回(2021年7月)、『TLS証明書チェッカーcheck-tls-certの公開』というエントリーを公開しました。このcheck-tls-certを開発するにあたって、テスト用のPKI(Public Key Infrastructure、公開鍵基盤)を構築しました。

opensslコマンドを利用したPKI用のスクリプトを整備したのですが、開発当時ではOpenSSL 3.0の開発が進んでいることもあり、OpenSSL 3.0でも利用できるようにとドキュメントを読んでみると、「deprecated」(非推奨)の文字が散見されました。そのため、それを踏まえたスクリプトを書きました。この際に得られた知見を本記事で紹介します。

なお、2021年9月7日にOpenSSL 3.0.0がリリースされました。

本記事を1行でまとめると次のようになります。

  • OpenSSL 3.0のgenpkey, pkeyコマンドを利用したプライベート鍵の生成方法の紹介

注記: opensslコマンドに対するサブコマンドのことをこの記事では単にコマンドと記述しています。

プライベート鍵の生成

RSAのプライベート鍵(公開鍵ペア)を生成するときには、従来はopensslのgenrsaコマンドを利用していました。しかし、このコマンドのOpenSSL 3.0.0のマニュアルには次のように記述されています。

This command has been deprecated. The openssl-genpkey(1) command should be used instead.

そのため、プライベート鍵の生成にはgenpkeyコマンドを利用することになります。 このコマンドではRSAだけでなくECDSAやEdDSAのプライベート鍵を生成できます。

次のようにしてプライベート鍵を生成できます。

openssl genpkey -out filename [-cipher] -algorithm alg [-pkeyopt opt:value]

-algorithmにデジタル署名アルゴリズムを、-pkeyoptにそのアルゴリズムのパラメータを指定します。

実際には他にもオプションがありますので興味のある方はマニュアルをご覧ください。

実行例

デジタル署名アルゴリズム毎の実行例を紹介します。

RSA

openssl genpkey -out server.key -algorithm RSA -pkeyopt rsa_keygen_bits:4096

-algorithmRSAを指定します。-pkeyoptにはrsa_keygen_bitsの値として鍵長を指定します。

ECDSA

openssl genpkey -out server.key -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1

-algorithmECを指定します。-pkeyoptにはec_paramgen_curveの値として曲線名を指定します。

曲線の名前はopenssl ecparam -list_curvesで出力される物から選べますが、prime256v1(P-256)かsecp384r1(P-384)を利用するとよいでしょう。

Ed25519

openssl genpkey -out server.key -algorithm ED25519

-algorithmED25519を指定します。

レガシーな形式

OpenSSL 3.0では生成される鍵ファイルは次のようなPKCS #8の形式になります。

-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDToBBMpZCUPd0y
...
-----END PRIVATE KEY-----

レガシーな形式に変換したいときにはpkeyコマンドを用いて次のように実行します。

openssl pkey -in server.key -out server-traditional.key -traditional

鍵ファイルは次のような見慣れた形式になります。

RSA

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA06AQTKWQlD3dMiGC0t9rB6FetoUZ2wow41mmWQFgCqMPn5bZ
...
-----END RSA PRIVATE KEY-----

ECDSA

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIGxOe5ZjOEMifS4Fz4cyo2x6KThx/n9gkdYxQtqRU1DDoAoGCCqGSM49
...
-----END EC PRIVATE KEY-----

プライベート鍵の暗号化

生成される鍵を暗号化する場合は対称鍵暗号のアルゴリズムを指定するだけです。

openssl genpkey -out server.key -aes128 -algorithm RSA -pkeyopt rsa_keygen_bits:4096

ここでは、対称鍵暗号として-aes128を指定しました。

次のように暗号化されたファイルが生成されます。

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQImBNO1LBSREkCAggA
...
-----END ENCRYPTED PRIVATE KEY-----

公開鍵の確認

TLS証明書ファイルとプライベート鍵ファイルの整合性の確認のために、公開鍵が一致するかを確認することがあります。 特にRSAの場合はmodulusの値を確認してきました。

pkeyコマンドを使って、公開鍵の情報を次のようにして出力できます。

openssl pkey -in server.key -noout -text_pub

RSAの場合は次のような形式で公開鍵の情報が出力されます。

Public-Key: (4096 bit)
Modulus:
    00:df:33:76:05:fd:b8:39:b6:b0:c0:b4:25:f5:ec:
    ...
Exponent: 65537 (0x10001)

これをTLS証明書の公開鍵情報と付き合わせてみることにより整合性を確認できます。

参考までに従来のrsaコマンドでは次のようにしてmodulusの値を出力できます。

openssl rsa -in server.key -noout -modulus

この結果、次のような形式で出力されます。

Modulus=DF337605FDB839B6B0C0B425F5EC...

pkeyコマンドの出力とrsaコマンドの出力を比べてみるとpkeyコマンドの先頭には00が差し込まれています。 これは、OpenSSLの関数print_labeled_bignum()において、次のようなコメントが書いており、先頭のビットがセットされていたら、00を先頭に挿入するという仕様のためです。

    /* Add a leading 00 if the top bit is set */

なお、弊社で開発したTLS証明書チェッカーcheck-tls-certではこの整合性の確認作業もコマンド1回で行えます。詳しくは次の記事をご覧ください。

最後に

既存のコマンドがすぐに使えなくなるわけではないですが、プライベート鍵の操作は将来的にはgenpkey, pkeyコマンドを使うことになります。 ちなみに、genpkeyやpkeyコマンド自体は以前のバージョンからもありますので、すでに利用可能です。

株式会社ハートビーツの技術情報やイベント情報などをお届けする公式ブログです。