PythonでX.509 v3の証明書を作成してみる
どうも!大阪オフィスの西村祐二です。
Pythonを使って証明書を作成する場面に出くわしたので、その方法を紹介したいと思います。
今回、外部ライブラリのpyOpenSSLを使ってやっていきます。
pyOpenSSLはけっこう高機能で、Pythonにデフォルトで入っているsslのライブラリではできないようなことを簡単にできたりします。ただ、書き方など少しクセがあるようにかんじたので、備忘録もかねてブログ化しておきたいと思います。
環境
- macOS Mojave 10.14.1
- Python 3.6.5
- pyOpenSSL v18.0.0
インストール
$ pip install pyopenssl
プログラム
ファイルパスは各々変更してください。証明書とあわせて、ついでに秘密鍵も出力してみます。
"""Create Cert.""" from OpenSSL import crypto from os.path import join CERT_FILE = 'test.crt' KEY_FILE = 'test.key' LOCAL_TMP_DIR = '/tmp/' def create_cert(): """証明書(cert)を作成.""" # create key pair key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 2048) # create self-signed cert cert = crypto.X509() cert.get_subject().C = 'JP' cert.get_subject().ST = 'test' cert.get_subject().L = 'test' cert.get_subject().O = 'test' cert.get_subject().OU = 'test' cert.get_subject().CN = 'test' cert.set_serial_number(1000) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(10*365*24*60*60) cert.set_issuer(cert.get_subject()) cert.set_pubkey(key) cert.add_extensions([ crypto.X509Extension( 'basicConstraints'.encode('ascii'), False, 'CA:FALSE'.encode('ascii')), crypto.X509Extension( 'keyUsage'.encode('ascii'), True, 'Digital Signature, Non Repudiation'.encode('ascii')), crypto.X509Extension( 'issuerAltName'.encode('ascii'), False, 'email:'.encode('ascii')+'test'.encode('ascii')) ]) # v3 cert.set_version(2) # self signature cert.sign(key, 'sha256') # save cert open(join(LOCAL_TMP_DIR, CERT_FILE), 'wt').write( crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')) # save private key open(join(LOCAL_TMP_DIR, KEY_FILE), 'wt').write( crypto.dump_privatekey(crypto.FILETYPE_PEM, key).decode('utf-8')) print('ok') create_cert()
- 13-14行目 crypto.PKey()
- キーペアの作成する。
- https://pyopenssl.org/en/stable/api/crypto.html#OpenSSL.crypto.PKey.generate_key
- 「openssl genrsa -out test.key 2048」コマンドにちかいことをしています。
- 17行目 cert = crypto.X509()
- 25〜26行目 有効期限を設定する。今回の場合10年
- 29〜36行目 v3の拡張属性の設定を行う。
add_extensions
で設定を追加することができ、その中でX509Extension
を使う。- https://pyopenssl.org/en/stable/api/crypto.html#x509extension-objects
- 設定項目については下記リンクを参照。今回テストのため適当に設定しているので、実際に利用する際は各々で変更してください。
- https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
.encode('ascii')
でエンコードしないとエラーとなるので注意。
- 38行目 set_version(2)
- 40行目 cert.sign(key, 'sha256')
- 43行目 crypto.dump_certificate
- 証明書の情報を取り出す関数。
- 証明書情報をファイルに書き込んで保存
- https://pyopenssl.org/en/stable/api/crypto.html#OpenSSL.crypto.dump_certificate
- 47行目 crypto.dump_privatekey
- 秘密鍵の情報を取り出す関数・
- 秘密鍵の情報をファイルに書き込んで保存
- https://pyopenssl.org/en/stable/api/crypto.html#OpenSSL.crypto.dump_privatekey
実行
上記プログラムを実行します。
$ python cert.py ok
上記のプログラムを実行すると、/tmp/下にファイルが生成されます。opensslコマンドで中身を確認してみます。
$ openssl x509 -text -noout -in /tmp/test.crt Certificate: Data: Version: 3 (0x2) Serial Number: 1000 (0x3e8) Signature Algorithm: sha256WithRSAEncryption Issuer: C=JP, ST=test, L=test, O=test, OU=test, CN=test Validity Not Before: Nov 23 17:05:15 2018 GMT Not After : Nov 20 17:05:15 2028 GMT Subject: C=JP, ST=test, L=test, O=test, OU=test, CN=test Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: .... Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: critical Digital Signature, Non Repudiation X509v3 Issuer Alternative Name: email:test Signature Algorithm: sha256WithRSAEncryption ....
想定どおり、v3の証明書が作成できました。
秘密鍵も下記コマンドで中身を確認することができます。
$ openssl rsa -text -noout -in /tmp/test.key
さいごに
いかがだったでしょうか。
Pythonを使ってx509v3証明書を作成する方法を紹介しました。
今回使用したpyOpenSSLはとても高機能でできることがいっぱいあるので、今後も使い方など紹介していきたいと思います。
誰かの参考になれば幸いです。