certified.cert_base — FullCert
FullCert is the base class for all certificate types that hold both a certificate
and its corresponding private key. CA and LeafCert (see ca.md) both
extend this class.
Originally derived from trustme (MIT license).
FullCert
A full certificate contains both a certificate and private key.
Source code in certified/cert_base.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 | class FullCert:
""" A full certificate contains both a certificate and private key.
"""
_certificate: x509.Certificate
_private_key: CertificateIssuerPrivateKeyTypes
def __init__(self, cert_bytes: bytes, private_key_bytes: bytes,
get_pw: PWCallback = None) -> None:
"""Create from an existing cert and private key.
Args:
cert_bytes: The bytes of the certificate in PEM format
private_key_bytes: The bytes of the private key in PEM format
get_pw: get the password used to decrypt the key (if a password was set)
"""
#self.parent_cert = None
self._certificate = x509.load_pem_x509_certificate(cert_bytes)
password : Optional[bytes] = None
if get_pw:
password = get_pw()
pkey = load_pem_private_key(
private_key_bytes, password=password
)
assert isinstance(pkey, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey, rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey)), f"Unusable key type: {type(pkey)}"
self._private_key = pkey
@classmethod
def load(cls, base : Pstr, get_pw = None):
cert = Blob.read(str(base) + ".crt")
key = Blob.read(str(base) + ".key")
assert key.is_secret, f"{str(base)+'.key'} has compromised file permissions."
return cls(cert.bytes(), key.bytes(), get_pw)
def save(self, base : Pstr, overwrite = False):
self.cert_pem.write(str(base) + ".crt")
self._get_private_key().write(str(base) + ".key")
@property
def certificate(self) -> x509.Certificate:
return self._certificate
@property
def pubkey(self) -> CertificatePublicKeyTypes:
return self._certificate.public_key()
@property
def serial(self) -> str:
return serial_number(self._certificate)
@property
def cert_pem(self) -> PublicBlob:
"""`Blob`: The PEM-encoded certificate for this CA. Add this to your
trust store to trust this CA."""
return PublicBlob(self._certificate)
def _get_private_key(self) -> PrivateBlob:
"""`PrivateBlob`: The PEM-encoded private key.
You should avoid using this if possible.
"""
return PrivateBlob(self._private_key)
def __str__(self) -> str:
return str(self.cert_pem)
def create_csr(self) -> x509.CertificateSigningRequest:
""" Generate a CSR.
"""
try:
san = self._certificate.extensions.get_extension_for_class(
x509.SubjectAlternativeName
)
except x509.ExtensionNotFound:
san = None
pubkey = self._certificate.public_key()
csr = x509.CertificateSigningRequestBuilder().subject_name(
self._certificate.subject
)
if san:
csr = csr.add_extension(
san.value,
critical=san.critical,
)
return csr.sign(self._private_key, encode.hash_for_pubkey(pubkey))
def revoke(self) -> None:
# https://cryptography.io/en/latest/x509/reference/#x-509-certificate-revocation-list-builder
raise RuntimeError("FIXME: Not implemented.")
|
cert_pem
property
Blob: The PEM-encoded certificate for this CA. Add this to your
trust store to trust this CA.
__init__(cert_bytes, private_key_bytes, get_pw=None)
Create from an existing cert and private key.
Parameters:
| Name |
Type |
Description |
Default |
cert_bytes
|
bytes
|
The bytes of the certificate in PEM format
|
required
|
private_key_bytes
|
bytes
|
The bytes of the private key in PEM format
|
required
|
get_pw
|
PWCallback
|
get the password used to decrypt the key (if a password was set)
|
None
|
Source code in certified/cert_base.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 | def __init__(self, cert_bytes: bytes, private_key_bytes: bytes,
get_pw: PWCallback = None) -> None:
"""Create from an existing cert and private key.
Args:
cert_bytes: The bytes of the certificate in PEM format
private_key_bytes: The bytes of the private key in PEM format
get_pw: get the password used to decrypt the key (if a password was set)
"""
#self.parent_cert = None
self._certificate = x509.load_pem_x509_certificate(cert_bytes)
password : Optional[bytes] = None
if get_pw:
password = get_pw()
pkey = load_pem_private_key(
private_key_bytes, password=password
)
assert isinstance(pkey, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey, rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey)), f"Unusable key type: {type(pkey)}"
self._private_key = pkey
|
create_csr()
Generate a CSR.
Source code in certified/cert_base.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 | def create_csr(self) -> x509.CertificateSigningRequest:
""" Generate a CSR.
"""
try:
san = self._certificate.extensions.get_extension_for_class(
x509.SubjectAlternativeName
)
except x509.ExtensionNotFound:
san = None
pubkey = self._certificate.public_key()
csr = x509.CertificateSigningRequestBuilder().subject_name(
self._certificate.subject
)
if san:
csr = csr.add_extension(
san.value,
critical=san.critical,
)
return csr.sign(self._private_key, encode.hash_for_pubkey(pubkey))
|