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

80 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:05 +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 

5from __future__ import annotations 

6 

7import abc 

8import typing 

9 

10from cryptography import utils 

11from cryptography.hazmat.primitives.hashes import HashAlgorithm 

12 

13# This exists to break an import cycle. These classes are normally accessible 

14# from the serialization module. 

15 

16 

17class PBES(utils.Enum): 

18 PBESv1SHA1And3KeyTripleDESCBC = "PBESv1 using SHA1 and 3-Key TripleDES" 

19 PBESv2SHA256AndAES256CBC = "PBESv2 using SHA256 PBKDF2 and AES256 CBC" 

20 

21 

22class Encoding(utils.Enum): 

23 PEM = "PEM" 

24 DER = "DER" 

25 OpenSSH = "OpenSSH" 

26 Raw = "Raw" 

27 X962 = "ANSI X9.62" 

28 SMIME = "S/MIME" 

29 

30 

31class PrivateFormat(utils.Enum): 

32 PKCS8 = "PKCS8" 

33 TraditionalOpenSSL = "TraditionalOpenSSL" 

34 Raw = "Raw" 

35 OpenSSH = "OpenSSH" 

36 PKCS12 = "PKCS12" 

37 

38 def encryption_builder(self) -> KeySerializationEncryptionBuilder: 

39 if self not in (PrivateFormat.OpenSSH, PrivateFormat.PKCS12): 

40 raise ValueError( 

41 "encryption_builder only supported with PrivateFormat.OpenSSH" 

42 " and PrivateFormat.PKCS12" 

43 ) 

44 return KeySerializationEncryptionBuilder(self) 

45 

46 

47class PublicFormat(utils.Enum): 

48 SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" 

49 PKCS1 = "Raw PKCS#1" 

50 OpenSSH = "OpenSSH" 

51 Raw = "Raw" 

52 CompressedPoint = "X9.62 Compressed Point" 

53 UncompressedPoint = "X9.62 Uncompressed Point" 

54 

55 

56class ParameterFormat(utils.Enum): 

57 PKCS3 = "PKCS3" 

58 

59 

60class KeySerializationEncryption(metaclass=abc.ABCMeta): 

61 pass 

62 

63 

64class BestAvailableEncryption(KeySerializationEncryption): 

65 def __init__(self, password: bytes): 

66 if not isinstance(password, bytes) or len(password) == 0: 

67 raise ValueError("Password must be 1 or more bytes.") 

68 

69 self.password = password 

70 

71 

72class NoEncryption(KeySerializationEncryption): 

73 pass 

74 

75 

76class KeySerializationEncryptionBuilder: 

77 def __init__( 

78 self, 

79 format: PrivateFormat, 

80 *, 

81 _kdf_rounds: typing.Optional[int] = None, 

82 _hmac_hash: typing.Optional[HashAlgorithm] = None, 

83 _key_cert_algorithm: typing.Optional[PBES] = None, 

84 ) -> None: 

85 self._format = format 

86 

87 self._kdf_rounds = _kdf_rounds 

88 self._hmac_hash = _hmac_hash 

89 self._key_cert_algorithm = _key_cert_algorithm 

90 

91 def kdf_rounds(self, rounds: int) -> KeySerializationEncryptionBuilder: 

92 if self._kdf_rounds is not None: 

93 raise ValueError("kdf_rounds already set") 

94 

95 if not isinstance(rounds, int): 

96 raise TypeError("kdf_rounds must be an integer") 

97 

98 if rounds < 1: 

99 raise ValueError("kdf_rounds must be a positive integer") 

100 

101 return KeySerializationEncryptionBuilder( 

102 self._format, 

103 _kdf_rounds=rounds, 

104 _hmac_hash=self._hmac_hash, 

105 _key_cert_algorithm=self._key_cert_algorithm, 

106 ) 

107 

108 def hmac_hash( 

109 self, algorithm: HashAlgorithm 

110 ) -> KeySerializationEncryptionBuilder: 

111 if self._format is not PrivateFormat.PKCS12: 

112 raise TypeError( 

113 "hmac_hash only supported with PrivateFormat.PKCS12" 

114 ) 

115 

116 if self._hmac_hash is not None: 

117 raise ValueError("hmac_hash already set") 

118 return KeySerializationEncryptionBuilder( 

119 self._format, 

120 _kdf_rounds=self._kdf_rounds, 

121 _hmac_hash=algorithm, 

122 _key_cert_algorithm=self._key_cert_algorithm, 

123 ) 

124 

125 def key_cert_algorithm( 

126 self, algorithm: PBES 

127 ) -> KeySerializationEncryptionBuilder: 

128 if self._format is not PrivateFormat.PKCS12: 

129 raise TypeError( 

130 "key_cert_algorithm only supported with " 

131 "PrivateFormat.PKCS12" 

132 ) 

133 if self._key_cert_algorithm is not None: 

134 raise ValueError("key_cert_algorithm already set") 

135 return KeySerializationEncryptionBuilder( 

136 self._format, 

137 _kdf_rounds=self._kdf_rounds, 

138 _hmac_hash=self._hmac_hash, 

139 _key_cert_algorithm=algorithm, 

140 ) 

141 

142 def build(self, password: bytes) -> KeySerializationEncryption: 

143 if not isinstance(password, bytes) or len(password) == 0: 

144 raise ValueError("Password must be 1 or more bytes.") 

145 

146 return _KeySerializationEncryption( 

147 self._format, 

148 password, 

149 kdf_rounds=self._kdf_rounds, 

150 hmac_hash=self._hmac_hash, 

151 key_cert_algorithm=self._key_cert_algorithm, 

152 ) 

153 

154 

155class _KeySerializationEncryption(KeySerializationEncryption): 

156 def __init__( 

157 self, 

158 format: PrivateFormat, 

159 password: bytes, 

160 *, 

161 kdf_rounds: typing.Optional[int], 

162 hmac_hash: typing.Optional[HashAlgorithm], 

163 key_cert_algorithm: typing.Optional[PBES], 

164 ): 

165 self._format = format 

166 self.password = password 

167 

168 self._kdf_rounds = kdf_rounds 

169 self._hmac_hash = hmac_hash 

170 self._key_cert_algorithm = key_cert_algorithm