From 3121798f69dc8f5e9360aab01008a8d858cb1b43 Mon Sep 17 00:00:00 2001 From: valefar-on-discord <124839138+valefar-on-discord@users.noreply.github.com> Date: Sun, 5 May 2024 19:56:45 -0500 Subject: [PATCH 1/3] Can now generated keystores with PBKDF2 --- staking_deposit/cli/generate_keys.py | 9 +- staking_deposit/credentials.py | 16 ++- tests/test_cli/test_existing_mnemonic.py | 78 +++++++++++++ .../test_exit_transaction_keystore.py | 106 +++++++++++++++++- tests/test_cli/test_new_mnemonic.py | 83 ++++++++++++++ 5 files changed, 284 insertions(+), 8 deletions(-) diff --git a/staking_deposit/cli/generate_keys.py b/staking_deposit/cli/generate_keys.py index 1e5206c6..8ece1a04 100644 --- a/staking_deposit/cli/generate_keys.py +++ b/staking_deposit/cli/generate_keys.py @@ -105,6 +105,12 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[ param_decls=['--execution_address', '--eth1_withdrawal_address'], prompt=lambda: load_text(['arg_execution_address', 'prompt'], func='generate_keys_arguments_decorator'), ), + jit_option( + default=False, + is_flag=True, + param_decls='--pbkdf2', + help='Uses the pbkdf2 encryption method instead of scrypt.', + ), ] for decorator in reversed(decorators): function = decorator(function) @@ -115,7 +121,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[ @click.pass_context def generate_keys(ctx: click.Context, validator_start_index: int, num_validators: int, folder: str, chain: str, keystore_password: str, - execution_address: HexAddress, **kwargs: Any) -> None: + execution_address: HexAddress, pbkdf2: bool, **kwargs: Any) -> None: mnemonic = ctx.obj['mnemonic'] mnemonic_password = ctx.obj['mnemonic_password'] amounts = [MAX_DEPOSIT_AMOUNT] * num_validators @@ -134,6 +140,7 @@ def generate_keys(ctx: click.Context, validator_start_index: int, chain_setting=chain_setting, start_index=validator_start_index, hex_eth1_withdrawal_address=execution_address, + use_pbkdf2=pbkdf2 ) keystore_filefolders = credentials.export_keystores(password=keystore_password, folder=folder) deposits_file = credentials.export_deposit_data_json(folder=folder) diff --git a/staking_deposit/credentials.py b/staking_deposit/credentials.py index 1f59ceee..1c7a51b2 100644 --- a/staking_deposit/credentials.py +++ b/staking_deposit/credentials.py @@ -14,6 +14,7 @@ from staking_deposit.key_handling.key_derivation.path import mnemonic_and_path_to_key from staking_deposit.key_handling.keystore import ( Keystore, + Pbkdf2Keystore, ScryptKeystore, ) from staking_deposit.settings import DEPOSIT_CLI_VERSION, BaseChainSetting @@ -49,7 +50,8 @@ class Credential: """ def __init__(self, *, mnemonic: str, mnemonic_password: str, index: int, amount: int, chain_setting: BaseChainSetting, - hex_eth1_withdrawal_address: Optional[HexAddress]): + hex_eth1_withdrawal_address: Optional[HexAddress], + use_pbkdf2: Optional[bool] = False): # Set path as EIP-2334 format # https://eips.ethereum.org/EIPS/eip-2334 purpose = '12381' @@ -65,6 +67,7 @@ def __init__(self, *, mnemonic: str, mnemonic_password: str, self.amount = amount self.chain_setting = chain_setting self.hex_eth1_withdrawal_address = hex_eth1_withdrawal_address + self.use_pbkdf2 = use_pbkdf2 @property def signing_pk(self) -> bytes: @@ -149,7 +152,10 @@ def deposit_datum_dict(self) -> Dict[str, bytes]: def signing_keystore(self, password: str) -> Keystore: secret = self.signing_sk.to_bytes(32, 'big') - return ScryptKeystore.encrypt(secret=secret, password=password, path=self.signing_key_path) + if self.use_pbkdf2: + return Pbkdf2Keystore.encrypt(secret=secret, password=password, path=self.signing_key_path) + else: + return ScryptKeystore.encrypt(secret=secret, password=password, path=self.signing_key_path) def save_signing_keystore(self, password: str, folder: str) -> str: keystore = self.signing_keystore(password) @@ -240,7 +246,8 @@ def from_mnemonic(cls, amounts: List[int], chain_setting: BaseChainSetting, start_index: int, - hex_eth1_withdrawal_address: Optional[HexAddress]) -> 'CredentialList': + hex_eth1_withdrawal_address: Optional[HexAddress], + use_pbkdf2: Optional[bool] = False) -> 'CredentialList': if len(amounts) != num_keys: raise ValueError( f"The number of keys ({num_keys}) doesn't equal to the corresponding deposit amounts ({len(amounts)})." @@ -250,7 +257,8 @@ def from_mnemonic(cls, show_percent=False, show_pos=True) as indices: return cls([Credential(mnemonic=mnemonic, mnemonic_password=mnemonic_password, index=index, amount=amounts[index - start_index], chain_setting=chain_setting, - hex_eth1_withdrawal_address=hex_eth1_withdrawal_address) + hex_eth1_withdrawal_address=hex_eth1_withdrawal_address, + use_pbkdf2=use_pbkdf2) for index in indices]) def export_keystores(self, password: str, folder: str) -> List[str]: diff --git a/tests/test_cli/test_existing_mnemonic.py b/tests/test_cli/test_existing_mnemonic.py index 3a16b92d..81035ae6 100644 --- a/tests/test_cli/test_existing_mnemonic.py +++ b/tests/test_cli/test_existing_mnemonic.py @@ -165,6 +165,84 @@ def test_existing_mnemonic_eth1_address_withdrawal_bad_checksum() -> None: clean_key_folder(my_folder_path) +def test_pbkdf2_new_mnemonic() -> None: + # Prepare pbkdf2 folder + pbkdf2_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER') + clean_key_folder(pbkdf2_folder_path) + if not os.path.exists(pbkdf2_folder_path): + os.mkdir(pbkdf2_folder_path) + + # Prepare scrypt folder + scrypt_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER_2') + clean_key_folder(scrypt_folder_path) + if not os.path.exists(scrypt_folder_path): + os.mkdir(scrypt_folder_path) + + runner = CliRunner() + inputs = [ + 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about', + '0', '0', '1', 'mainnet', 'MyPassword', 'MyPassword', + ] + data = '\n'.join(inputs) + arguments = [ + '--language', 'english', + 'existing-mnemonic', + '--eth1_withdrawal_address', '', + '--folder', pbkdf2_folder_path, + '--pbkdf2', + ] + result = runner.invoke(cli, arguments, input=data) + assert result.exit_code == 0 + + arguments = [ + '--language', 'english', + 'existing-mnemonic', + '--eth1_withdrawal_address', '', + '--folder', scrypt_folder_path, + ] + result = runner.invoke(cli, arguments, input=data) + assert result.exit_code == 0 + + # Load store generated files + validator_keys_folder_path = os.path.join(pbkdf2_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME) + _, _, key_files = next(os.walk(validator_keys_folder_path)) + + deposit_file = [key_file for key_file in key_files if key_file.startswith('deposit_data')][0] + with open(validator_keys_folder_path + '/' + deposit_file, 'r', encoding='utf-8') as f: + pbkdf2_deposit_dict = json.load(f)[0] + + keystore_file = [key_file for key_file in key_files if key_file.startswith('keystore-m_')][0] + with open(validator_keys_folder_path + '/' + keystore_file, 'r', encoding='utf-8') as f: + pbkdf2_keystore_dict = json.load(f) + + validator_keys_folder_path = os.path.join(scrypt_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME) + _, _, key_files = next(os.walk(validator_keys_folder_path)) + + deposit_file = [key_file for key_file in key_files if key_file.startswith('deposit_data')][0] + with open(validator_keys_folder_path + '/' + deposit_file, 'r', encoding='utf-8') as f: + scrypt_deposit_dict = json.load(f)[0] + + keystore_file = [key_file for key_file in key_files if key_file.startswith('keystore-m_')][0] + with open(validator_keys_folder_path + '/' + keystore_file, 'r', encoding='utf-8') as f: + scrypt_keystore_dict = json.load(f) + + # Verify deposit files + assert pbkdf2_deposit_dict['withdrawal_credentials'] == scrypt_deposit_dict['withdrawal_credentials'] + assert pbkdf2_deposit_dict['pubkey'] == scrypt_deposit_dict['pubkey'] + assert pbkdf2_deposit_dict['signature'] == scrypt_deposit_dict['signature'] + assert pbkdf2_deposit_dict['deposit_message_root'] == scrypt_deposit_dict['deposit_message_root'] + assert pbkdf2_deposit_dict['deposit_data_root'] == scrypt_deposit_dict['deposit_data_root'] + + # Verify keystore files + assert pbkdf2_keystore_dict['crypto']['kdf']['function'] == 'pbkdf2' + assert scrypt_keystore_dict['crypto']['kdf']['function'] == 'scrypt' + assert pbkdf2_keystore_dict['pubkey'] == scrypt_keystore_dict['pubkey'] + + # Clean up + clean_key_folder(pbkdf2_folder_path) + clean_key_folder(scrypt_folder_path) + + @pytest.mark.asyncio async def test_script() -> None: my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER') diff --git a/tests/test_cli/test_exit_transaction_keystore.py b/tests/test_cli/test_exit_transaction_keystore.py index 0cf29775..895095ad 100644 --- a/tests/test_cli/test_exit_transaction_keystore.py +++ b/tests/test_cli/test_exit_transaction_keystore.py @@ -44,8 +44,6 @@ def test_exit_transaction_keystore() -> None: keystore_filepath = credential.save_signing_keystore(keystore_password, exit_transaction_folder_path) runner = CliRunner() - inputs = [] - data = '\n'.join(inputs) arguments = [ '--language', 'english', '--non_interactive', @@ -57,7 +55,7 @@ def test_exit_transaction_keystore() -> None: '--validator_index', '1', '--epoch', '1234', ] - result = runner.invoke(cli, arguments, input=data) + result = runner.invoke(cli, arguments) assert result.exit_code == 0 @@ -83,6 +81,108 @@ def test_exit_transaction_keystore() -> None: clean_exit_transaction_folder(my_folder_path) +def test_exit_transaction_with_pbkdf2() -> None: + # Prepare folder + pbkdf2_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER') + pbkdf2_exit_transaction_folder_path = os.path.join(pbkdf2_folder_path, DEFAULT_EXIT_TRANSACTION_FOLDER_NAME) + clean_exit_transaction_folder(pbkdf2_folder_path) + scrypt_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER2') + scrypt_exit_transaction_folder_path = os.path.join(scrypt_folder_path, DEFAULT_EXIT_TRANSACTION_FOLDER_NAME) + clean_exit_transaction_folder(pbkdf2_folder_path) + if not os.path.exists(pbkdf2_folder_path): + os.mkdir(pbkdf2_folder_path) + if not os.path.exists(scrypt_folder_path): + os.mkdir(scrypt_folder_path) + if not os.path.exists(pbkdf2_exit_transaction_folder_path): + os.mkdir(pbkdf2_exit_transaction_folder_path) + if not os.path.exists(scrypt_exit_transaction_folder_path): + os.mkdir(scrypt_exit_transaction_folder_path) + + # Shared parameters + chain = 'mainnet' + keystore_password = 'solo-stakers' + + # Prepare credential + pbkdf2_credential = Credential( + mnemonic='aban aban aban aban aban aban aban aban aban aban aban abou', + mnemonic_password='', + index=0, + amount=0, + chain_setting=get_chain_setting(chain), + hex_eth1_withdrawal_address=None, + use_pbkdf2=True, + ) + scrypt_credential = Credential( + mnemonic='aban aban aban aban aban aban aban aban aban aban aban abou', + mnemonic_password='', + index=0, + amount=0, + chain_setting=get_chain_setting(chain), + hex_eth1_withdrawal_address=None, + use_pbkdf2=False, + ) + + # Save keystore file + pbkdf2_keystore_filepath = pbkdf2_credential.save_signing_keystore( + keystore_password, + pbkdf2_exit_transaction_folder_path, + ) + scrypt_keystore_filepath = scrypt_credential.save_signing_keystore( + keystore_password, + scrypt_exit_transaction_folder_path, + ) + + runner = CliRunner() + arguments = [ + '--language', 'english', + '--non_interactive', + 'exit-transaction-keystore', + '--output_folder', pbkdf2_folder_path, + '--chain', chain, + '--keystore', pbkdf2_keystore_filepath, + '--keystore_password', keystore_password, + '--validator_index', '1', + '--epoch', '1234', + ] + result = runner.invoke(cli, arguments) + assert result.exit_code == 0 + + arguments = [ + '--language', 'english', + '--non_interactive', + 'exit-transaction-keystore', + '--output_folder', scrypt_folder_path, + '--chain', chain, + '--keystore', scrypt_keystore_filepath, + '--keystore_password', keystore_password, + '--validator_index', '1', + '--epoch', '1234', + ] + result = runner.invoke(cli, arguments) + assert result.exit_code == 0 + + # Check files + _, _, exit_transaction_files = next(os.walk(pbkdf2_exit_transaction_folder_path)) + pbkdf2_exit_transaction_file = [f for f in exit_transaction_files if 'signed_exit' in f] + assert len(set(pbkdf2_exit_transaction_file)) == 1 + pbkdf2_json_data = read_json_file(pbkdf2_exit_transaction_folder_path, pbkdf2_exit_transaction_file[0]) + + _, _, exit_transaction_files = next(os.walk(scrypt_exit_transaction_folder_path)) + scrypt_exit_transaction_file = [f for f in exit_transaction_files if 'signed_exit' in f] + assert len(set(scrypt_exit_transaction_file)) == 1 + scrypt_json_data = read_json_file(scrypt_exit_transaction_folder_path, scrypt_exit_transaction_file[0]) + + assert pbkdf2_json_data['message']['epoch'] == scrypt_json_data['message']['epoch'] + assert pbkdf2_json_data['message']['validator_index'] == scrypt_json_data['message']['validator_index'] + assert pbkdf2_json_data['signature'] == scrypt_json_data['signature'] + + verify_file_permission(os, folder_path=pbkdf2_exit_transaction_folder_path, files=pbkdf2_exit_transaction_file) + verify_file_permission(os, folder_path=scrypt_exit_transaction_folder_path, files=scrypt_exit_transaction_file) + + clean_exit_transaction_folder(pbkdf2_folder_path) + clean_exit_transaction_folder(scrypt_folder_path) + + def test_invalid_keystore_path() -> None: my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER') clean_exit_transaction_folder(my_folder_path) diff --git a/tests/test_cli/test_new_mnemonic.py b/tests/test_cli/test_new_mnemonic.py index 40b76eb9..f1ee063c 100644 --- a/tests/test_cli/test_new_mnemonic.py +++ b/tests/test_cli/test_new_mnemonic.py @@ -266,6 +266,89 @@ def mock_get_mnemonic(language, words_path, entropy=None) -> str: assert result.exit_code == 0 +def test_pbkdf2_new_mnemonic(monkeypatch) -> None: + # monkeypatch get_mnemonic + def mock_get_mnemonic(language, words_path, entropy=None) -> str: + return "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + + monkeypatch.setattr(new_mnemonic, "get_mnemonic", mock_get_mnemonic) + + # Prepare pbkdf2 folder + pbkdf2_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER') + clean_key_folder(pbkdf2_folder_path) + if not os.path.exists(pbkdf2_folder_path): + os.mkdir(pbkdf2_folder_path) + + # Prepare scrypt folder + scrypt_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER_2') + clean_key_folder(scrypt_folder_path) + if not os.path.exists(scrypt_folder_path): + os.mkdir(scrypt_folder_path) + + runner = CliRunner() + + inputs = ['english', '1', 'mainnet', 'MyPassword', 'MyPassword', + 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'] + data = '\n'.join(inputs) + arguments = [ + '--language', 'english', + 'new-mnemonic', + '--eth1_withdrawal_address', '', + '--folder', pbkdf2_folder_path, + '--pbkdf2', + ] + result = runner.invoke(cli, arguments, input=data) + assert result.exit_code == 0 + + arguments = [ + '--language', 'english', + 'new-mnemonic', + '--eth1_withdrawal_address', '', + '--folder', scrypt_folder_path, + ] + result = runner.invoke(cli, arguments, input=data) + assert result.exit_code == 0 + + # Load store generated files + validator_keys_folder_path = os.path.join(pbkdf2_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME) + _, _, key_files = next(os.walk(validator_keys_folder_path)) + + deposit_file = [key_file for key_file in key_files if key_file.startswith('deposit_data')][0] + with open(validator_keys_folder_path + '/' + deposit_file, 'r', encoding='utf-8') as f: + pbkdf2_deposit_dict = json.load(f)[0] + + keystore_file = [key_file for key_file in key_files if key_file.startswith('keystore-m_')][0] + with open(validator_keys_folder_path + '/' + keystore_file, 'r', encoding='utf-8') as f: + pbkdf2_keystore_dict = json.load(f) + + validator_keys_folder_path = os.path.join(scrypt_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME) + _, _, key_files = next(os.walk(validator_keys_folder_path)) + + deposit_file = [key_file for key_file in key_files if key_file.startswith('deposit_data')][0] + with open(validator_keys_folder_path + '/' + deposit_file, 'r', encoding='utf-8') as f: + scrypt_deposit_dict = json.load(f)[0] + + keystore_file = [key_file for key_file in key_files if key_file.startswith('keystore-m_')][0] + with open(validator_keys_folder_path + '/' + keystore_file, 'r', encoding='utf-8') as f: + scrypt_keystore_dict = json.load(f) + + # Verify deposit files + assert pbkdf2_deposit_dict['withdrawal_credentials'] == scrypt_deposit_dict['withdrawal_credentials'] + assert pbkdf2_deposit_dict['pubkey'] == scrypt_deposit_dict['pubkey'] + assert pbkdf2_deposit_dict['signature'] == scrypt_deposit_dict['signature'] + assert pbkdf2_deposit_dict['deposit_message_root'] == scrypt_deposit_dict['deposit_message_root'] + assert pbkdf2_deposit_dict['deposit_data_root'] == scrypt_deposit_dict['deposit_data_root'] + + # Verify keystore files + assert pbkdf2_keystore_dict['crypto']['kdf']['function'] == 'pbkdf2' + assert scrypt_keystore_dict['crypto']['kdf']['function'] == 'scrypt' + assert pbkdf2_keystore_dict['pubkey'] == scrypt_keystore_dict['pubkey'] + + # Clean up + clean_key_folder(pbkdf2_folder_path) + clean_key_folder(scrypt_folder_path) + + @pytest.mark.asyncio async def test_script_bls_withdrawal() -> None: # Prepare folder From 59cdf2f68cd11d9724a2ce2d8d91444cc4bd1a69 Mon Sep 17 00:00:00 2001 From: valefar-on-discord <124839138+valefar-on-discord@users.noreply.github.com> Date: Mon, 6 May 2024 16:09:21 -0500 Subject: [PATCH 2/3] Updating documentation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6aaba134..d503561c 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ You can use `new-mnemonic --help` to see all arguments. Note that if there are m | `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) | | `--chain` | String. `mainnet` by default | The chain setting for the signing domain. | | `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). | +| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | ###### `existing-mnemonic` Arguments @@ -164,6 +165,7 @@ You can use `existing-mnemonic --help` to see all arguments. Note that if there | `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) | | `--chain` | String. `mainnet` by default | The chain setting for the signing domain. | | `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). | +| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | ###### Successful message From c75123b89ee25d480c0989550841a798a932a408 Mon Sep 17 00:00:00 2001 From: valefar-on-discord <124839138+valefar-on-discord@users.noreply.github.com> Date: Thu, 9 May 2024 13:37:03 -0500 Subject: [PATCH 3/3] Will specifically mentioned keystore files with pbkdf2 option --- README.md | 4 ++-- staking_deposit/cli/generate_keys.py | 2 +- staking_deposit/intl/en/cli/generate_keys.json | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d503561c..57d5faa1 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ You can use `new-mnemonic --help` to see all arguments. Note that if there are m | `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) | | `--chain` | String. `mainnet` by default | The chain setting for the signing domain. | | `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). | -| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | +| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt for generated keystore files as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | ###### `existing-mnemonic` Arguments @@ -165,7 +165,7 @@ You can use `existing-mnemonic --help` to see all arguments. Note that if there | `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) | | `--chain` | String. `mainnet` by default | The chain setting for the signing domain. | | `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). | -| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | +| `--pbkdf2` | Flag | Will use pbkdf2 key derivation instead of scrypt for generated keystore files as defined in EIP-2335. This can be a good alternative if you intend to work with a large number of keys. | ###### Successful message diff --git a/staking_deposit/cli/generate_keys.py b/staking_deposit/cli/generate_keys.py index 8ece1a04..bbf87ff5 100644 --- a/staking_deposit/cli/generate_keys.py +++ b/staking_deposit/cli/generate_keys.py @@ -109,7 +109,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[ default=False, is_flag=True, param_decls='--pbkdf2', - help='Uses the pbkdf2 encryption method instead of scrypt.', + help=lambda: load_text(['arg_pbkdf2', 'help'], func='generate_keys_arguments_decorator'), ), ] for decorator in reversed(decorators): diff --git a/staking_deposit/intl/en/cli/generate_keys.json b/staking_deposit/intl/en/cli/generate_keys.json index 4df4388f..612009ff 100644 --- a/staking_deposit/intl/en/cli/generate_keys.json +++ b/staking_deposit/intl/en/cli/generate_keys.json @@ -22,6 +22,9 @@ "prompt": "Please enter the optional 20-byte execution address for the new withdrawal credentials. Note that you CANNOT change it once you have set it on chain.", "confirm": "Repeat your execution address for confirmation.", "mismatch": "Error: the two entered values do not match. Please type again." + }, + "arg_pbkdf2": { + "help": "Uses the pbkdf2 hashing function instead of scrypt for generated keystore files. " } }, "generate_keys": {