# Assign a Regular Key Pair This tutorial shows how to authorize a secondary key pair, called a *[regular key pair](/es-es/docs/concepts/accounts/cryptographic-keys)*, to sign future transactions. Unlike the master key pair, which is mathematically linked to the account's address, you can remove or replace the regular key pair, which is better for security. You can use these steps to assign a regular key pair for the first time or to replace an existing regular key pair with a new one. You can use this same process for key rotation as a proactive security measure. ## Goals By following this tutorial, you should learn how to: - Securely generate a regular key pair and attach it to your account. - Submit transactions using a regular key pair. - Check a transaction to see if the key that was used to sign it matches a known key pair. ## Prerequisites To complete this tutorial, you should: - Have a basic understanding of the XRP Ledger. - Have an [XRP Ledger client library](/es-es/docs/references/client-libraries), such as **xrpl.js**, installed. - Have a basic understanding of [Cryptographic Keys](/es-es/docs/concepts/accounts/cryptographic-keys). ## Source Code You can find the complete source code for this tutorial's examples in the code samples section of this website's repository. ## Steps ### 1. Install dependencies JavaScript From the code sample folder, use `npm` to install dependencies: ```sh npm i ``` Python From the code sample folder, set up a virtual environment and use `pip` to install dependencies: ```sh python -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ### 2. Connect and get account(s) To get started, import the client library and instantiate an API client. For this tutorial, you need one account, which the sample code funds using the Testnet faucet; you could also use an existing account. JavaScript import xrpl from 'xrpl' const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233') await client.connect() console.log('Funding new wallet from faucet...') const { wallet } = await client.fundWallet() console.log(`Funded. Master key pair: Address: ${wallet.address} Seed: ${wallet.seed} `) Python import json from xrpl.clients import JsonRpcClient from xrpl.wallet import generate_faucet_wallet, Wallet from xrpl.models.transactions import SetRegularKey, AccountSet from xrpl.transaction import submit_and_wait client = JsonRpcClient("https://s.altnet.rippletest.net:51234") print("Funding new wallet from faucet...") wallet = generate_faucet_wallet(client) print(f"""Funded. Master key pair: Address: {wallet.address} Seed: {wallet.seed} """) ### 3. Generate a key pair Next, generate a key pair to use as the regular key pair. This is the same data type as a master key pair, so you can generate it the same way. Warning It's important to generate and store the key pair securely; otherwise, it may be possible for malicious actors to gain access to your account and take your money. Common errors include: - Getting your secret key from a remote machine, or otherwise sending your secret key in plain text over the internet. - Generating a key pair using a compromised software library. - Generating a key pair from a passphrase or other secret value that does not have enough entropy. JavaScript Use the [`Wallet.generate()` class method](https://js.xrpl.org/classes/Wallet.html#generate) to generate a key pair locally on your machine. // Generate a new key pair to use as the regular key --------------------------- const algorithm = 'ed25519' const regularKeyPair = xrpl.Wallet.generate(algorithm) console.log(`Generated regular key pair: Address: ${regularKeyPair.address} Seed: ${regularKeyPair.seed} Algorithm: ${algorithm} `) Python Use the [`Wallet.create()` class method](https://xrpl-py.readthedocs.io/en/stable/source/xrpl.wallet.html#xrpl.wallet.Wallet.create) to generate a key pair locally on your machine. # Generate a new key pair to use as the regular key ---------------------------- algorithm = "ed25519" regular_key_pair = Wallet.create(algorithm=algorithm) print(f"""Generated regular key pair: Address: {regular_key_pair.address} Seed: {regular_key_pair.seed} Algorithm: {algorithm} """) ### 4. Send a SetRegularKey transaction Use a [SetRegularKey transaction](/docs/references/protocol/transactions/types/setregularkey) to assign the new key pair to your account as a regular key pair. This example signs the transaction using the master key pair, but you could also use an existing regular key pair, or a [multi-signing list](/es-es/docs/concepts/accounts/multi-signing) if your account has multi-signing set up. JavaScript // Send SetRegularKey transaction ---------------------------------------------- const regularKeyTx = { TransactionType: 'SetRegularKey', Account: wallet.address, RegularKey: regularKeyPair.address } xrpl.validate(regularKeyTx) console.log('Signing and submitting the SetRegularKey transaction:', JSON.stringify(regularKeyTx, null, 2)) const response = await client.submitAndWait(regularKeyTx, { wallet, autofill: true }) // Check result of the SetRegularKey transaction ------------------------------- console.log(JSON.stringify(response.result, null, 2)) const setRegularKeyResultCode = response.result.meta.TransactionResult if (setRegularKeyResultCode === 'tesSUCCESS') { console.log('Regular Key set successfully.') } else { console.error(`SetRegularKey failed with code ${setRegularKeyResultCode}.`) client.disconnect() process.exit(1) } Python # Send SetRegularKey transaction ----------------------------------------------- regular_key_tx = SetRegularKey( account=wallet.address, regular_key=regular_key_pair.address ) print( "Signing and submitting the SetRegularKey transaction:", json.dumps(regular_key_tx.to_xrpl(), indent=2), ) try: response = submit_and_wait(regular_key_tx, client, wallet) except err: print("Submitting SetRegularKey transaction failed with error", err) exit(1) # Check result of the SetRegularKey transaction -------------------------------- print(json.dumps(response.result, indent=2)) set_regular_key_result_code = response.result["meta"]["TransactionResult"] if set_regular_key_result_code == "tesSUCCESS": print("Regular Key set successfully.") else: print(f"SetRegularKey failed with code {set_regular_key_result_code}.") exit(1) ### 5. Send a test transaction using the regular key After the SetRegularKey transaction succeeds, the regular key pair is assigned to your account and you should be able to send transactions using the regular key pair. **To avoid losing control of your account**, it is important that you test your regular key before you take any additional steps such as [disabling the master key pair](/es-es/docs/tutorials/best-practices/key-management/disable-master-key-pair). If you make a mistake and lose access to your account, no one can restore it for you. To test the key, send any type of transaction, signing it using the regular key pair. The sample code sends an [AccountSet transaction](/docs/references/protocol/transactions/types/accountset) with no parameters, which is a "no-op" that does nothing besides use a sequence number and burn the transaction cost. JavaScript // Send a test transaction using the regular key ------------------------------- const testTx = { TransactionType: 'AccountSet', Account: wallet.address } xrpl.validate(testTx) console.log('Signing and submitting the test transaction using the regular key') const testResponse = await client.submitAndWait(testTx, { wallet: regularKeyPair, // IMPORTANT: use the regular key pair here autofill: true }) Python # Send a test transaction using the regular key -------------------------------- test_tx = AccountSet(account=wallet.address) print("Signing and submitting the test transaction using the regular key") try: test_response = submit_and_wait( test_tx, client, regular_key_pair # IMPORTANT: use regular key pair here ) except err: print("Submitting test transaction failed with error", err) exit(1) ### 6. Confirm that the test transaction succeeded as expected If the test transaction succeeds, your regular key pair works as expected. For further confirmation, you can look at the `SigningPubKey` field which is automatically added to a transaction during signing; this field contains the *public key* of the key pair that was used to sign the transaction, and is what the network uses to validate the transaction signature. When you use your regular key pair to sign a transaction, the `SigningPubKey` field contains the public key from your regular key pair. JavaScript // Check result of the test transaction ---------------------------------------- console.log(JSON.stringify(testResponse.result, null, 2)) const testResultCode = testResponse.result.meta.TransactionResult const testSigningPubKey = testResponse.result.tx_json.SigningPubKey if (testResultCode === 'tesSUCCESS') { console.log('Test transaction was successful.') } else { console.log(`Test transaction failed with code ${testResultCode}`) } if (testSigningPubKey === regularKeyPair.publicKey) { console.log('This transaction was signed with the regular key pair.') } else if (testSigningPubKey === wallet.publicKey) { console.warn('This transaction was signed with the master key pair.') } else { console.warn(`Unexpected signing key mismatch. Regular key: ${regularKeyPair.publicKey} Key used: ${testSigningPubKey}`) } client.disconnect() Python # Check result of the test transaction ----------------------------------------- print(json.dumps(test_response.result, indent=2)) test_result_code = test_response.result["meta"]["TransactionResult"] test_signing_pub_key = test_response.result["tx_json"]["SigningPubKey"] if test_result_code == "tesSUCCESS": print("Test transaction was successful.") else: print(f"Test transaction failed with code {test_result_code}") if test_signing_pub_key == regular_key_pair.public_key: print("This transaction was signed with the regular key pair.") elif test_signing_pub_key == wallet.public_key: print("This transaction was signed with the master key pair.") else: print(f"""Unexpected signing key mismatch. Regular key: {regular_key_pair.public_key} Key used: {test_signing_pub_key}""") If the transaction fails with the following [result codes](/es-es/docs/references/protocol/transactions/transaction-results), here are some things to check: - **`tefBAD_AUTH`**: The regular key you signed your test transaction with doesn't match the regular key you set in the previous step. Check that the secret and address for your regular key pair match and double-check which values you used in each step. - **`tefBAD_AUTH_MASTER`** or **`temBAD_AUTH_MASTER`**: Your account doesn't have a regular key assigned. Check that the SetRegularKey transaction executed successfully. You can also use the [account_info method](/docs/references/http-websocket-apis/public-api-methods/account-methods/account_info) to confirm that your regular key is set in the `RegularKey` field as expected. For possible causes of other result codes, see [Transaction Results](/es-es/docs/references/protocol/transactions/transaction-results). ## See Also Now that you're familiar with the benefits of assigning a regular key pair to an account, consider taking a look at these related topics and tutorials: - **Concepts:** - [Cryptographic Keys](/es-es/docs/concepts/accounts/cryptographic-keys) - [Multi-Signing](/es-es/docs/concepts/accounts/multi-signing) - [Issuing and Operational Addresses](/es-es/docs/concepts/accounts/account-types) - **Tutorials:** - [Remove a Regular Key Pair](/es-es/docs/tutorials/best-practices/key-management/remove-a-regular-key-pair) - [Set Up Multi-Signing](/es-es/docs/tutorials/best-practices/key-management/set-up-multi-signing) - [List XRP as an Exchange](/es-es/docs/use-cases/defi/list-xrp-as-an-exchange) - **References:** - [wallet_propose method](/docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose) - [sign method](/docs/references/http-websocket-apis/admin-api-methods/signing-methods/sign) - [SetRegularKey transaction](/docs/references/protocol/transactions/types/setregularkey) - [AccountRoot object](/es-es/docs/references/protocol/ledger-data/ledger-entry-types/accountroot) where the regular key is stored in the field `RegularKey`