Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py: 40%
82 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 07:26 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 07:26 +0000
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
5from __future__ import annotations
7import typing
9from cryptography import x509
10from cryptography.hazmat.primitives import serialization
11from cryptography.hazmat.primitives._serialization import PBES as PBES
12from cryptography.hazmat.primitives.asymmetric import (
13 dsa,
14 ec,
15 ed448,
16 ed25519,
17 rsa,
18)
19from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
21__all__ = [
22 "PBES",
23 "PKCS12PrivateKeyTypes",
24 "PKCS12Certificate",
25 "PKCS12KeyAndCertificates",
26 "load_key_and_certificates",
27 "load_pkcs12",
28 "serialize_key_and_certificates",
29]
31PKCS12PrivateKeyTypes = typing.Union[
32 rsa.RSAPrivateKey,
33 dsa.DSAPrivateKey,
34 ec.EllipticCurvePrivateKey,
35 ed25519.Ed25519PrivateKey,
36 ed448.Ed448PrivateKey,
37]
40class PKCS12Certificate:
41 def __init__(
42 self,
43 cert: x509.Certificate,
44 friendly_name: bytes | None,
45 ):
46 if not isinstance(cert, x509.Certificate):
47 raise TypeError("Expecting x509.Certificate object")
48 if friendly_name is not None and not isinstance(friendly_name, bytes):
49 raise TypeError("friendly_name must be bytes or None")
50 self._cert = cert
51 self._friendly_name = friendly_name
53 @property
54 def friendly_name(self) -> bytes | None:
55 return self._friendly_name
57 @property
58 def certificate(self) -> x509.Certificate:
59 return self._cert
61 def __eq__(self, other: object) -> bool:
62 if not isinstance(other, PKCS12Certificate):
63 return NotImplemented
65 return (
66 self.certificate == other.certificate
67 and self.friendly_name == other.friendly_name
68 )
70 def __hash__(self) -> int:
71 return hash((self.certificate, self.friendly_name))
73 def __repr__(self) -> str:
74 return "<PKCS12Certificate({}, friendly_name={!r})>".format(
75 self.certificate, self.friendly_name
76 )
79class PKCS12KeyAndCertificates:
80 def __init__(
81 self,
82 key: PrivateKeyTypes | None,
83 cert: PKCS12Certificate | None,
84 additional_certs: list[PKCS12Certificate],
85 ):
86 if key is not None and not isinstance(
87 key,
88 (
89 rsa.RSAPrivateKey,
90 dsa.DSAPrivateKey,
91 ec.EllipticCurvePrivateKey,
92 ed25519.Ed25519PrivateKey,
93 ed448.Ed448PrivateKey,
94 ),
95 ):
96 raise TypeError(
97 "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448"
98 " private key, or None."
99 )
100 if cert is not None and not isinstance(cert, PKCS12Certificate):
101 raise TypeError("cert must be a PKCS12Certificate object or None")
102 if not all(
103 isinstance(add_cert, PKCS12Certificate)
104 for add_cert in additional_certs
105 ):
106 raise TypeError(
107 "all values in additional_certs must be PKCS12Certificate"
108 " objects"
109 )
110 self._key = key
111 self._cert = cert
112 self._additional_certs = additional_certs
114 @property
115 def key(self) -> PrivateKeyTypes | None:
116 return self._key
118 @property
119 def cert(self) -> PKCS12Certificate | None:
120 return self._cert
122 @property
123 def additional_certs(self) -> list[PKCS12Certificate]:
124 return self._additional_certs
126 def __eq__(self, other: object) -> bool:
127 if not isinstance(other, PKCS12KeyAndCertificates):
128 return NotImplemented
130 return (
131 self.key == other.key
132 and self.cert == other.cert
133 and self.additional_certs == other.additional_certs
134 )
136 def __hash__(self) -> int:
137 return hash((self.key, self.cert, tuple(self.additional_certs)))
139 def __repr__(self) -> str:
140 fmt = (
141 "<PKCS12KeyAndCertificates(key={}, cert={}, additional_certs={})>"
142 )
143 return fmt.format(self.key, self.cert, self.additional_certs)
146def load_key_and_certificates(
147 data: bytes,
148 password: bytes | None,
149 backend: typing.Any = None,
150) -> tuple[
151 PrivateKeyTypes | None,
152 x509.Certificate | None,
153 list[x509.Certificate],
154]:
155 from cryptography.hazmat.backends.openssl.backend import backend as ossl
157 return ossl.load_key_and_certificates_from_pkcs12(data, password)
160def load_pkcs12(
161 data: bytes,
162 password: bytes | None,
163 backend: typing.Any = None,
164) -> PKCS12KeyAndCertificates:
165 from cryptography.hazmat.backends.openssl.backend import backend as ossl
167 return ossl.load_pkcs12(data, password)
170_PKCS12CATypes = typing.Union[
171 x509.Certificate,
172 PKCS12Certificate,
173]
176def serialize_key_and_certificates(
177 name: bytes | None,
178 key: PKCS12PrivateKeyTypes | None,
179 cert: x509.Certificate | None,
180 cas: typing.Iterable[_PKCS12CATypes] | None,
181 encryption_algorithm: serialization.KeySerializationEncryption,
182) -> bytes:
183 if key is not None and not isinstance(
184 key,
185 (
186 rsa.RSAPrivateKey,
187 dsa.DSAPrivateKey,
188 ec.EllipticCurvePrivateKey,
189 ed25519.Ed25519PrivateKey,
190 ed448.Ed448PrivateKey,
191 ),
192 ):
193 raise TypeError(
194 "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448"
195 " private key, or None."
196 )
197 if cert is not None and not isinstance(cert, x509.Certificate):
198 raise TypeError("cert must be a certificate or None")
200 if cas is not None:
201 cas = list(cas)
202 if not all(
203 isinstance(
204 val,
205 (
206 x509.Certificate,
207 PKCS12Certificate,
208 ),
209 )
210 for val in cas
211 ):
212 raise TypeError("all values in cas must be certificates")
214 if not isinstance(
215 encryption_algorithm, serialization.KeySerializationEncryption
216 ):
217 raise TypeError(
218 "Key encryption algorithm must be a "
219 "KeySerializationEncryption instance"
220 )
222 if key is None and cert is None and not cas:
223 raise ValueError("You must supply at least one of key, cert, or cas")
225 from cryptography.hazmat.backends.openssl.backend import backend
227 return backend.serialize_key_and_certificates_to_pkcs12(
228 name, key, cert, cas, encryption_algorithm
229 )