""" Passlib module to understand hashed password format of Werkzeug
"""
__version__ = ' 0.1.0 '
from base64 import b64encode
from passlib . crypto . digest import pbkdf2_hmac
from passlib . exc import InvalidHashError
from passlib . registry import register_crypt_handler_path
import passlib . utils . handlers as uh
from passlib . utils . binary import AB64_CHARS , ab64_decode , ab64_encode
from passlib . utils . compat import u
SALT_CHARS = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "
class werkzeug_pbkdf2_sha256 ( uh . HasSalt , uh . HasRounds , uh . GenericHandler ) :
# pylint: disable=invalid-name
""" Passlib handler for Werkzeug’s PBKDF2:SHA-256 passwords
"""
checksum_chars = ' 0123456789abcdef '
checksum_size = 64
default_rounds = 150000
default_salt_chars = SALT_CHARS
default_salt_size = 8
_digest = ' sha256 '
ident = u ( ' pbkdf2:sha256 ' )
min_salt_size = 1
name = ' werkzeug_pbkdf2_sha256 '
salt_chars = SALT_CHARS
# pylint: disable=arguments-differ
@classmethod
def from_string ( cls , password_hash , * * context ) :
""" Create a new hash object from a string
"""
try :
full_method , salt , checksum = password_hash . split ( ' $ ' )
except ValueError as exc :
raise InvalidHashError ( cls ) from exc
method , digest , rounds = full_method . split ( ' : ' )
if ' : ' . join ( ( method , digest ) ) != cls . ident :
raise InvalidHashError ( cls )
if checksum :
bytes . fromhex ( checksum )
return cls ( salt = salt , checksum = checksum , rounds = int ( rounds ) )
def to_string ( self ) :
full_method = ' : ' . join ( ( self . ident , str ( self . rounds ) ) )
return ' $ ' . join ( ( full_method , self . salt , self . checksum ) )
def _calc_checksum ( self , secret ) :
checksum = pbkdf2_hmac ( self . _digest , secret , self . salt , self . rounds )
return checksum . hex ( )
register_crypt_handler_path ( ' werkzeug_pbkdf2_sha256 ' , ' passlib_werkzeug ' )