Last active
April 16, 2019 19:57
-
-
Save 0xpizza/96a44d810d156eedc17911b7fc34d12c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import base64 | |
import hashlib | |
class Scrypt(): | |
@staticmethod | |
def _make_bytes(pw, encoding): | |
if isinstance(pw, str): | |
try: | |
pw = pw.encode(encoding) | |
except UnicodeEncodeError as e: | |
e.args = ('Invalid string. Hashes must be ASCII and passwords should be UTF-8',) | |
raise e | |
if not isinstance(pw, bytes): | |
raise ValueError( | |
'Value must be {} or {}, not {}'\ | |
.format(repr(bytes), repr(str), type(pw)) | |
) | |
return pw | |
@staticmethod | |
def _const_time_comparison(a, b): | |
if len(a) != len(b): | |
return False | |
result = 0 | |
for j,k in zip(a,b): | |
result ^= j ^ k | |
if result == 0: | |
return True | |
else: | |
return False | |
@staticmethod | |
def hash(password, salt=None, n=17, p=1, r=8, dklen=18, encoding='UTF-8'): | |
maxmem = 0x7fffffff | |
password = Scrypt._make_bytes(password, encoding) | |
_n = 2**n | |
salt = os.urandom(18) if salt is None else salt | |
hash = hashlib.scrypt(password, salt=salt, n=_n, p=p, r=r, maxmem=maxmem, dklen=dklen) | |
salt = base64.b64encode(salt).decode() | |
hash = base64.b64encode(hash).decode() | |
PHC = f'$scrypt$n={n}$p={p}$r={r}${salt}${hash}' | |
return PHC | |
@staticmethod | |
def verify(param_string, password): | |
params = param_string.split('$')[1:] | |
salt = params[-2] | |
try: | |
params = {k:int(v) for k,v in map(lambda s: s.split('='), params[1:-2])} | |
except ValueError: | |
raise ValueError( | |
'invalid parameter string' | |
) | |
salt = base64.b64decode(salt) | |
return Scrypt._const_time_comparison( | |
Scrypt._make_bytes(Scrypt.hash(password, salt=salt, **params), 'ascii') | |
,Scrypt._make_bytes(param_string, 'ascii')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment