mirror of
https://gitlab.com/pulsechaincom/staking-deposit-cli.git
synced 2024-12-23 03:51:39 +00:00
Unicode support keystore passwords
This commit is contained in:
parent
4f481012d4
commit
39703588d7
@ -26,9 +26,9 @@ def get_seed(*, mnemonic: str, password: str='') -> bytes:
|
||||
"""
|
||||
Derives the seed for the pre-image root of the tree.
|
||||
"""
|
||||
mnemonic = normalize('NFKD', mnemonic)
|
||||
encoded_mnemonic = normalize('NFKD', mnemonic).encode('utf-8')
|
||||
salt = normalize('NFKD', 'mnemonic' + password).encode('utf-8')
|
||||
return PBKDF2(password=mnemonic, salt=salt, dklen=64, c=2048, prf='sha512')
|
||||
return PBKDF2(password=encoded_mnemonic, salt=salt, dklen=64, c=2048, prf='sha512')
|
||||
|
||||
|
||||
def get_languages(path: str) -> List[str]:
|
||||
|
@ -5,16 +5,21 @@ from dataclasses import (
|
||||
field as dataclass_field
|
||||
)
|
||||
import json
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from secrets import randbits
|
||||
from typing import Any, Dict, Union
|
||||
from unicodedata import normalize
|
||||
from uuid import uuid4
|
||||
|
||||
from eth2deposit.utils.crypto import (
|
||||
AES_128_CTR,
|
||||
PBKDF2,
|
||||
scrypt,
|
||||
SHA256,
|
||||
)
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from eth2deposit.utils.constants import (
|
||||
UNICODE_CONTROL_CHARS,
|
||||
)
|
||||
|
||||
hexdigits = set('0123456789abcdef')
|
||||
|
||||
@ -91,13 +96,22 @@ class Keystore(BytesDataclass):
|
||||
version = json_dict['version']
|
||||
return cls(crypto=crypto, pubkey=pubkey, path=path, uuid=uuid, version=version)
|
||||
|
||||
@staticmethod
|
||||
def _process_password(password: str) -> bytes:
|
||||
password = normalize('NFKD', password)
|
||||
password = ''.join(c for c in password if ord(c) not in UNICODE_CONTROL_CHARS)
|
||||
return password.encode('UTF-8')
|
||||
|
||||
@classmethod
|
||||
def encrypt(cls, *, secret: bytes, password: str, path: str='',
|
||||
kdf_salt: bytes=randbits(256).to_bytes(32, 'big'),
|
||||
aes_iv: bytes=randbits(128).to_bytes(16, 'big')) -> 'Keystore':
|
||||
keystore = cls()
|
||||
keystore.crypto.kdf.params['salt'] = kdf_salt
|
||||
decryption_key = keystore.kdf(password=password, **keystore.crypto.kdf.params)
|
||||
decryption_key = keystore.kdf(
|
||||
password=cls._process_password(password),
|
||||
**keystore.crypto.kdf.params
|
||||
)
|
||||
keystore.crypto.cipher.params['iv'] = aes_iv
|
||||
cipher = AES_128_CTR(key=decryption_key[:16], **keystore.crypto.cipher.params)
|
||||
keystore.crypto.cipher.message = cipher.encrypt(secret)
|
||||
@ -107,7 +121,10 @@ class Keystore(BytesDataclass):
|
||||
return keystore
|
||||
|
||||
def decrypt(self, password: str) -> bytes:
|
||||
decryption_key = self.kdf(password=password, **self.crypto.kdf.params)
|
||||
decryption_key = self.kdf(
|
||||
password=self._process_password(password),
|
||||
**self.crypto.kdf.params
|
||||
)
|
||||
assert SHA256(decryption_key[16:32] + self.crypto.cipher.message) == self.crypto.checksum.message
|
||||
cipher = AES_128_CTR(key=decryption_key[:16], **self.crypto.cipher.params)
|
||||
return cipher.decrypt(self.crypto.cipher.message)
|
||||
|
@ -13,3 +13,7 @@ MAX_DEPOSIT_AMOUNT = 2 ** 5 * 10 ** 9
|
||||
# File/folder constants
|
||||
WORD_LISTS_PATH = os.path.join('eth2deposit', 'key_handling', 'key_derivation', 'word_lists')
|
||||
DEFAULT_VALIDATOR_KEYS_FOLDER_NAME = 'validator_keys'
|
||||
|
||||
|
||||
# Sundry constants
|
||||
UNICODE_CONTROL_CHARS = list(range(0x00, 0x20)) + list(range(0x7F, 0xA0))
|
||||
|
@ -24,11 +24,10 @@ def scrypt(*, password: str, salt: str, n: int, r: int, p: int, dklen: int) -> b
|
||||
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
||||
|
||||
|
||||
def PBKDF2(*, password: str, salt: bytes, dklen: int, c: int, prf: str) -> bytes:
|
||||
def PBKDF2(*, password: bytes, salt: bytes, dklen: int, c: int, prf: str) -> bytes:
|
||||
assert('sha' in prf)
|
||||
_hash = _sha256 if 'sha256' in prf else _sha512
|
||||
password_bytes = password.encode("utf-8")
|
||||
res = _PBKDF2(password=password_bytes, salt=salt, dkLen=dklen, count=c, hmac_hash_module=_hash) # type: ignore
|
||||
res = _PBKDF2(password=password, salt=salt, dkLen=dklen, count=c, hmac_hash_module=_hash) # type: ignore
|
||||
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
||||
|
||||
|
||||
|
@ -13,18 +13,18 @@
|
||||
"checksum": {
|
||||
"function": "sha256",
|
||||
"params": {},
|
||||
"message": "18b148af8e52920318084560fd766f9d09587b4915258dec0676cba5b0da09d8"
|
||||
"message": "8a9f5d9912ed7e75ea794bc5a89bca5f193721d30868ade6f73043c6ea6febf1"
|
||||
},
|
||||
"cipher": {
|
||||
"function": "aes-128-ctr",
|
||||
"params": {
|
||||
"iv": "264daa3f303d7259501c93d997d84fe6"
|
||||
},
|
||||
"message": "a9249e0ca7315836356e4c7440361ff22b9fe71e2e2ed34fc1eb03976924ed48"
|
||||
"message": "cee03fde2af33149775b7223e7845e4fb2c8ae1792e5f99fe9ecf474cc8c16ad"
|
||||
}
|
||||
},
|
||||
"pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
|
||||
"path": "m/12381/60/3141592653589793238/4626433832795028841",
|
||||
"path": "m/12381/60/0/0",
|
||||
"uuid": "64625def-3331-4eea-ab6f-782f3ed16a83",
|
||||
"version": 4
|
||||
}
|
@ -14,18 +14,18 @@
|
||||
"checksum": {
|
||||
"function": "sha256",
|
||||
"params": {},
|
||||
"message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
|
||||
"message": "d2217fe5f3e9a1e34581ef8a78f7c9928e436d36dacc5e846690a5581e8ea484"
|
||||
},
|
||||
"cipher": {
|
||||
"function": "aes-128-ctr",
|
||||
"params": {
|
||||
"iv": "264daa3f303d7259501c93d997d84fe6"
|
||||
},
|
||||
"message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
|
||||
"message": "06ae90d55fe0a6e9c5c3bc5b170827b2e5cce3929ed3f116c2811e6366dfe20f"
|
||||
}
|
||||
},
|
||||
"pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
|
||||
"path": "m/12381/60/0/0",
|
||||
"path": "m/12381/60/3141592653/589793238",
|
||||
"uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
|
||||
"version": 4
|
||||
}
|
@ -7,7 +7,7 @@ from eth2deposit.key_handling.keystore import (
|
||||
Pbkdf2Keystore,
|
||||
)
|
||||
|
||||
test_vector_password = 'testpassword'
|
||||
test_vector_password = '𝔱𝔢𝔰𝔱𝔭𝔞𝔰𝔰𝔴𝔬𝔯𝔡🔑'
|
||||
test_vector_secret = bytes.fromhex('000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f')
|
||||
test_vector_folder = os.path.join(os.getcwd(), 'tests', 'test_key_handling', 'keystore_test_vectors')
|
||||
_, _, test_vector_files = next(os.walk(test_vector_folder)) # type: ignore
|
||||
|
Loading…
Reference in New Issue
Block a user