Utilities/crypto/py3PBKDF2.py

changeset 5604
b047181a4a33
parent 5389
9b1c800daff3
child 6048
82ad8ec9548c
equal deleted inserted replaced
5603:4f2dd0850803 5604:b047181a4a33
34 @param salt salt value (bytes) 34 @param salt salt value (bytes)
35 @param iterations number of times hash function should be applied (integer) 35 @param iterations number of times hash function should be applied (integer)
36 @param digestMod hash function 36 @param digestMod hash function
37 @return hashed password (bytes) 37 @return hashed password (bytes)
38 """ 38 """
39 hash = password 39 pwHash = password
40 for i in range(iterations): 40 for i in range(iterations):
41 hash = hmac.new(salt, hash, digestMod).digest() 41 pwHash = hmac.new(salt, pwHash, digestMod).digest()
42 return hash 42 return pwHash
43 43
44 44
45 def hashPasswordTuple(password, digestMod=hashlib.sha512, iterations=10000, 45 def hashPasswordTuple(password, digestMod=hashlib.sha512, iterations=10000,
46 saltSize=32): 46 saltSize=32):
47 """ 47 """
54 @return tuple of digestname (string), number of iterations (integer), 54 @return tuple of digestname (string), number of iterations (integer),
55 salt (bytes) and hashed password (bytes) 55 salt (bytes) and hashed password (bytes)
56 """ 56 """
57 salt = os.urandom(saltSize) 57 salt = os.urandom(saltSize)
58 password = password.encode("utf-8") 58 password = password.encode("utf-8")
59 hash = pbkdf2(password, salt, iterations, digestMod) 59 pwHash = pbkdf2(password, salt, iterations, digestMod)
60 digestname = digestMod.__name__.replace("openssl_", "") 60 digestname = digestMod.__name__.replace("openssl_", "")
61 return digestname, iterations, salt, hash 61 return digestname, iterations, salt, pwHash
62 62
63 63
64 def hashPassword(password, digestMod=hashlib.sha512, iterations=10000, 64 def hashPassword(password, digestMod=hashlib.sha512, iterations=10000,
65 saltSize=32): 65 saltSize=32):
66 """ 66 """
70 @param digestMod hash function 70 @param digestMod hash function
71 @param iterations number of times hash function should be applied (integer) 71 @param iterations number of times hash function should be applied (integer)
72 @param saltSize size of the salt (integer) 72 @param saltSize size of the salt (integer)
73 @return hashed password entry according to PBKDF2 specification (string) 73 @return hashed password entry according to PBKDF2 specification (string)
74 """ 74 """
75 digestname, iterations, salt, hash = \ 75 digestname, iterations, salt, pwHash = \
76 hashPasswordTuple(password, digestMod, iterations, saltSize) 76 hashPasswordTuple(password, digestMod, iterations, saltSize)
77 return Delimiter.join([ 77 return Delimiter.join([
78 digestname, 78 digestname,
79 str(iterations), 79 str(iterations),
80 base64.b64encode(salt).decode("ascii"), 80 base64.b64encode(salt).decode("ascii"),
81 base64.b64encode(hash).decode("ascii") 81 base64.b64encode(pwHash).decode("ascii")
82 ]) 82 ])
83 83
84 84
85 def verifyPassword(password, hash): 85 def verifyPassword(password, pwHash):
86 """ 86 """
87 Module function to verify a password against a hash encoded password. 87 Module function to verify a password against a hash encoded password.
88 88
89 @param password clear text password (string) 89 @param password clear text password (string)
90 @param hash hash encoded password in the form 90 @param pwHash hash encoded password in the form
91 'digestmod$iterations$salt$hashed_password' as produced by the 91 'digestmod$iterations$salt$hashed_password' as produced by the
92 hashPassword function (string) 92 hashPassword function (string)
93 @return flag indicating a successfull verification (boolean) 93 @return flag indicating a successfull verification (boolean)
94 @exception ValueError the hash is not of the expected format or the 94 @exception ValueError the hash is not of the expected format or the
95 digest is not one of the known ones 95 digest is not one of the known ones
96 """ 96 """
97 try: 97 try:
98 digestname, iterations, salt, pwHash = hash.split(Delimiter) 98 digestname, iterations, salt, pwHash = pwHash.split(Delimiter)
99 except ValueError: 99 except ValueError:
100 raise ValueError( 100 raise ValueError(
101 "Expected hash encoded password in format " 101 "Expected hash encoded password in format "
102 "'digestmod{0}iterations{0}salt{0}hashed_password" 102 "'digestmod{0}iterations{0}salt{0}hashed_password"
103 .format(Delimiter)) 103 .format(Delimiter))
104 104
105 if digestname not in Hashes.keys(): 105 if digestname not in Hashes.keys():
106 raise ValueError( 106 raise ValueError(
107 "Unsupported hash algorithm '{0}' for hash encoded password '{1}'." 107 "Unsupported hash algorithm '{0}' for hash encoded password '{1}'."
108 .format(digestname, hash)) 108 .format(digestname, pwHash))
109 109
110 iterations = int(iterations) 110 iterations = int(iterations)
111 salt = base64.b64decode(salt.encode("ascii")) 111 salt = base64.b64decode(salt.encode("ascii"))
112 pwHash = base64.b64decode(pwHash.encode("ascii")) 112 pwHash = base64.b64decode(pwHash.encode("ascii"))
113 password = password.encode("utf-8") 113 password = password.encode("utf-8")
133 "'digestmod{0}iterations{0}salt".format(Delimiter)) 133 "'digestmod{0}iterations{0}salt".format(Delimiter))
134 134
135 if digestname not in Hashes.keys(): 135 if digestname not in Hashes.keys():
136 raise ValueError( 136 raise ValueError(
137 "Unsupported hash algorithm '{0}' for hash parameters '{1}'." 137 "Unsupported hash algorithm '{0}' for hash parameters '{1}'."
138 .format(digestname, hash)) 138 .format(digestname, hashParameters))
139 139
140 iterations = int(iterations) 140 iterations = int(iterations)
141 salt = base64.b64decode(salt.encode("ascii")) 141 salt = base64.b64decode(salt.encode("ascii"))
142 password = password.encode("utf-8") 142 password = password.encode("utf-8")
143 return pbkdf2(password, salt, iterations, Hashes[digestname]) 143 return pbkdf2(password, salt, iterations, Hashes[digestname])

eric ide

mercurial