Advent Calendar 2021:自作メッセージングプロトコル
Day 4: CAの準備
昨日は送受信者IDの生成と証明書署名要求を実装しました。今日はCAによるユニーク性の保証(検証)とこの証明書署名要求への署名を実装します。
CAの実装
CAはOpenSSLのスクリプト (CA.sh
) をそのまま使ってもよいのですが、CAの署名手順の理解を深めるためにこちらもPythonで実装します。
CA証明書の生成
まずはCA証明書を作ります。CAの証明書は自己署名証明書と呼ばれる、自分の秘密鍵で署名した証明書です。そのため、昨日作ったCSRと同様の手順で証明書署名要求を作成します。ただし、今回作成する証明書はCAの証明書として使うため、X.509形式の証明書拡張として、basicConstraints
拡張フィールドに CA:true
という属性を付与します。CA証明書を生成する関数 generate_cacert()
を以下のとおり実装しました。
VALID_NOT_BEFORE = 0
VALID_NOT_AFTER = 3600 * 24 * 356 * 10 # 10 years
def generate_cacert(cn, key):
# Generate a new CSR
req = OpenSSL.crypto.X509Req()
# Set the common name
req.get_subject().CN = cn
# Set the public key to the request (with SHA256 fingerprint)
req.set_pubkey(key)
req.sign(key, 'sha256')
# Extension for CA
extensions = ([
OpenSSL.crypto.X509Extension(b'basicConstraints', False, b'CA:true'),
])
req.add_extensions(extensions)
# Create a self-signed certificate
cert = OpenSSL.crypto.X509()
cert.set_serial_number(1)
cert.gmtime_adj_notBefore(VALID_NOT_BEFORE)
cert.gmtime_adj_notAfter(VALID_NOT_AFTER)
cert.set_issuer(req.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(key, 'sha256')
return cert
昨日の generate_csr()
関数との違いは、CSRを作成した後に、自分の鍵 key
で有効期限が10年の証明書に署名をして発行している点です。
この generate_cacert()
関数をCAの鍵ペアを作成した後に呼び出します。ここで生成するCA証明書(ルート証明書)の Common Name
は Advent Calendar CA Root 2021
とします。
以下のコードのように、鍵ペアを作成してPEM形式のCA証明書 cacert_pem
を生成します。なお、秘密鍵は今後IDのCSRへの署名に必要になるので、必ず安全な場所に保存しておきます。
CA_CN = "Advent Calendar CA Root 2021"
# Generate a key pair using 256-bit ECDSA
key = ec.generate_private_key(ec.SECP256R1(), default_backend())
# Private key PEM
key_pem = key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())
# Public key
pub_pem = key.public_key().public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)
# Convert the private key information to OpenSSL format
okey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, key_pem)
# Generate a self-signed CA certificate
cacert = generate_cacert(CA_CN, okey)
# Dump the CSR as a PEM file
cacert_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cacert)
print(cacert_pem.decode('utf-8'))
実装
上記で説明したCA証明書の発行を [github:drpnd/advmsg:prepare_ca.py] に実装しました。このプログラムを実行すると以下のように、秘密鍵を ca/cakey.pem
、CA証明書を ca/cacert.pem
に保存します。なお、証明書のPEMも表示しています。
$ python3 prepare_ca.py
Generated CA certificate:
Private key: ca/cakey.pem
CA Certificate: ca/cacert.pem
-----BEGIN CERTIFICATE-----
MIIBNTCB3AIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxBZHZlbnQgQ2FsZW5k
YXIgQ0EgUm9vdCAyMDIxMB4XDTIxMTIwNTA1MDM0NVoXDTMxMDkwNDA1MDM0NVow
JzElMCMGA1UEAwwcQWR2ZW50IENhbGVuZGFyIENBIFJvb3QgMjAyMTBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABH3RsB9gRQs5KLddLhCRV6TMTwmKvc8+dAMQmvv7
+DUVMG6LnSf4zEEI7n2B4lQPZejPNG1AlAAO2HfTmPVA0GUwCgYIKoZIzj0EAwID
SAAwRQIgHxTusyCKCwAjiH3HhwOiNPB37yBCXLhXBmlvOoiiKWMCIQC9Woit8B8G
xpjshBJrG0H+/vuD9xNVuGFLYKiRKB17GA==
-----END CERTIFICATE-----
このCA証明書の中身は openssl
コマンドで以下のように確認できます。
$ openssl x509 -in ca/cacert.pem -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN=Advent Calendar CA Root 2021
Validity
Not Before: Dec 5 05:03:45 2021 GMT
Not After : Sep 4 05:03:45 2031 GMT
Subject: CN=Advent Calendar CA Root 2021
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:7d:d1:b0:1f:60:45:0b:39:28:b7:5d:2e:10:91:
57:a4:cc:4f:09:8a:bd:cf:3e:74:03:10:9a:fb:fb:
f8:35:15:30:6e:8b:9d:27:f8:cc:41:08:ee:7d:81:
e2:54:0f:65:e8:cf:34:6d:40:94:00:0e:d8:77:d3:
98:f5:40:d0:65
ASN1 OID: prime256v1
NIST CURVE: P-256
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:1f:14:ee:b3:20:8a:0b:00:23:88:7d:c7:87:03:
a2:34:f0:77:ef:20:42:5c:b8:57:06:69:6f:3a:88:a2:29:63:
02:21:00:bd:5a:88:ad:f0:1f:06:c6:98:ec:84:12:6b:1b:41:
fe:fe:fb:83:f7:13:55:b8:61:4b:60:a8:91:28:1d:7b:18
-----BEGIN CERTIFICATE-----
MIIBNTCB3AIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxBZHZlbnQgQ2FsZW5k
YXIgQ0EgUm9vdCAyMDIxMB4XDTIxMTIwNTA1MDM0NVoXDTMxMDkwNDA1MDM0NVow
JzElMCMGA1UEAwwcQWR2ZW50IENhbGVuZGFyIENBIFJvb3QgMjAyMTBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABH3RsB9gRQs5KLddLhCRV6TMTwmKvc8+dAMQmvv7
+DUVMG6LnSf4zEEI7n2B4lQPZejPNG1AlAAO2HfTmPVA0GUwCgYIKoZIzj0EAwID
SAAwRQIgHxTusyCKCwAjiH3HhwOiNPB37yBCXLhXBmlvOoiiKWMCIQC9Woit8B8G
xpjshBJrG0H+/vuD9xNVuGFLYKiRKB17GA==
-----END CERTIFICATE-----
まとめと明日の予定
今日はCAの準備をしました。明日は3日目で作成したCSRへの署名を実装する予定です。