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.2.2, created at 2023-03-26 06:36 +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 ed448, 

14 ed25519, 

15 rsa, 

16) 

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

18 

19__all__ = [ 

20 "PBES", 

21 "PKCS12PrivateKeyTypes", 

22 "PKCS12Certificate", 

23 "PKCS12KeyAndCertificates", 

24 "load_key_and_certificates", 

25 "load_pkcs12", 

26 "serialize_key_and_certificates", 

27] 

28 

29PKCS12PrivateKeyTypes = typing.Union[ 

30 rsa.RSAPrivateKey, 

31 dsa.DSAPrivateKey, 

32 ec.EllipticCurvePrivateKey, 

33 ed25519.Ed25519PrivateKey, 

34 ed448.Ed448PrivateKey, 

35] 

36 

37 

38class PKCS12Certificate: 

39 def __init__( 

40 self, 

41 cert: x509.Certificate, 

42 friendly_name: typing.Optional[bytes], 

43 ): 

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

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

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

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

48 self._cert = cert 

49 self._friendly_name = friendly_name 

50 

51 @property 

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

53 return self._friendly_name 

54 

55 @property 

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

57 return self._cert 

58 

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

60 if not isinstance(other, PKCS12Certificate): 

61 return NotImplemented 

62 

63 return ( 

64 self.certificate == other.certificate 

65 and self.friendly_name == other.friendly_name 

66 ) 

67 

68 def __hash__(self) -> int: 

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

70 

71 def __repr__(self) -> str: 

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

73 self.certificate, self.friendly_name 

74 ) 

75 

76 

77class PKCS12KeyAndCertificates: 

78 def __init__( 

79 self, 

80 key: typing.Optional[PrivateKeyTypes], 

81 cert: typing.Optional[PKCS12Certificate], 

82 additional_certs: typing.List[PKCS12Certificate], 

83 ): 

84 if key is not None and not isinstance( 

85 key, 

86 ( 

87 rsa.RSAPrivateKey, 

88 dsa.DSAPrivateKey, 

89 ec.EllipticCurvePrivateKey, 

90 ed25519.Ed25519PrivateKey, 

91 ed448.Ed448PrivateKey, 

92 ), 

93 ): 

94 raise TypeError( 

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

96 " private key, or None." 

97 ) 

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

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

100 if not all( 

101 isinstance(add_cert, PKCS12Certificate) 

102 for add_cert in additional_certs 

103 ): 

104 raise TypeError( 

105 "all values in additional_certs must be PKCS12Certificate" 

106 " objects" 

107 ) 

108 self._key = key 

109 self._cert = cert 

110 self._additional_certs = additional_certs 

111 

112 @property 

113 def key(self) -> typing.Optional[PrivateKeyTypes]: 

114 return self._key 

115 

116 @property 

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

118 return self._cert 

119 

120 @property 

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

122 return self._additional_certs 

123 

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

125 if not isinstance(other, PKCS12KeyAndCertificates): 

126 return NotImplemented 

127 

128 return ( 

129 self.key == other.key 

130 and self.cert == other.cert 

131 and self.additional_certs == other.additional_certs 

132 ) 

133 

134 def __hash__(self) -> int: 

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

136 

137 def __repr__(self) -> str: 

138 fmt = ( 

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

140 ) 

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

142 

143 

144def load_key_and_certificates( 

145 data: bytes, 

146 password: typing.Optional[bytes], 

147 backend: typing.Any = None, 

148) -> typing.Tuple[ 

149 typing.Optional[PrivateKeyTypes], 

150 typing.Optional[x509.Certificate], 

151 typing.List[x509.Certificate], 

152]: 

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

154 

155 return ossl.load_key_and_certificates_from_pkcs12(data, password) 

156 

157 

158def load_pkcs12( 

159 data: bytes, 

160 password: typing.Optional[bytes], 

161 backend: typing.Any = None, 

162) -> PKCS12KeyAndCertificates: 

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

164 

165 return ossl.load_pkcs12(data, password) 

166 

167 

168_PKCS12CATypes = typing.Union[ 

169 x509.Certificate, 

170 PKCS12Certificate, 

171] 

172 

173 

174def serialize_key_and_certificates( 

175 name: typing.Optional[bytes], 

176 key: typing.Optional[PKCS12PrivateKeyTypes], 

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

178 cas: typing.Optional[typing.Iterable[_PKCS12CATypes]], 

179 encryption_algorithm: serialization.KeySerializationEncryption, 

180) -> bytes: 

181 if key is not None and not isinstance( 

182 key, 

183 ( 

184 rsa.RSAPrivateKey, 

185 dsa.DSAPrivateKey, 

186 ec.EllipticCurvePrivateKey, 

187 ed25519.Ed25519PrivateKey, 

188 ed448.Ed448PrivateKey, 

189 ), 

190 ): 

191 raise TypeError( 

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

193 " private key, or None." 

194 ) 

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

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

197 

198 if cas is not None: 

199 cas = list(cas) 

200 if not all( 

201 isinstance( 

202 val, 

203 ( 

204 x509.Certificate, 

205 PKCS12Certificate, 

206 ), 

207 ) 

208 for val in cas 

209 ): 

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

211 

212 if not isinstance( 

213 encryption_algorithm, serialization.KeySerializationEncryption 

214 ): 

215 raise TypeError( 

216 "Key encryption algorithm must be a " 

217 "KeySerializationEncryption instance" 

218 ) 

219 

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

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

222 

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

224 

225 return backend.serialize_key_and_certificates_to_pkcs12( 

226 name, key, cert, cas, encryption_algorithm 

227 )