PythonでX.509 v3の証明書を作成してみる

2018.11.24

この記事は公開されてから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()

実行

上記プログラムを実行します。

$ 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はとても高機能でできることがいっぱいあるので、今後も使い方など紹介していきたいと思います。

誰かの参考になれば幸いです。