Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py: 40%

81 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +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. 

4 

5import typing 

6 

7from cryptography import x509 

8from cryptography.hazmat.primitives import serialization 

9from cryptography.hazmat.primitives._serialization import PBES as PBES 

10from cryptography.hazmat.primitives.asymmetric import ( 

11 dsa, 

12 ec, 

13 ed25519, 

14 ed448, 

15 rsa, 

16) 

17from cryptography.hazmat.primitives.asymmetric.types import ( 

18 PRIVATE_KEY_TYPES, 

19) 

20 

21__all__ = [ 

22 "PBES", 

23 "PKCS12Certificate", 

24 "PKCS12KeyAndCertificates", 

25 "load_key_and_certificates", 

26 "load_pkcs12", 

27 "serialize_key_and_certificates", 

28] 

29 

30_ALLOWED_PKCS12_TYPES = typing.Union[ 

31 rsa.RSAPrivateKey, 

32 dsa.DSAPrivateKey, 

33 ec.EllipticCurvePrivateKey, 

34 ed25519.Ed25519PrivateKey, 

35 ed448.Ed448PrivateKey, 

36] 

37 

38 

39class PKCS12Certificate: 

40 def __init__( 

41 self, 

42 cert: x509.Certificate, 

43 friendly_name: typing.Optional[bytes], 

44 ): 

45 if not isinstance(cert, x509.Certificate): 

46 raise TypeError("Expecting x509.Certificate object") 

47 if friendly_name is not None and not isinstance(friendly_name, bytes): 

48 raise TypeError("friendly_name must be bytes or None") 

49 self._cert = cert 

50 self._friendly_name = friendly_name 

51 

52 @property 

53 def friendly_name(self) -> typing.Optional[bytes]: 

54 return self._friendly_name 

55 

56 @property 

57 def certificate(self) -> x509.Certificate: 

58 return self._cert 

59 

60 def __eq__(self, other: object) -> bool: 

61 if not isinstance(other, PKCS12Certificate): 

62 return NotImplemented 

63 

64 return ( 

65 self.certificate == other.certificate 

66 and self.friendly_name == other.friendly_name 

67 ) 

68 

69 def __hash__(self) -> int: 

70 return hash((self.certificate, self.friendly_name)) 

71 

72 def __repr__(self) -> str: 

73 return "<PKCS12Certificate({}, friendly_name={!r})>".format( 

74 self.certificate, self.friendly_name 

75 ) 

76 

77 

78class PKCS12KeyAndCertificates: 

79 def __init__( 

80 self, 

81 key: typing.Optional[PRIVATE_KEY_TYPES], 

82 cert: typing.Optional[PKCS12Certificate], 

83 additional_certs: typing.List[PKCS12Certificate], 

84 ): 

85 if key is not None and not isinstance( 

86 key, 

87 ( 

88 rsa.RSAPrivateKey, 

89 dsa.DSAPrivateKey, 

90 ec.EllipticCurvePrivateKey, 

91 ed25519.Ed25519PrivateKey, 

92 ed448.Ed448PrivateKey, 

93 ), 

94 ): 

95 raise TypeError( 

96 "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" 

97 " private key, or None." 

98 ) 

99 if cert is not None and not isinstance(cert, PKCS12Certificate): 

100 raise TypeError("cert must be a PKCS12Certificate object or None") 

101 if not all( 

102 isinstance(add_cert, PKCS12Certificate) 

103 for add_cert in additional_certs 

104 ): 

105 raise TypeError( 

106 "all values in additional_certs must be PKCS12Certificate" 

107 " objects" 

108 ) 

109 self._key = key 

110 self._cert = cert 

111 self._additional_certs = additional_certs 

112 

113 @property 

114 def key(self) -> typing.Optional[PRIVATE_KEY_TYPES]: 

115 return self._key 

116 

117 @property 

118 def cert(self) -> typing.Optional[PKCS12Certificate]: 

119 return self._cert 

120 

121 @property 

122 def additional_certs(self) -> typing.List[PKCS12Certificate]: 

123 return self._additional_certs 

124 

125 def __eq__(self, other: object) -> bool: 

126 if not isinstance(other, PKCS12KeyAndCertificates): 

127 return NotImplemented 

128 

129 return ( 

130 self.key == other.key 

131 and self.cert == other.cert 

132 and self.additional_certs == other.additional_certs 

133 ) 

134 

135 def __hash__(self) -> int: 

136 return hash((self.key, self.cert, tuple(self.additional_certs))) 

137 

138 def __repr__(self) -> str: 

139 fmt = ( 

140 "<PKCS12KeyAndCertificates(key={}, cert={}, additional_certs={})>" 

141 ) 

142 return fmt.format(self.key, self.cert, self.additional_certs) 

143 

144 

145def load_key_and_certificates( 

146 data: bytes, 

147 password: typing.Optional[bytes], 

148 backend: typing.Any = None, 

149) -> typing.Tuple[ 

150 typing.Optional[PRIVATE_KEY_TYPES], 

151 typing.Optional[x509.Certificate], 

152 typing.List[x509.Certificate], 

153]: 

154 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

155 

156 return ossl.load_key_and_certificates_from_pkcs12(data, password) 

157 

158 

159def load_pkcs12( 

160 data: bytes, 

161 password: typing.Optional[bytes], 

162 backend: typing.Any = None, 

163) -> PKCS12KeyAndCertificates: 

164 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

165 

166 return ossl.load_pkcs12(data, password) 

167 

168 

169_PKCS12_CAS_TYPES = typing.Union[ 

170 x509.Certificate, 

171 PKCS12Certificate, 

172] 

173 

174 

175def serialize_key_and_certificates( 

176 name: typing.Optional[bytes], 

177 key: typing.Optional[_ALLOWED_PKCS12_TYPES], 

178 cert: typing.Optional[x509.Certificate], 

179 cas: typing.Optional[typing.Iterable[_PKCS12_CAS_TYPES]], 

180 encryption_algorithm: serialization.KeySerializationEncryption, 

181) -> bytes: 

182 if key is not None and not isinstance( 

183 key, 

184 ( 

185 rsa.RSAPrivateKey, 

186 dsa.DSAPrivateKey, 

187 ec.EllipticCurvePrivateKey, 

188 ed25519.Ed25519PrivateKey, 

189 ed448.Ed448PrivateKey, 

190 ), 

191 ): 

192 raise TypeError( 

193 "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" 

194 " private key, or None." 

195 ) 

196 if cert is not None and not isinstance(cert, x509.Certificate): 

197 raise TypeError("cert must be a certificate or None") 

198 

199 if cas is not None: 

200 cas = list(cas) 

201 if not all( 

202 isinstance( 

203 val, 

204 ( 

205 x509.Certificate, 

206 PKCS12Certificate, 

207 ), 

208 ) 

209 for val in cas 

210 ): 

211 raise TypeError("all values in cas must be certificates") 

212 

213 if not isinstance( 

214 encryption_algorithm, serialization.KeySerializationEncryption 

215 ): 

216 raise TypeError( 

217 "Key encryption algorithm must be a " 

218 "KeySerializationEncryption instance" 

219 ) 

220 

221 if key is None and cert is None and not cas: 

222 raise ValueError("You must supply at least one of key, cert, or cas") 

223 

224 from cryptography.hazmat.backends.openssl.backend import backend 

225 

226 return backend.serialize_key_and_certificates_to_pkcs12( 

227 name, key, cert, cas, encryption_algorithm 

228 )