1
0

keystore: revert KDF change from #4838

making the KDF expensive is blocked on #4909
This commit is contained in:
SomberNight
2018-12-18 15:37:29 +01:00
parent c59ac49fea
commit 0c9a03ac54
2 changed files with 29 additions and 34 deletions

View File

@@ -116,9 +116,11 @@ def DecodeAES_bytes(secret: bytes, ciphertext: bytes) -> bytes:
return s
PW_HASH_VERSION_LATEST = 2
KNOWN_PW_HASH_VERSIONS = (1, 2)
PW_HASH_VERSION_LATEST = 1
KNOWN_PW_HASH_VERSIONS = (1, 2, )
SUPPORTED_PW_HASH_VERSIONS = (1, )
assert PW_HASH_VERSION_LATEST in KNOWN_PW_HASH_VERSIONS
assert PW_HASH_VERSION_LATEST in SUPPORTED_PW_HASH_VERSIONS
class UnexpectedPasswordHashVersion(InvalidPassword):
@@ -126,23 +128,30 @@ class UnexpectedPasswordHashVersion(InvalidPassword):
self.version = version
def __str__(self):
return "{unexpected}: {version}\n{please_update}".format(
return "{unexpected}: {version}\n{instruction}".format(
unexpected=_("Unexpected password hash version"),
version=self.version,
please_update=_('You are most likely using an outdated version of Electrum. Please update.'))
instruction=_('You are most likely using an outdated version of Electrum. Please update.'))
def _hash_password(password: Union[bytes, str], *, version: int, salt: bytes) -> bytes:
class UnsupportedPasswordHashVersion(InvalidPassword):
def __init__(self, version):
self.version = version
def __str__(self):
return "{unsupported}: {version}\n{instruction}".format(
unsupported=_("Unsupported password hash version"),
version=self.version,
instruction=f"To open this wallet, try 'git checkout password_v{self.version}'.\n"
"Alternatively, restore from seed.")
def _hash_password(password: Union[bytes, str], *, version: int) -> bytes:
pw = to_bytes(password, 'utf8')
if version not in SUPPORTED_PW_HASH_VERSIONS:
raise UnsupportedPasswordHashVersion(version)
if version == 1:
return sha256d(pw)
elif version == 2:
if not isinstance(salt, bytes) or len(salt) < 16:
raise Exception('too weak salt', salt)
return hashlib.pbkdf2_hmac(hash_name='sha256',
password=pw,
salt=b'ELECTRUM_PW_HASH_V2'+salt,
iterations=50_000)
else:
assert version not in KNOWN_PW_HASH_VERSIONS
raise UnexpectedPasswordHashVersion(version)
@@ -154,17 +163,9 @@ def pw_encode(data: str, password: Union[bytes, str, None], *, version: int) ->
if version not in KNOWN_PW_HASH_VERSIONS:
raise UnexpectedPasswordHashVersion(version)
# derive key from password
if version == 1:
salt = b''
elif version == 2:
salt = bytes(os.urandom(16))
else:
assert False, version
secret = _hash_password(password, version=version, salt=salt)
secret = _hash_password(password, version=version)
# encrypt given data
e = EncodeAES_bytes(secret, to_bytes(data, "utf8"))
# return base64(salt + encrypted data)
ciphertext = salt + e
ciphertext = EncodeAES_bytes(secret, to_bytes(data, "utf8"))
ciphertext_b64 = base64.b64encode(ciphertext)
return ciphertext_b64.decode('utf8')
@@ -176,13 +177,7 @@ def pw_decode(data: str, password: Union[bytes, str, None], *, version: int) ->
raise UnexpectedPasswordHashVersion(version)
data_bytes = bytes(base64.b64decode(data))
# derive key from password
if version == 1:
salt = b''
elif version == 2:
salt, data_bytes = data_bytes[:16], data_bytes[16:]
else:
assert False, version
secret = _hash_password(password, version=version, salt=salt)
secret = _hash_password(password, version=version)
# decrypt given data
try:
d = to_string(DecodeAES_bytes(secret, data_bytes), "utf8")