TLS証明書や電子署名に使うRSA、ECDSA、Ed25519の秘密鍵を作りたいときは、openssl genpkeyを使う。
$ openssl genpkey -algorithm ED25519 -out ed25519.pem
-algorithmで鍵の種類を、-outで出力先を指定する。-outを省略すると、標準出力にPEM形式で出力する。
実行例はUbuntu 24.04のOpenSSL 3.0.13のもの。
RSAの秘密鍵を作る
$ openssl genpkey -algorithm RSA -out rsa.pem
鍵長を指定しない場合は2048ビットになる。-pkeyopt rsa_keygen_bits:[ビット数]で変更できる。
$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out rsa4096.pem
作成した鍵の鍵長は、openssl pkeyで確認できる。
$ openssl pkey -in rsa4096.pem -noout -text | head -1
Private-Key: (4096 bit, 2 primes)
公開指数は65537がデフォルトである。-pkeyopt rsa_keygen_pubexp:[値]で指定できるが、変更する理由は通常ない。
ECDSAの秘密鍵を作る
ECの鍵は、曲線名の指定が必須である。-pkeyopt ec_paramgen_curve:[曲線名]を付ける。
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec.pem
曲線名を省略するとエラーになる。
$ openssl genpkey -algorithm EC -out ec.pem
genpkey: Error generating EC key
失敗しても、0バイトの出力ファイルは残る。削除してからやり直す。
よく使う曲線はP-256(prime256v1)とP-384(secp384r1)である。どちらの名前も指定できる。使える曲線の一覧はopenssl ecparam -list_curvesで確認できる。
$ openssl pkey -in ec.pem -noout -text | grep -E 'ASN1 OID|NIST'
ASN1 OID: prime256v1
NIST CURVE: P-256
存在しない曲線名を指定するとエラーになる。
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:foo
genpkey: Error generating EC key
...error:0800008D:elliptic curve routines:group_new_from_name:invalid curve...
Ed25519の秘密鍵を作る
Ed25519は鍵長や曲線のパラメーターがなく、-algorithmだけで作れる。
$ openssl genpkey -algorithm ED25519 -out ed25519.pem
$ openssl pkey -in ed25519.pem -noout -text | head -1
ED25519 Private-Key:
-algorithmは大文字・小文字を区別しないため、ed25519でも同じ鍵を作れる。
ほかにED448、鍵交換用のX25519、RSA-PSSなども指定できる。
パスフレーズで保護する
-aes-256-cbcなどの暗号名を付けると、秘密鍵をパスフレーズで暗号化して保存する。
$ openssl genpkey -algorithm RSA -aes-256-cbc -out rsa-enc.pem
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
$ head -1 rsa-enc.pem
-----BEGIN ENCRYPTED PRIVATE KEY-----
非対話で指定する場合は-passを使う。pass:はpsの出力に残るため、env:やfile:が安全である。-passの指定方法はopenssl encと共通である。
参考: 【openssl】ファイルをパスワードで暗号化・復号する (enc)
進捗表示を消す
RSAの鍵を作るとき、画面に.や+の進捗表示が出る。この表示は標準エラー出力に出る。スクリプトなどで邪魔な場合は、2>/dev/nullで消す。
$ openssl genpkey -algorithm RSA -out rsa.pem 2>/dev/null
エラーも消えるため、-outで保存した鍵の内容や終了コードで成否を確認する。
出力ファイルのパーミッション
-outで作った秘密鍵のファイルは、パーミッションが600(所有者のみ読み書き)になる。
$ ls -l rsa.pem
-rw------- 1 root root 1704 Sep 30 14:44 rsa.pem
標準出力をリダイレクトして保存した場合は、umaskに従う。umask 077を設定しておくか、-outを使う。
DER形式で出力する
-outform DERを付けると、PEMではなくバイナリのDER形式で出力する。
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -outform DER -out ec.der
$ od -An -tx1 ec.der | head -1
30 77 02 01 01 04 20 e7 be 27 23 6b 1b 58 88 cb
genrsaやecparamとの違い
古い記事では、openssl genrsaやopenssl ecparam -genkeyで鍵を作る例がよく見られる。
$ openssl genrsa -out g.pem 2048
$ openssl ecparam -name prime256v1 -genkey -noout -out ep.pem
genrsaとecparamは鍵の種類ごとの専用コマンドで、genpkeyは1つのコマンドでRSA、EC、Ed25519などを扱える。OpenSSL 3.0では、genrsaはgenpkeyと同じPKCS#8形式(BEGIN PRIVATE KEY)で出力する。genrsa -traditionalやecparam -genkeyは、従来形式(BEGIN RSA PRIVATE KEYやBEGIN EC PRIVATE KEY)で出力する。
$ openssl genrsa -out g.pem 2048
$ head -1 g.pem
-----BEGIN PRIVATE KEY-----
$ openssl genrsa -traditional -out gt.pem 2048
$ head -1 gt.pem
-----BEGIN RSA PRIVATE KEY-----
$ openssl ecparam -name prime256v1 -genkey -noout -out ep.pem
$ head -1 ep.pem
-----BEGIN EC PRIVATE KEY-----
新規に鍵を作る場合は、形式が統一されるgenpkeyを使う。
バージョンによる違い
OpenSSL 3.5や3.6でも、ここまでの例は同じように動く。
macOS標準の/usr/bin/openssl(LibreSSL 3.3.6)は、genpkeyがED25519に対応していない。
$ /usr/bin/openssl genpkey -algorithm ED25519 -out ed25519.pem
Algorithm ED25519 not found
また、LibreSSL 3.3.6のgenrsaは、従来形式(BEGIN RSA PRIVATE KEY)で出力する。Ed25519が必要な場合は、Homebrewなどでインストールしたopensslを使う。
