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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

79 statements  

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 

8 

9from cryptography import utils 

10from cryptography.hazmat.primitives.hashes import HashAlgorithm 

11 

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

13# from the serialization module. 

14 

15 

16class PBES(utils.Enum): 

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

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

19 

20 

21class Encoding(utils.Enum): 

22 PEM = "PEM" 

23 DER = "DER" 

24 OpenSSH = "OpenSSH" 

25 Raw = "Raw" 

26 X962 = "ANSI X9.62" 

27 SMIME = "S/MIME" 

28 

29 

30class PrivateFormat(utils.Enum): 

31 PKCS8 = "PKCS8" 

32 TraditionalOpenSSL = "TraditionalOpenSSL" 

33 Raw = "Raw" 

34 OpenSSH = "OpenSSH" 

35 PKCS12 = "PKCS12" 

36 

37 def encryption_builder(self) -> KeySerializationEncryptionBuilder: 

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

39 raise ValueError( 

40 "encryption_builder only supported with PrivateFormat.OpenSSH" 

41 " and PrivateFormat.PKCS12" 

42 ) 

43 return KeySerializationEncryptionBuilder(self) 

44 

45 

46class PublicFormat(utils.Enum): 

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

48 PKCS1 = "Raw PKCS#1" 

49 OpenSSH = "OpenSSH" 

50 Raw = "Raw" 

51 CompressedPoint = "X9.62 Compressed Point" 

52 UncompressedPoint = "X9.62 Uncompressed Point" 

53 

54 

55class ParameterFormat(utils.Enum): 

56 PKCS3 = "PKCS3" 

57 

58 

59class KeySerializationEncryption(metaclass=abc.ABCMeta): 

60 pass 

61 

62 

63class BestAvailableEncryption(KeySerializationEncryption): 

64 def __init__(self, password: bytes): 

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

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

67 

68 self.password = password 

69 

70 

71class NoEncryption(KeySerializationEncryption): 

72 pass 

73 

74 

75class KeySerializationEncryptionBuilder: 

76 def __init__( 

77 self, 

78 format: PrivateFormat, 

79 *, 

80 _kdf_rounds: int | None = None, 

81 _hmac_hash: HashAlgorithm | None = None, 

82 _key_cert_algorithm: PBES | None = None, 

83 ) -> None: 

84 self._format = format 

85 

86 self._kdf_rounds = _kdf_rounds 

87 self._hmac_hash = _hmac_hash 

88 self._key_cert_algorithm = _key_cert_algorithm 

89 

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

91 if self._kdf_rounds is not None: 

92 raise ValueError("kdf_rounds already set") 

93 

94 if not isinstance(rounds, int): 

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

96 

97 if rounds < 1: 

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

99 

100 return KeySerializationEncryptionBuilder( 

101 self._format, 

102 _kdf_rounds=rounds, 

103 _hmac_hash=self._hmac_hash, 

104 _key_cert_algorithm=self._key_cert_algorithm, 

105 ) 

106 

107 def hmac_hash( 

108 self, algorithm: HashAlgorithm 

109 ) -> KeySerializationEncryptionBuilder: 

110 if self._format is not PrivateFormat.PKCS12: 

111 raise TypeError( 

112 "hmac_hash only supported with PrivateFormat.PKCS12" 

113 ) 

114 

115 if self._hmac_hash is not None: 

116 raise ValueError("hmac_hash already set") 

117 return KeySerializationEncryptionBuilder( 

118 self._format, 

119 _kdf_rounds=self._kdf_rounds, 

120 _hmac_hash=algorithm, 

121 _key_cert_algorithm=self._key_cert_algorithm, 

122 ) 

123 

124 def key_cert_algorithm( 

125 self, algorithm: PBES 

126 ) -> KeySerializationEncryptionBuilder: 

127 if self._format is not PrivateFormat.PKCS12: 

128 raise TypeError( 

129 "key_cert_algorithm only supported with " 

130 "PrivateFormat.PKCS12" 

131 ) 

132 if self._key_cert_algorithm is not None: 

133 raise ValueError("key_cert_algorithm already set") 

134 return KeySerializationEncryptionBuilder( 

135 self._format, 

136 _kdf_rounds=self._kdf_rounds, 

137 _hmac_hash=self._hmac_hash, 

138 _key_cert_algorithm=algorithm, 

139 ) 

140 

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

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

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

144 

145 return _KeySerializationEncryption( 

146 self._format, 

147 password, 

148 kdf_rounds=self._kdf_rounds, 

149 hmac_hash=self._hmac_hash, 

150 key_cert_algorithm=self._key_cert_algorithm, 

151 ) 

152 

153 

154class _KeySerializationEncryption(KeySerializationEncryption): 

155 def __init__( 

156 self, 

157 format: PrivateFormat, 

158 password: bytes, 

159 *, 

160 kdf_rounds: int | None, 

161 hmac_hash: HashAlgorithm | None, 

162 key_cert_algorithm: PBES | None, 

163 ): 

164 self._format = format 

165 self.password = password 

166 

167 self._kdf_rounds = kdf_rounds 

168 self._hmac_hash = hmac_hash 

169 self._key_cert_algorithm = key_cert_algorithm