証明書をPEM形式からDER形式に、DER形式からPEM形式に変換したいときは、openssl x509 -outformを使う。
$ openssl x509 -in cert.pem -outform DER -out cert.der
DER形式をPEM形式に戻すには、-inform DERで入力の形式を指定する。
$ openssl x509 -inform DER -in cert.der -out cert.pem
-outformを省略すると、出力はPEM形式になる。
実行例はUbuntu 24.04のOpenSSL 3.0.13のもの。
PEMとDERの違い
証明書のファイル形式は、主に2つある。
| 形式 | 中身 | 見分け方 | 主な拡張子 |
|---|---|---|---|
| PEM | DERをBase64にしたテキスト | -----BEGIN CERTIFICATE-----で始まる | .pem、.crt、.cer |
| DER | バイナリ | テキストエディターで開くと文字化けする | .der、.cer、.crt |
.cerや.crtはどちらの形式でも使われるため、拡張子では判別できない。先頭を確認する。
$ head -c 27 cert.pem
-----BEGIN CERTIFICATE-----
$ od -An -tx1 cert.der | head -1
30 82 01 9c 30 82 01 42 a0 03 02 01 02 02 14 3e
DER形式は、30 82(ASN.1のSEQUENCE)で始まる。
PEM形式からDER形式に変換しても、データの内容は変わらない。DERをPEMに戻すと、元のPEMと完全に一致する。
$ openssl x509 -inform DER -in cert.der -out cert2.pem
$ cmp cert.pem cert2.pem && echo same
same
DER形式の証明書を読み込む
DER形式の証明書をopenssl x509で表示する場合は、-inform DERを付ける。
$ openssl x509 -inform DER -in cert.der -noout -subject
subject=CN = example.test
OpenSSL 3.0以降は、-informを省略してもDER形式を自動判別して読み込める。macOS標準の/usr/bin/openssl(LibreSSL 3.3.6)は自動判別できず、-inform DERを付けないとエラーになる。
$ /usr/bin/openssl x509 -in cert.der -noout -subject
unable to load certificate
...Expecting: TRUSTED CERTIFICATE
どのバージョンでも動くように、DER形式では-inform DERを付けておく。
PKCS#7形式に変換する
複数の証明書を1つのファイルにまとめる形式として、PKCS#7(.p7b、.p7c)がある。openssl crl2pkcs7で作る。
$ openssl crl2pkcs7 -nocrl -certfile cert.pem -out cert.p7b
$ head -1 cert.p7b
-----BEGIN PKCS7-----
PKCS#7形式から証明書を取り出すには、openssl pkcs7 -print_certsを使う。
$ openssl pkcs7 -in cert.p7b -print_certs -out certs.pem
出力ファイルには、各証明書のPEMの前にsubject=とissuer=の行が付く。openssl x509はPEM以外の行を読み飛ばすため、そのまま読み込める。
秘密鍵も含めてまとめる形式には、PKCS#12(.p12、.pfx)もある。
フィンガープリントを表示する
-fingerprintは、証明書のDER形式に対するハッシュ値を表示する。証明書が同じものかを確認するときや、サイトが公開しているフィンガープリントと照合するときに使う。
$ openssl x509 -in cert.pem -noout -fingerprint -sha256
sha256 Fingerprint=E1:60:C4:AD:CE:D4:EE:F3:5B:31:79:CA:20:12:D7:72:0B:1F:EE:71:66:C1:B5:D1:00:03:03:10:06:E0:15:6A
ハッシュアルゴリズムを省略すると、OpenSSL 3.xではSHA-1になる。LibreSSL 3.3.6ではSHA-256になる。バージョンによって結果が変わらないように、-sha256を明示する。
$ openssl x509 -in cert.pem -noout -fingerprint
sha1 Fingerprint=15:40:4D:4A:6C:BA:C8:17:31:C4:BA:60:6D:64:71:EB:EA:6F:34:E4
フィンガープリントは、DER形式のデータに対する単純なハッシュ値である。openssl dgstで同じ値を再現できる。
$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256
SHA2-256(stdin)= e160c4adced4eef35b3179ca2012d7720b1fee7166c1b5d10003031006e0156a
PEM形式のファイルをそのままハッシュしても、同じ値にならない。Base64とヘッダー行を含むためである。
参考: 【openssl】ファイルのハッシュ値を計算する (dgst)
証明書から公開鍵を取り出す
-pubkeyで、証明書に含まれる公開鍵をPEM形式で取り出す。
$ openssl x509 -in cert.pem -noout -pubkey
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
取り出した公開鍵は、openssl pkey -pubinで内容を確認できる。
参考: 【openssl】秘密鍵から公開鍵を取り出す (pkey)
サブジェクトのハッシュ値を表示する
-hashは、サブジェクトのハッシュ値を8桁の16進数で表示する。/etc/ssl/certs/のように、証明書を[ハッシュ値].0というファイル名で並べたディレクトリ(-CApathで指定するディレクトリ)を作るときに使う。
$ openssl x509 -in cert.pem -noout -hash
8593a23d
$ mkdir certs
$ cp cert.pem certs/$(openssl x509 -in cert.pem -noout -hash).0
$ openssl verify -CApath certs cert.pem
cert.pem: OK
OpenSSL 1.0.0以降と、それ以前(0.9.8)では、ハッシュの計算方法が異なる。古い形式が必要な場合は、-subject_hash_oldを使う。
$ openssl x509 -in cert.pem -noout -subject_hash_old
90179be9
その他の項目を表示する
openssl x509は、-nooutと表示オプションの組み合わせで、必要な項目だけを取り出せる。
| オプション | 表示内容 |
|---|---|
-subject | サブジェクト |
-issuer | 発行者 |
-serial | シリアル番号 |
-dates | 有効期間の開始日時と終了日時 |
-ext subjectAltName | SANなどの拡張 |
-purpose | 証明書の用途 |
$ openssl x509 -in cert.pem -noout -serial
serial=3EAC40FC1180B5DC74E6CB1603644E35DD3E48DC
有効期限や拡張の確認は、別の記事で説明している。
参考: 【openssl】証明書ファイルの有効期限を確認する
表示形式の違い
-subjectの表示は、バージョンで異なる。
| 実行環境 | 出力例 |
|---|---|
| OpenSSL 3.0 | subject=CN = example.test |
| OpenSSL 3.5、3.6 | subject=CN=example.test |
| LibreSSL 3.3.6 | subject= /CN=example.test |
出力をスクリプトで処理する場合は、この違いに注意する。
複数の証明書を含むファイルを扱う
PEM形式のファイルに複数の証明書を連結している場合、openssl x509は先頭の1枚だけを処理する。
$ cat cert.pem cert.pem > two.pem
$ openssl x509 -in two.pem -noout -subject
subject=CN = example.test
すべての証明書を表示するには、openssl pkcs7 -print_certsを使う。
$ openssl crl2pkcs7 -nocrl -certfile two.pem | openssl pkcs7 -print_certs -noout
subject=CN = example.test
issuer=CN = example.test
subject=CN = example.test
issuer=CN = example.test
