参考
- とてもわかり易いサイト
- OpenSSL Cookbook (必読)
用語
- DER format とは? ASN.1 バイナリ形式
- PEM format とは? ASN.1 の Base64 --BEGIN から始まる。
この練習で使うファイル
- private-key.pem: 秘密鍵
- public-key.pem: 公開鍵
- request.csr: 証明書署名要求
- public-key.crt: 証明書 (最初オレオレ証明書を作って後で他の証明書でサインする)
- root-ca/root-ca.crt: ルート証明書
- private/root-ca.key: ルート証明書用の秘密鍵
- short.txt: 短いテキスト
- short.rsaenc: rsautl で暗号化したもの
- short.rsasig: rsautl で作った署名
- long.txt: 長いテキスト
- long.dgst: dgst で作った署名
- long.der: smime pkcs7 で作った署名
オレオレ証明書を作る
RSA 秘密鍵の生成 (genrsa は古い): -> private-key.pem
(-aes-128-cbc
をつけるとパスフレーズを設定できる。)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-128-cbc > private-key.pem
RSA 秘密鍵の中身を見る
openssl pkey -text -noout < private-key.pem
RSA公開鍵の生成: private-key.pem -> public-key.pem
openssl pkey -pubout < private-key.pem > public-key.pem
RSA 公開鍵の中身を見る
openssl pkey -text -noout -pubin < public-key.pem
証明書署名要求(CSR) の作成: private-key.pem -> request.csr
openssl req -new -key private-key.pem > request.csr
証明書署名要求(CSR) の中身を見る
openssl req -text -noout < request.csr
オレオレ証明書(署名付き公開鍵)の作成: request.csr, private-key.pem -> public-key.crt
openssl x509 -req -days 36500 -signkey private-key.pem < request.csr > public-key.crt
証明書の中を中身を見る -noout 無しだと PEM 形式証明書が末尾に付く。
openssl x509 -text -noout < public-key.crt
証明書から公開鍵を取り出す: public-key.crt -> public-key.pem と同じ物が出る。(ここまでOK)
openssl x509 -pubkey -noout < public-key.crt
dgst を使ったハッシュ値の取得と署名
openssl dgst ではハッシュ値の取得と署名検証を行えます。デフォルトで SHA256 が選ばれます。
単純にハッシュ値を得る。
openssl dgst long.txt
SHA256(long.txt)= 497ea784506cfa79fa4a4eff25bc7fb4fd907040f23e7e095f71f405633e80c3
秘密鍵で long.txt を署名する: private-key.pem, long.txt -> long.dgst
openssl dgst -sign private-key.pem long.txt > long.dgst
long.txt と署名を公開鍵で検証する: public-key.pem, long.dgst, long.txt -> 成功失敗
openssl dgst -verify public-key.pem -signature long.dgst long.txt
rsautl を使った署名、検証、暗号、復号
openssl rsautl では RSA を使った署名、検証、暗号、復号が行えます。ただあまり長いデータは使えません。RSA の勉強にはなりますが実用途は無いと思います。
公開鍵で short.txt を暗号化する: public-key.pem, short.txt -> short.encrypted
openssl rsautl -encrypt -pubin -inkey public-key.pem < short.txt > short.rsaenc
秘密鍵で復号する: private-key.pem, short.rsaenc -> short.txt と同じ物が出る。
openssl rsautl -decrypt -inkey private-key.pem < short.rsaenc
秘密鍵で short.txt を署名する: private-key.pem, long.txt -> long.dgst
openssl rsautl -sign -inkey private-key.pem < short.txt > short.rsasig
公開鍵で署名を検証する:public-key.pem, short.rsasig -> short.txt と同じ物が出る。
openssl rsautl -verify -pubin -inkey public-key.pem < short.rsasig
Root CA (ルート認証局) を作る
ディレクトリ構成を作る。
mkdir root-ca
cd root-ca
mkdir certs db private
chmod 700 private
touch db/index
openssl rand -hex 16 > db/serial
echo 1001 > db/crlnumber
https://www.feistyduck.com/library/openssl-cookbook/online/openssl-command-line/private-ca-creating-root.html を参考に設定ファイル root-ca/ に root-ca.conf を作る。
証明書署名要求(CSR) の作成: -> root-ca.csr, private/root-ca.key
openssl req -new -config root-ca.conf -out root-ca.csr -keyout private/root-ca.key
オレオレ証明書の作成: root-ca.csr -> root-ca.crt
root-ca.conf 内の ca_ext セクション critical,CA:true
で、この証明書が CA である事を示す。
openssl ca -selfsign -config root-ca.conf -in root-ca.csr -out root-ca.crt -extensions ca_ext
CRL (失効リスト) の作成
openssl ca -gencrl -config root-ca.conf -out root-ca.crl
Root CA (ルート認証局) で 証明書署名要求(CSR) を署名する
いよいよここで証明書を作るが、ちょっと趣向を凝らして S/MIME の署名と暗号ができる証明書を作ってみる。
x509(1) の S/MIME Signing, Encryption の項目によると S/MIME を有効にするには次のような妙な条件を満たす必要がある。
- S/MIME Signing には Common S/MIME client tests が有効で keyUsage の digitalSignature が有効である必要がある。
- S/MIME Encryption には Common S/MIME client tests が有効で keyUsage の keyEncipherment が有効である必要がある。
- Common S/MIME client test には extendedKeyUsage の emailProtection が有効である必要がある。
これに対応する設定ファイル root-ca.conf
の項目 [sub_ca_ext]
は次のようになる。
[sub_ca_ext]
...
extendedKeyUsage = clientAuth,serverAuth,emailProtection
keyUsage = critical,keyCertSign,cRLSign,digitalSignature,keyEncipherment
ついでに、サンプルのままだとルート証明書と同じ国名の証明書しか署名できないので、制限を緩めるために [policy_c_o_match]
の項目を編集する。
countryName = supplied
設定ファイルの [sub_ca_ext]
の利用用途に emailProtection
を追加する。これで S/MIME 用の証明書を作れる。詳しくは x509v3_config(5)。
extendedKeyUsage = clientAuth,serverAuth,emailProtection
ついに証明書の発行。例えば最初に作った request.csr
を署名してみる。設定ファイルは -config root-ca.conf
として、extension (利用用途)の設定は -extensions [sub_ca_ext]
として指定する。
openssl ca -config root-ca.conf -in ../request.csr -out ../public-key.crt -extensions sub_ca_ext
- OCSP とは? 証明書の失効情報を伝えるプロトコルらしい: https://www.openssl.org/docs/man1.1.1/man1/ocsp.html
- 参考: config ファイルの説明がわかりやすい: https://qiita.com/3244/items/780469306a3c3051c9fe
openssl x509 -text
の -purpose
オプションで S/MIME signing : Yes
S/MIME encryption : Yes
の行が出たら完成!
openssl x509 -text -noout -purpose < ../public-key.crt
...
S/MIME signing : Yes
S/MIME encryption : Yes
smime
秘密鍵で long.txt を smime 署名: private-key.pem, long.txt -> long.smime
cd ..
openssl smime -sign -text -inkey private-key.pem -signer public-key.crt < long.txt > long.smime
long.txt と long.smime を公開鍵で検証する: public-key.pem, long.smime -> 成功失敗
もしも S/MIME に purpose が設定されていない証明書なら -purpose any
が必要になる。
openssl smime -verify -CAfile root-ca/root-ca.crt < long.smime > /dev/null
秘密鍵で long.txt を smime 署名 (PKCS7 DER): private-key.pem, long.txt -> long.der (-binary がトリッキー!!)
openssl smime -sign -outform der -binary -inkey private-key.pem -signer public-key.crt < long.txt > long.der
long.der の中を見る
openssl pkcs7 -in long.der -inform DER -print
long.txt と long.der を公開鍵で検証する: public-key.pem, long.der -> 成功失敗
openssl smime -verify -inform der -CAfile root-ca/root-ca.crt -content long.txt < long.der > /dev/null
smime (gnutls certtool 利用)
秘密鍵で long.txt を smime 署名 (PKCS7 DER): private-key.pem, long.txt -> long.der
certtool --p7-detached-sign --infile=long.txt --load-certificate=public-key.crt --load-privkey=private-key.pem --outder > long.der
long.txt と long.der を公開鍵で検証する: public-key.pem, long.der -> 成功失敗
certtool --p7-verify --infile=long.der --inder --load-ca-certificate=root-ca/root-ca.crt --load-data=long.txt