certbuilder is a Python library for constructing X.509 certificates. It provides a high-level interface with knowledge of RFC 5280 to produce, valid, correct certificates without terrible APIs or hunting through RFCs.
Since its only dependencies are the asn1crypto and oscrypto libraries, it is easy to install and use on Windows, OS X, Linux and the BSDs.
The documentation consists of the following topics:
A simple, self-signed certificate can be created by generating a public/private
key pair using oscrypto and then passing a dictionary of name information to
the CertificateBuilder() constructor:
from oscrypto import asymmetric
from certbuilder import CertificateBuilder, pem_armor_certificate
public_key, private_key = asymmetric.generate_pair('rsa', bit_size=2048)
with open('/path/to/my/env/will_bond.key', 'wb') as f:
f.write(asymmetric.dump_private_key(private_key, 'password'))
builder = CertificateBuilder(
{
'country_name': 'US',
'state_or_province_name': 'Massachusetts',
'locality_name': 'Newbury',
'organization_name': 'Codex Non Sufficit LC',
'common_name': 'Will Bond',
},
public_key
)
builder.self_signed = True
certificate = builder.build(private_key)
with open('/path/to/my/env/will_bond.crt', 'wb') as f:
f.write(pem_armor_certificate(certificate))All name components must be unicode strings. Common name keys include:
country_namestate_or_province_namelocality_nameorganization_namecommon_name
Less common keys include:
organizational_unit_nameemail_addressstreet_addresspostal_codebusiness_categoryincorporation_localityincorporation_state_or_provinceincorporation_country
See CertificateBuilder.subject for a full
list of supported name keys.
Beyond self-signed certificates lives the world of root CAs, intermediate CAs and end-entity certificates.
The example below will create a root CA and then an end-entity certificate signed by the root. By simply creating another CA certificate signed by the root CA, an intermediate CA certificate could be added.
from oscrypto import asymmetric
from certbuilder import CertificateBuilder, pem_armor_certificate
# Generate and save the key and certificate for the root CA
root_ca_public_key, root_ca_private_key = asymmetric.generate_pair('rsa', bit_size=2048)
with open('/path/to/my/env/root_ca.key', 'wb') as f:
f.write(asymmetric.dump_private_key(root_ca_private_key, 'password'))
builder = CertificateBuilder(
{
'country_name': 'US',
'state_or_province_name': 'Massachusetts',
'locality_name': 'Newbury',
'organization_name': 'Codex Non Sufficit LC',
'common_name': 'CodexNS Root CA 1',
},
root_ca_public_key
)
builder.self_signed = True
builder.ca = True
root_ca_certificate = builder.build(root_ca_private_key)
with open('/path/to/my/env/root_ca.crt', 'wb') as f:
f.write(pem_armor_certificate(root_ca_certificate))
# Generate an end-entity key and certificate, signed by the root
end_entity_public_key, end_entity_private_key = asymmetric.generate_pair('rsa', bit_size=2048)
with open('/path/to/my/env/will_bond.key', 'wb') as f:
f.write(asymmetric.dump_private_key(end_entity_private_key, 'password'))
builder = CertificateBuilder(
{
'country_name': 'US',
'state_or_province_name': 'Massachusetts',
'locality_name': 'Newbury',
'organization_name': 'Codex Non Sufficit LC',
'common_name': 'Will Bond',
},
end_entity_public_key
)
builder.issuer = root_ca_certificate
end_entity_certificate = builder.build(root_ca_private_key)
with open('/path/to/my/env/will_bond.crt', 'wb') as f:
f.write(pem_armor_certificate(end_entity_certificate))