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を使う。

参考

openssl-genpkey - OpenSSL Documentation