この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうも!大阪オフィスの西村祐二です。
Pythonを使って証明書を作成する場面に出くわしたので、その方法を紹介したいと思います。
今回、外部ライブラリのpyOpenSSLを使ってやっていきます。
pyOpenSSLはけっこう高機能で、Pythonにデフォルトで入っているsslのライブラリではできないようなことを簡単にできたりします。ただ、書き方など少しクセがあるようにかんじたので、備忘録もかねてブログ化しておきたいと思います。
環境
- macOS Mojave 10.14.1
- Python 3.6.5
- pyOpenSSL v18.0.0
インストール
$ pip install pyopenssl
プログラム
ファイルパスは各々変更してください。証明書とあわせて、ついでに秘密鍵も出力してみます。
cert.py
"""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はとても高機能でできることがいっぱいあるので、今後も使い方など紹介していきたいと思います。
誰かの参考になれば幸いです。