Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PyNaCl-1.6.0.dev1-py3.11-linux-x86_64.egg/nacl/pwhash/scrypt.py: 89%

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

38 statements  

1# Copyright 2013 Donald Stufft and individual contributors 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14from typing import cast 

15 

16import nacl.bindings 

17import nacl.encoding 

18from nacl import exceptions as exc 

19from nacl.exceptions import ensure 

20 

21_strbytes_plus_one = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES 

22 

23AVAILABLE = nacl.bindings.has_crypto_pwhash_scryptsalsa208sha256 

24 

25STRPREFIX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRPREFIX 

26 

27SALTBYTES = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_SALTBYTES 

28 

29PASSWD_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN 

30PASSWD_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX 

31 

32PWHASH_SIZE = _strbytes_plus_one - 1 

33 

34BYTES_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN 

35BYTES_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX 

36 

37MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN 

38MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX 

39OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN 

40OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX 

41 

42OPSLIMIT_INTERACTIVE = ( 

43 nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 

44) 

45MEMLIMIT_INTERACTIVE = ( 

46 nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 

47) 

48OPSLIMIT_SENSITIVE = ( 

49 nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 

50) 

51MEMLIMIT_SENSITIVE = ( 

52 nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 

53) 

54 

55OPSLIMIT_MODERATE = 8 * OPSLIMIT_INTERACTIVE 

56MEMLIMIT_MODERATE = 8 * MEMLIMIT_INTERACTIVE 

57 

58 

59def kdf( 

60 size: int, 

61 password: bytes, 

62 salt: bytes, 

63 opslimit: int = OPSLIMIT_SENSITIVE, 

64 memlimit: int = MEMLIMIT_SENSITIVE, 

65 encoder: nacl.encoding.Encoder = nacl.encoding.RawEncoder, 

66) -> bytes: 

67 """ 

68 Derive a ``size`` bytes long key from a caller-supplied 

69 ``password`` and ``salt`` pair using the scryptsalsa208sha256 

70 memory-hard construct. 

71 

72 

73 the enclosing module provides the constants 

74 

75 - :py:const:`.OPSLIMIT_INTERACTIVE` 

76 - :py:const:`.MEMLIMIT_INTERACTIVE` 

77 - :py:const:`.OPSLIMIT_SENSITIVE` 

78 - :py:const:`.MEMLIMIT_SENSITIVE` 

79 - :py:const:`.OPSLIMIT_MODERATE` 

80 - :py:const:`.MEMLIMIT_MODERATE` 

81 

82 as a guidance for correct settings respectively for the 

83 interactive login and the long term key protecting sensitive data 

84 use cases. 

85 

86 :param size: derived key size, must be between 

87 :py:const:`.BYTES_MIN` and 

88 :py:const:`.BYTES_MAX` 

89 :type size: int 

90 :param password: password used to seed the key derivation procedure; 

91 it length must be between 

92 :py:const:`.PASSWD_MIN` and 

93 :py:const:`.PASSWD_MAX` 

94 :type password: bytes 

95 :param salt: **RANDOM** salt used in the key derivation procedure; 

96 its length must be exactly :py:const:`.SALTBYTES` 

97 :type salt: bytes 

98 :param opslimit: the time component (operation count) 

99 of the key derivation procedure's computational cost; 

100 it must be between 

101 :py:const:`.OPSLIMIT_MIN` and 

102 :py:const:`.OPSLIMIT_MAX` 

103 :type opslimit: int 

104 :param memlimit: the memory occupation component 

105 of the key derivation procedure's computational cost; 

106 it must be between 

107 :py:const:`.MEMLIMIT_MIN` and 

108 :py:const:`.MEMLIMIT_MAX` 

109 :type memlimit: int 

110 :rtype: bytes 

111 :raises nacl.exceptions.UnavailableError: If called when using a 

112 minimal build of libsodium. 

113 

114 .. versionadded:: 1.2 

115 """ 

116 ensure( 

117 AVAILABLE, 

118 "Not available in minimal build", 

119 raising=exc.UnavailableError, 

120 ) 

121 

122 ensure( 

123 len(salt) == SALTBYTES, 

124 "The salt must be exactly %s, not %s bytes long" 

125 % (SALTBYTES, len(salt)), 

126 raising=exc.ValueError, 

127 ) 

128 

129 n_log2, r, p = nacl.bindings.nacl_bindings_pick_scrypt_params( 

130 opslimit, memlimit 

131 ) 

132 maxmem = memlimit + (2**16) 

133 

134 return encoder.encode( 

135 nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll( 

136 password, 

137 salt, 

138 # Cast safety: n_log2 is a positive integer, and so 2 ** n_log2 is also 

139 # a positive integer. Mypy+typeshed can't deduce this, because there's no 

140 # way to for them to know that n_log2: int is positive. 

141 cast(int, 2**n_log2), 

142 r, 

143 p, 

144 maxmem=maxmem, 

145 dklen=size, 

146 ) 

147 ) 

148 

149 

150def str( 

151 password: bytes, 

152 opslimit: int = OPSLIMIT_INTERACTIVE, 

153 memlimit: int = MEMLIMIT_INTERACTIVE, 

154) -> bytes: 

155 """ 

156 Hashes a password with a random salt, using the memory-hard 

157 scryptsalsa208sha256 construct and returning an ascii string 

158 that has all the needed info to check against a future password 

159 

160 The default settings for opslimit and memlimit are those deemed 

161 correct for the interactive user login case. 

162 

163 :param bytes password: 

164 :param int opslimit: 

165 :param int memlimit: 

166 :rtype: bytes 

167 :raises nacl.exceptions.UnavailableError: If called when using a 

168 minimal build of libsodium. 

169 

170 .. versionadded:: 1.2 

171 """ 

172 ensure( 

173 AVAILABLE, 

174 "Not available in minimal build", 

175 raising=exc.UnavailableError, 

176 ) 

177 

178 return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str( 

179 password, opslimit, memlimit 

180 ) 

181 

182 

183def verify(password_hash: bytes, password: bytes) -> bool: 

184 """ 

185 Takes the output of scryptsalsa208sha256 and compares it against 

186 a user provided password to see if they are the same 

187 

188 :param password_hash: bytes 

189 :param password: bytes 

190 :rtype: boolean 

191 :raises nacl.exceptions.UnavailableError: If called when using a 

192 minimal build of libsodium. 

193 

194 .. versionadded:: 1.2 

195 """ 

196 ensure( 

197 AVAILABLE, 

198 "Not available in minimal build", 

199 raising=exc.UnavailableError, 

200 ) 

201 

202 ensure( 

203 len(password_hash) == PWHASH_SIZE, 

204 "The password hash must be exactly %s bytes long" 

205 % nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES, 

206 raising=exc.ValueError, 

207 ) 

208 

209 return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str_verify( 

210 password_hash, password 

211 )