Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/oscrypto/_openssl/util.py: 20%

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

54 statements  

1# coding: utf-8 

2from __future__ import unicode_literals, division, absolute_import, print_function 

3 

4from .._errors import pretty_message 

5from .._ffi import buffer_from_bytes, bytes_from_buffer 

6from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error 

7from .._rand import rand_bytes 

8from .._types import type_name, byte_cls, int_types 

9 

10 

11__all__ = [ 

12 'pbkdf2', 

13 'pkcs12_kdf', 

14 'rand_bytes', 

15] 

16 

17 

18# OpenSSL 0.9.8 does not include PBKDF2 

19if libcrypto_version_info < (1,): 

20 from .._pkcs5 import pbkdf2 

21 

22else: 

23 def pbkdf2(hash_algorithm, password, salt, iterations, key_length): 

24 """ 

25 PBKDF2 from PKCS#5 

26 

27 :param hash_algorithm: 

28 The string name of the hash algorithm to use: "sha1", "sha224", "sha256", "sha384", "sha512" 

29 

30 :param password: 

31 A byte string of the password to use an input to the KDF 

32 

33 :param salt: 

34 A cryptographic random byte string 

35 

36 :param iterations: 

37 The numbers of iterations to use when deriving the key 

38 

39 :param key_length: 

40 The length of the desired key in bytes 

41 

42 :raises: 

43 ValueError - when any of the parameters contain an invalid value 

44 TypeError - when any of the parameters are of the wrong type 

45 

46 :return: 

47 The derived key as a byte string 

48 """ 

49 

50 if not isinstance(password, byte_cls): 

51 raise TypeError(pretty_message( 

52 ''' 

53 password must be a byte string, not %s 

54 ''', 

55 type_name(password) 

56 )) 

57 

58 if not isinstance(salt, byte_cls): 

59 raise TypeError(pretty_message( 

60 ''' 

61 salt must be a byte string, not %s 

62 ''', 

63 type_name(salt) 

64 )) 

65 

66 if not isinstance(iterations, int_types): 

67 raise TypeError(pretty_message( 

68 ''' 

69 iterations must be an integer, not %s 

70 ''', 

71 type_name(iterations) 

72 )) 

73 

74 if iterations < 1: 

75 raise ValueError('iterations must be greater than 0') 

76 

77 if not isinstance(key_length, int_types): 

78 raise TypeError(pretty_message( 

79 ''' 

80 key_length must be an integer, not %s 

81 ''', 

82 type_name(key_length) 

83 )) 

84 

85 if key_length < 1: 

86 raise ValueError('key_length must be greater than 0') 

87 

88 if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): 

89 raise ValueError(pretty_message( 

90 ''' 

91 hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", 

92 "sha512", not %s 

93 ''', 

94 repr(hash_algorithm) 

95 )) 

96 

97 evp_md = { 

98 'sha1': libcrypto.EVP_sha1, 

99 'sha224': libcrypto.EVP_sha224, 

100 'sha256': libcrypto.EVP_sha256, 

101 'sha384': libcrypto.EVP_sha384, 

102 'sha512': libcrypto.EVP_sha512 

103 }[hash_algorithm]() 

104 

105 output_buffer = buffer_from_bytes(key_length) 

106 result = libcrypto.PKCS5_PBKDF2_HMAC( 

107 password, 

108 len(password), 

109 salt, 

110 len(salt), 

111 iterations, 

112 evp_md, 

113 key_length, 

114 output_buffer 

115 ) 

116 handle_openssl_error(result) 

117 

118 return bytes_from_buffer(output_buffer) 

119 

120 pbkdf2.pure_python = False 

121 

122 

123def pkcs12_kdf(hash_algorithm, password, salt, iterations, key_length, id_): 

124 """ 

125 KDF from RFC7292 appendix B.2 - https://tools.ietf.org/html/rfc7292#page-19 

126 

127 :param hash_algorithm: 

128 The string name of the hash algorithm to use: "md5", "sha1", "sha224", "sha256", "sha384", "sha512" 

129 

130 :param password: 

131 A byte string of the password to use an input to the KDF 

132 

133 :param salt: 

134 A cryptographic random byte string 

135 

136 :param iterations: 

137 The numbers of iterations to use when deriving the key 

138 

139 :param key_length: 

140 The length of the desired key in bytes 

141 

142 :param id_: 

143 The ID of the usage - 1 for key, 2 for iv, 3 for mac 

144 

145 :raises: 

146 ValueError - when any of the parameters contain an invalid value 

147 TypeError - when any of the parameters are of the wrong type 

148 

149 :return: 

150 The derived key as a byte string 

151 """ 

152 

153 if not isinstance(password, byte_cls): 

154 raise TypeError(pretty_message( 

155 ''' 

156 password must be a byte string, not %s 

157 ''', 

158 type_name(password) 

159 )) 

160 

161 if not isinstance(salt, byte_cls): 

162 raise TypeError(pretty_message( 

163 ''' 

164 salt must be a byte string, not %s 

165 ''', 

166 type_name(salt) 

167 )) 

168 

169 if not isinstance(iterations, int_types): 

170 raise TypeError(pretty_message( 

171 ''' 

172 iterations must be an integer, not %s 

173 ''', 

174 type_name(iterations) 

175 )) 

176 

177 if iterations < 1: 

178 raise ValueError(pretty_message( 

179 ''' 

180 iterations must be greater than 0 - is %s 

181 ''', 

182 repr(iterations) 

183 )) 

184 

185 if not isinstance(key_length, int_types): 

186 raise TypeError(pretty_message( 

187 ''' 

188 key_length must be an integer, not %s 

189 ''', 

190 type_name(key_length) 

191 )) 

192 

193 if key_length < 1: 

194 raise ValueError(pretty_message( 

195 ''' 

196 key_length must be greater than 0 - is %s 

197 ''', 

198 repr(key_length) 

199 )) 

200 

201 if hash_algorithm not in set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']): 

202 raise ValueError(pretty_message( 

203 ''' 

204 hash_algorithm must be one of "md5", "sha1", "sha224", "sha256", 

205 "sha384", "sha512", not %s 

206 ''', 

207 repr(hash_algorithm) 

208 )) 

209 

210 if id_ not in set([1, 2, 3]): 

211 raise ValueError(pretty_message( 

212 ''' 

213 id_ must be one of 1, 2, 3, not %s 

214 ''', 

215 repr(id_) 

216 )) 

217 

218 utf16_password = password.decode('utf-8').encode('utf-16be') + b'\x00\x00' 

219 

220 digest_type = { 

221 'md5': libcrypto.EVP_md5, 

222 'sha1': libcrypto.EVP_sha1, 

223 'sha224': libcrypto.EVP_sha224, 

224 'sha256': libcrypto.EVP_sha256, 

225 'sha384': libcrypto.EVP_sha384, 

226 'sha512': libcrypto.EVP_sha512, 

227 }[hash_algorithm]() 

228 

229 output_buffer = buffer_from_bytes(key_length) 

230 result = libcrypto.PKCS12_key_gen_uni( 

231 utf16_password, 

232 len(utf16_password), 

233 salt, 

234 len(salt), 

235 id_, 

236 iterations, 

237 key_length, 

238 output_buffer, 

239 digest_type 

240 ) 

241 handle_openssl_error(result) 

242 

243 return bytes_from_buffer(output_buffer)