|
36 | 36 | > In the case that it encodes a certificate it would simply contain the
|
37 | 37 | > base64 encoding of the DER certificate [plus the header and footer].
|
38 | 38 |
|
| 39 | +PKCS12 |
| 40 | +-------- |
| 41 | +
|
| 42 | +PKCS12 stands for "Public Key Cryptography Standard #12". |
| 43 | +
|
| 44 | +> […] a binary format described in RFC 7292. It can contain certificates, keys, and more. |
| 45 | +> PKCS12 files commonly have a `pfx` or `p12` file suffix. |
39 | 46 | """
|
40 | 47 |
|
41 | 48 | __all__ = [
|
|
44 | 51 | ]
|
45 | 52 |
|
46 | 53 | import base64
|
47 |
| -from typing import Union |
| 54 | +from typing import Optional, Union |
48 | 55 |
|
49 | 56 | import cryptography.hazmat.backends.openssl.backend as _crypto_x509_backend
|
| 57 | +import cryptography.hazmat.primitives.serialization.pkcs12 |
50 | 58 | import cryptography.x509
|
51 | 59 | import signxml.util
|
52 | 60 | from cryptography.x509 import Certificate as X509Cert
|
@@ -170,3 +178,38 @@ def remove_pem_cert_header_footer(pem_cert: bytes) -> bytes:
|
170 | 178 | mod_pem_value_str = signxml.util.strip_pem_header(pem_value_str)
|
171 | 179 | mod_pem_value: bytes = mod_pem_value_str.encode('ascii').strip()
|
172 | 180 | return mod_pem_value
|
| 181 | + |
| 182 | + |
| 183 | +def load_pfx_x509_cert(pfx_value: bytes, password: Union[bytes, str, None]) -> Optional[X509Cert]: |
| 184 | + """ |
| 185 | + Load an X.509 certificate from PKCS12-encoded data. |
| 186 | +
|
| 187 | + :raises TypeError: |
| 188 | + :raises ValueError: |
| 189 | + """ |
| 190 | + if isinstance(password, str): |
| 191 | + password = password.encode() |
| 192 | + |
| 193 | + try: |
| 194 | + p12 = cryptography.hazmat.primitives.serialization.pkcs12.load_pkcs12( |
| 195 | + data=pfx_value, password=password |
| 196 | + ) |
| 197 | + except TypeError: |
| 198 | + # Examples: |
| 199 | + # - "TypeError: argument 'data': a bytes-like object is required, not 'NoneType'" |
| 200 | + # - "argument 'password': from_buffer() cannot return the address of a unicode object" |
| 201 | + raise |
| 202 | + except ValueError: |
| 203 | + # Examples: |
| 204 | + # - "Invalid password or PKCS12 data" |
| 205 | + # - "Could not deserialize PKCS12 data" |
| 206 | + raise |
| 207 | + |
| 208 | + pkcs12_cert = p12.cert |
| 209 | + x509_cert = pkcs12_cert.certificate if pkcs12_cert is not None else None |
| 210 | + return x509_cert |
| 211 | + |
| 212 | + |
| 213 | +# Aliases for `load_pfx_x509_cert()`: |
| 214 | +load_pkcs12_x509_cert = load_pfx_x509_cert |
| 215 | +load_p12_x509_cert = load_pfx_x509_cert |
0 commit comments