mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-30 08:51:32 +00:00
Merge pull request #4937 from SomberNight/revert_password_v2
keystore: revert KDF change
This commit is contained in:
commit
fa389a4e06
2 changed files with 29 additions and 34 deletions
|
@ -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")
|
||||
|
|
|
@ -11,7 +11,7 @@ from electrum.bitcoin import (public_key_to_p2pkh, address_from_private_key,
|
|||
from electrum.bip32 import (bip32_root, bip32_public_derivation, bip32_private_derivation,
|
||||
xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation,
|
||||
is_xpub, convert_bip32_path_to_list_of_uint32)
|
||||
from electrum.crypto import sha256d, KNOWN_PW_HASH_VERSIONS
|
||||
from electrum.crypto import sha256d, SUPPORTED_PW_HASH_VERSIONS
|
||||
from electrum import ecc, crypto, constants
|
||||
from electrum.ecc import number_to_string, string_to_number
|
||||
from electrum.transaction import opcodes
|
||||
|
@ -219,7 +219,7 @@ class Test_bitcoin(SequentialTestCase):
|
|||
"""Make sure AES is homomorphic."""
|
||||
payload = u'\u66f4\u7a33\u5b9a\u7684\u4ea4\u6613\u5e73\u53f0'
|
||||
password = u'secret'
|
||||
for version in KNOWN_PW_HASH_VERSIONS:
|
||||
for version in SUPPORTED_PW_HASH_VERSIONS:
|
||||
enc = crypto.pw_encode(payload, password, version=version)
|
||||
dec = crypto.pw_decode(enc, password, version=version)
|
||||
self.assertEqual(dec, payload)
|
||||
|
@ -228,7 +228,7 @@ class Test_bitcoin(SequentialTestCase):
|
|||
def test_aes_encode_without_password(self):
|
||||
"""When not passed a password, pw_encode is noop on the payload."""
|
||||
payload = u'\u66f4\u7a33\u5b9a\u7684\u4ea4\u6613\u5e73\u53f0'
|
||||
for version in KNOWN_PW_HASH_VERSIONS:
|
||||
for version in SUPPORTED_PW_HASH_VERSIONS:
|
||||
enc = crypto.pw_encode(payload, None, version=version)
|
||||
self.assertEqual(payload, enc)
|
||||
|
||||
|
@ -236,7 +236,7 @@ class Test_bitcoin(SequentialTestCase):
|
|||
def test_aes_deencode_without_password(self):
|
||||
"""When not passed a password, pw_decode is noop on the payload."""
|
||||
payload = u'\u66f4\u7a33\u5b9a\u7684\u4ea4\u6613\u5e73\u53f0'
|
||||
for version in KNOWN_PW_HASH_VERSIONS:
|
||||
for version in SUPPORTED_PW_HASH_VERSIONS:
|
||||
enc = crypto.pw_decode(payload, None, version=version)
|
||||
self.assertEqual(payload, enc)
|
||||
|
||||
|
@ -246,7 +246,7 @@ class Test_bitcoin(SequentialTestCase):
|
|||
payload = u"blah"
|
||||
password = u"uber secret"
|
||||
wrong_password = u"not the password"
|
||||
for version in KNOWN_PW_HASH_VERSIONS:
|
||||
for version in SUPPORTED_PW_HASH_VERSIONS:
|
||||
enc = crypto.pw_encode(payload, password, version=version)
|
||||
with self.assertRaises(InvalidPassword):
|
||||
crypto.pw_decode(enc, wrong_password, version=version)
|
||||
|
|
Loading…
Add table
Reference in a new issue