「OpenSSL」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) 細 (関連記事を追加) |
Kusanaginoturugi (トーク | 投稿記録) (→復号時に "bad decrypt" と表示される: add === Python 3.10 and "ca md too weak" errors ===) |
||
304行目: | 304行目: | ||
$ openssl enc -d -md md5 -in encrypted -out decrypted |
$ openssl enc -d -md md5 -in encrypted -out decrypted |
||
+ | |||
+ | === Python 3.10 and "ca md too weak" errors === |
||
+ | |||
+ | In Python 3.10 by default there is a hardcoded list of allowed OpenSSL ciphers. Some of the less secure, like MD5, have been disabled at the {{ic|ssl}} module level, ignoring the system-wide configuration of OpenSSL. It results sometimes in strange errors on older certificates, sometimes even when establishing {{ic|https}} connections, like: |
||
+ | |||
+ | requests.exceptions.SSLError: HTTPSConnectionPool(host='a.kind.of.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(398, '[SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3862)'))) |
||
+ | |||
+ | To make Python follow the system configuration, you may have to rebuild it, adding {{ic|1=--with-ssl-default-suites=openssl}} parameter to {{ic|./configure}}. The issue has been also reported as {{Bug|73549}}. |
||
==参照== |
==参照== |
2022年5月6日 (金) 14:14時点における版
OpenSSL は SSL と TLS プロトコルのオープンソース実装で、OpenSSL (Apache License 1.0) と SSLeay (4-clause BSD) ライセンスのデュアルライセンスで配布されています。BSD, Linux, OpenVMS, Solaris, Windows などの様々なプラットフォームをサポートしています。
SSL のイントロダクション
SSL に関する根本的な説明を飛ばして、SSL/TLS のセットアップだけを取り扱うために、この記事では基本的にファイルごとに SSL を説明します。
詳しい情報は Wikipedia:ja:認証局 や Wikipedia:ja:公開鍵基盤 を参照してください。
認証局 (CA)
認証局はエンドユーザーからの要求に対して証明書を返します。そのために、返されるエンドユーザーの証明書は CA 秘密鍵と CA 証明書で署名されており、従って CA 公開鍵も含みます。CA は証明書失効リスト (CRL) も配布し、エンドユーザーにもはや有効ではない証明書を通知し、次の CRL の期限を伝えます。
CA 秘密鍵
CA 秘密鍵は3つの中で一番重要です。秘密鍵が漏洩してしまうと中央局が許諾を確認したり取り消すという目的が瓦解すると同時に、CA 証明書を証明するのに使われる CA 公開鍵に対する署名済みの鍵ともなります。CA 秘密鍵の署名は CA 証明書自体に埋め込まれているため、漏洩した CA 秘密鍵を使うことで攻撃者は CA 証明書を複製することができてしまいます。
CA 証明書と公開鍵
単一のファイルとして全てのエンドユーザーに配布されます。CA 証明書と公開鍵を使うことで、メールサーバーやウェブサイトなど対応する CA によって署名されたとされる他のエンドユーザーの証明書を証明します。
エンドユーザー
エンドユーザーは識別名 (DN) を含む証明書の要求をCA に送信します。通常、CA は同一の DN を持つ有効な証明書の発行を許可しません。前の証明書を無効化します。エンドユーザーの証明書は期限日に更新されなかったなどの理由で無効になることがあります。
エンドユーザー生成鍵
CA に送信する証明書の要求に署名するためにエンドユーザーは鍵を生成します。CA 秘密鍵と同じように、ユーザーの鍵が漏洩してしまうと攻撃者はユーザーに扮して、ユーザーの名前を使って要求を送信することが可能です。そうなると CA は前の正しいユーザー証明書を無効化してしまいます。
証明書の要求
ユーザーの DN と公開鍵を含みます。その名のとおり、CA から証明書を取得する最初のプロセスを表します。
エンドユーザー証明書
エンドユーザー証明書と CA 証明書の一番の違いはエンドユーザー証明書は証明書に署名することはできないということです。情報と引き換えに証明する方法を与えるだけです。
証明書失効リスト (CRL)
CRL も CA 鍵によって署名されていますが、エンドユーザー証明書に関する情報だけを規定します。通常、新しい CRL が下されるまで30日間のスパンがあります。
設定
OpenSSL の設定ファイルは /etc/ssl/openssl.cnf
に置かれることになっており、一見すると複雑なように見えます。設定を分割する include ディレクティブは存在しません。しかしながら、このセクションでは重要な設定をカバーしています。
シェルスクリプトと同じように、代入で変数を拡張することができます。設定ファイルの形式に関する詳しい説明は config(5ssl) を見て下さい。オペレーティングシステムによっては、man ページの名前が openssl-config(5) や config(5) になっていることがあります。場合によって、man では読むことができず次の場所にマニュアルが配置されることもあります: /usr/share/openssl
。
グローバル変数
以下の設定は全てのセクションに適用されます。そのため、セクションヘッダの下に定義することはできません:
DIR= . # Useful macro for populating real vars. RANDFILE= ${DIR}/private/.rnd # Entropy source. default_md= sha1 # Default message digest.
ca セクション
以下の設定は CRL に署名したり、証明書に署名、あるいは無効化するときに使われます。リクエストを生成したいだけのユーザーは #req セクションにスキップできます。
[ ca ] default_ca= dft_ca # Configuration files may have more than one CA # section for different scenarios. [ dft_ca ] certificate= ${DIR}/cacert.pem # The CA certificate. database= ${DIR}/index.txt # Keeps tracks of valid/revoked certs. new_certs_dir= ${DIR}/newcerts # Copies of signed certificates, for # administrative purposes. private_key= ${DIR}/private/cakey.pem # The CA key. serial= ${DIR}/serial # Should be populated with the next # cert hex serial. # These govern the way certificates are displayed while confirming # the signing process. name_opt= ca_default cert_opt= ca_default default_days= 365 # How long to sign certificates for. default_crl_days=30 # The same, but for CRL. policy= dft_policy # The default policy should be lenient. x509_extensions=cert_v3 # For v3 certificates. [ dft_policy ] # A value of 'supplied' means the field must be present in the certificate, # whereas 'match' means the field must be populated with the same contents as # the CA certificate. 'optional' dictates that the field is entirely optional. C= supplied # Country ST= supplied # State or province L= optional # Locality O= supplied # Organization OU= optional # Organizational unit CN= supplied # Common name [ cert_v3 ] # With the exception of 'CA:FALSE', there are PKIX recommendations for end-user # certificates that should not be able to sign other certificates. # 'CA:FALSE' is explicitely set because some software will malfunction without. subjectKeyIdentifier= hash basicConstraints= CA:FALSE keyUsage= nonRepudiation, digitalSignature, keyEncipherment nsCertType= client, email nsComment= "OpenSSL Generated Certificate" authorityKeyIdentifier=keyid:always,issuer:always
req セクション
鍵やリクエスト、自己署名証明書の生成に関連する設定です。
req セクションは DN プロンプトを担当します。一般的な誤解は Common Name (CN) プロンプトです。これは、値としてユーザーの適切な名前を使用する必要があることを示唆しています。エンドユーザー証明書にはCNとして マシンのホスト名 が必要ですが、 CA には有効な TLD が ない 必要があるため、認定されたエンドユーザーの可能な組み合わせの間で CN と CA 証明書には、エンドユーザー証明書が自己署名されていることを意味するものとして一部のソフトウェアによって誤解される可能性があります。 Equifax のように、一部の CA 証明書には CN はありません。
$ openssl x509 -subject -noout < /etc/ssl/certs/Equifax_Secure_CA.pem
subject= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
ファイルを分割することは通常の機能に厳密に必要ではありませんが、同じ構成ファイルからの要求生成とCA管理を処理することは非常に混乱するため、設定を2つに明確に分離する規則に従うことをお勧めします cnf
ファイルと2つの含まれるディレクトリに。
両方のタスクに共通の設定は次のとおりです。
[ req ] # Default bit encryption and out file for generated keys. default_bits= 2048 default_keyfile=private/cakey.pem string_mask= utf8only # Only allow utf8 strings in request/ca fields. prompt= no # Do not prompt for field value confirmation.
CA req 設定
以下の設定で、他の証明書を署名することができる標準的な CA が作成されます:
distinguished_name=ca_dn # Distinguished name contents. x509_extensions=ca_v3 # For generating ca certificates. [ ca_dn ] # CN isn't needed for CA certificates C= US ST= New Jersey O= localdomain [ ca_v3 ] subjectKeyIdentifier= hash # PKIX says this should also contain the 'crucial' value, yet some programs # have trouble handling it. basicConstraints= CA:TRUE keyUsage= cRLSign, keyCertSign nsCertType= sslCA nsComment= "OpenSSL Generated CA Certificate" authorityKeyIdentifier=keyid:always,issuer:always
エンドユーザー req 設定
ほとんどの状況で使える v3 リクエストの作成:
distinguished_name=ca_dn # Distinguished name contents. req_extensions=req_v3 # For generating ca certificates. [ ca_dn ] C= US ST= New Jersey O= localdomain CN= localhost [ req_v3 ] basicConstraints= CA:FALSE keyUsage= nonRepudiation, digitalSignature, keyEncipherment
GOST エンジンのサポート
まず、システム上に libgost.so
が存在することを確かめます:
$ pacman -Ql openssl | grep libgost
何も問題がなければ、以下の行を設定に追加:
openssl_conf = openssl_def # this must be a top-level declaration
ドキュメントの末尾に以下の行を記述:
[ openssl_def ] engines = engine_section [ engine_section ] gost = gost_section [ gost_section ] engine_id = gost soft_load = 1 dynamic_path = /usr/lib/engines/libgost.so default_algorithms = ALL CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
公式の README.gost にいくつか例が記載されています。
鍵の生成
鍵を生成する前に、保存するディレクトリを作成してください:
$ mkdir -m0700 private
次に、あらかじめ鍵のパーミッションを設定しておきます:
$ touch private/key.pem $ chmod 0600 private/key.pem
もしくは umask を設定して新しく作成するファイルとディレクトリのパーティションを制限します:
$ umask 077
genpkey
で鍵を生成する例:
$ openssl genpkey -algorithm RSA -out private/key.pem -pkeyopt rsa_keygen_bits:4096
鍵を暗号化したい場合、以下のコマンドを使って下さい。パスワードが要求されます:
$ openssl genpkey -aes-256-cbc -algorithm RSA -out private/key.pem -pkeyopt rsa_keygen_bits:4096
要求の作成
CAcert.org などの公共の認証局や、ローカルで管理している認証局から証明書を取得するには、要求ファイルを CA に送信する必要があります。csr
ファイルと呼ばれます。
新しい要求を作成して先に生成した鍵を使って署名してください:
$ openssl req -new -sha256 -key private/key.pem -out req.csr
証明書の署名
ローカルで CA の署名を行う方法を説明します: 直接、自己署名証明書を作成するか、ローカルの CA を利用します。
自己署名証明書
自己署名証明書では動作しないプログラムは多数存在し、複数のシステムを自己署名証明書で管理する場合、認証局をセットアップする方がずっとトラブルが少なくなります。
先に説明したとおりに鍵を生成した場合、次のコマンドを使って新しい証明書に署名します:
$ openssl req -key private/key.pem -x509 -new -days 3650 -out cacert.pem
認証局
OpenSSL Certificate Authority には OpenSSL を CA として使用する詳しいガイドが載っています。
The method shown in this section is mostly meant to show how signing works; it is not suited for large deployments that need to automate signing a large number of certificates. Consider installing an SSL server for that purpose.
Makefile を作成するまえに、#設定 に従って設定ファイルを作成してください。要求の作成ではなく CA の管理に関する指示に従って下さい。
Makefile
Makefile
としてファイルに保存して、ファイルが存在するディレクトリで make
を実行することで最初の CRL が生成されます:
OPENSSL= openssl CNF= openssl.cnf CA= ${OPENSSL} ca -config ${CNF} REQ= ${OPENSSL} req -config ${CNF} KEY= private/cakey.pem KEYMODE= RSA CACERT= cacert.pem CADAYS= 3650 CRL= crl.pem INDEX= index.txt SERIAL= serial CADEPS= ${CNF} ${KEY} ${CACERT} all: ${CRL} ${CRL}: ${CADEPS} ${CA} -gencrl -out ${CRL} ${CACERT}: ${CNF} ${KEY} ${REQ} -key ${KEY} -x509 -new -days ${CADAYS} -out ${CACERT} rm -f ${INDEX} touch ${INDEX} echo 100001 > ${SERIAL} ${KEY}: ${CNF} mkdir -m0700 -p $(dir ${KEY}) touch ${KEY} chmod 0600 ${KEY} ${OPENSSL} genpkey -algorithm ${KEYMODE} -out ${KEY} revoke: ${CADEPS} ${item} @test -n $${item:?'usage: ${MAKE} revoke item=cert.pem'} ${CA} -revoke ${item} ${MAKE} ${CRL} sign: ${CADEPS} ${item} @test -n $${item:?'usage: ${MAKE} sign item=request.csr'} mkdir -p newcerts ${CA} -in ${item} -out ${item:.csr=.crt}
証明書に署名するには:
$ make sign item=req.csr
証明書を無効化するには:
$ make revoke item=cert.pem
トラブルシューティング
復号時に "bad decrypt" と表示される
OpenSSL 1.1.0 から dgst と enc コマンドのデフォルトのダイジェストアルゴリズムが MD5 から SHA256 に変更されています [1]。
OpenSSL 1.0.2 以前を使ってファイルを暗号化した場合、復号化しようとすると新しいバージョンでは以下のようにエラーが発生します:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:crypto/evp/evp_enc.c:540
-md md5
オプションを指定することで問題は解決します:
$ openssl enc -d -md md5 -in encrypted -out decrypted
Python 3.10 and "ca md too weak" errors
In Python 3.10 by default there is a hardcoded list of allowed OpenSSL ciphers. Some of the less secure, like MD5, have been disabled at the ssl
module level, ignoring the system-wide configuration of OpenSSL. It results sometimes in strange errors on older certificates, sometimes even when establishing https
connections, like:
requests.exceptions.SSLError: HTTPSConnectionPool(host='a.kind.of.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(398, '[SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3862)')))
To make Python follow the system configuration, you may have to rebuild it, adding --with-ssl-default-suites=openssl
parameter to ./configure
. The issue has been also reported as FS#73549.
参照
- Wikipedia の OpenSSL のページ
- OpenSSL プロジェクトページ
- FreeBSD ハンドブック
- 署名済みの SSL 証明書を作成するステップバイステップガイド
- OpenSSL Certificate Authority