2023-01-19 08:29:46 +01:00
#!/usr/bin/env python3
""" utility that generates X.509 certificates for testing
the following certificates and their keys are stored in your working directory :
- ca_cert . pem , ca_key . pem
- server_cert . pem , server_key . pem
- client_cert . pem , client_key . pem
"""
import datetime
from cryptography import x509
from cryptography . hazmat . primitives import hashes , serialization
from cryptography . hazmat . primitives . asymmetric . ed25519 import Ed25519PrivateKey
def gen_key ( ) :
return Ed25519PrivateKey . generate ( )
not_before = datetime . datetime . now ( datetime . timezone . utc )
not_after = not_before + datetime . timedelta ( days = 3 )
def gen_ca_cert ( ca_key ) :
ca_name = x509 . Name ( [
x509 . NameAttribute ( x509 . oid . NameOID . COMMON_NAME , " sqld dev CA " ) ,
] )
return x509 . CertificateBuilder ( ) \
. issuer_name ( ca_name ) \
. subject_name ( ca_name ) \
. public_key ( ca_key . public_key ( ) ) \
. serial_number ( x509 . random_serial_number ( ) ) \
. not_valid_before ( not_before ) \
. not_valid_after ( not_after ) \
. add_extension ( x509 . BasicConstraints ( ca = True , path_length = None ) , critical = True ) \
. add_extension ( x509 . KeyUsage (
key_cert_sign = True ,
crl_sign = True ,
digital_signature = False ,
content_commitment = False ,
key_encipherment = False ,
data_encipherment = False ,
key_agreement = False ,
encipher_only = False ,
decipher_only = False ,
) , critical = True ) \
. sign ( ca_key , None )
def gen_peer_cert ( ca_cert , ca_key , peer_key , peer_common_name , peer_dns_names ) :
return x509 . CertificateBuilder ( ) \
. issuer_name ( ca_cert . subject ) \
. subject_name ( x509 . Name ( [
x509 . NameAttribute ( x509 . oid . NameOID . COMMON_NAME , peer_common_name ) ,
] ) ) \
. public_key ( peer_key . public_key ( ) ) \
. serial_number ( x509 . random_serial_number ( ) ) \
. not_valid_before ( not_before ) \
. not_valid_after ( not_after ) \
. add_extension ( x509 . BasicConstraints ( ca = False , path_length = None ) , critical = True ) \
. add_extension ( x509 . KeyUsage (
digital_signature = True ,
key_encipherment = False ,
key_cert_sign = False ,
crl_sign = False ,
content_commitment = False ,
data_encipherment = False ,
key_agreement = False ,
encipher_only = False ,
decipher_only = False ,
) , critical = True ) \
. add_extension ( x509 . SubjectAlternativeName ( [
x509 . DNSName ( dns_name ) for dns_name in peer_dns_names
] ) , critical = False ) \
. sign ( ca_key , None )
def store_cert_chain_and_key ( cert_chain , key , name ) - > None :
cert_file = f " { name } _cert.pem "
key_file = f " { name } _key.pem "
with open ( cert_file , " wb " ) as f :
for cert in cert_chain :
f . write ( cert . public_bytes ( encoding = serialization . Encoding . PEM ) )
print ( f " stored cert { name !r} into { cert_file !r} " )
with open ( key_file , " wb " ) as f :
f . write ( key . private_bytes (
encoding = serialization . Encoding . PEM ,
format = serialization . PrivateFormat . PKCS8 ,
encryption_algorithm = serialization . NoEncryption ( ) ,
) )
print ( f " stored private key { name !r} into { key_file !r} " )
if __name__ == " __main__ " :
ca_key = gen_key ( )
ca_cert = gen_ca_cert ( ca_key )
store_cert_chain_and_key ( [ ca_cert ] , ca_key , " ca " )
server_key = gen_key ( )
server_cert = gen_peer_cert ( ca_cert , ca_key , server_key , " sqld " , [ " sqld " ] )
store_cert_chain_and_key ( [ server_cert , ca_cert ] , server_key , " server " )
2023-01-19 13:56:58 +01:00
client_key = gen_key ( )
client_cert = gen_peer_cert ( ca_cert , ca_key , client_key , " sqld replica " , [ ] )
store_cert_chain_and_key ( [ client_cert , ca_cert ] , client_key , " client " )
2023-01-19 08:29:46 +01:00
print ( f " these are development certs, they will expire at { not_after } " )