Skip to content
🎉 Welcome to the new Aptos Docs preview! Click here to submit feedback!
Build
Advanced Guides
Account Key Rotation

Account Key Rotation

Aptos Move accounts have a public address, an authentication key, a public key, and a private key. The public address is permanent, always matching the account’s initial authentication key.

The Aptos account model facilitates the unique ability to rotate an account’s private key. Since an account’s address is the initial authentication key, the ability to sign for an account can be transferred to another private key without changing its public address.

In this guide, we show examples of how to rotate an account’s authentication key using the CLI and few of the various Aptos SDKs.

Here are the installation links for the SDKs we will cover in this example:

⚠️

Some of the following examples use private keys. Do not share your private keys with anyone.

Aptos CLI

Initialize devnet profiles

Run the following to initialize test profiles. Leave the inputs blank each time you’re prompted for a private key.

Terminal
aptos init --profile test-profile-1 --network devnet --assume-yes
aptos init --profile test-profile-2 --network devnet --assume-yes
aptos init --profile test-profile-3 --network devnet --assume-yes

Get private key

To view test-profile-2 with its private key hidden:

Terminal
aptos config show-profiles --profile test-profile-2

To show the profile’s private key:

Terminal
aptos config show-private-key --profile test-profile-2
🧠

If your machine has jq, a lightweight and flexible command-line JSON processor, you can pipe the private key directly into an environment variable:

Terminal
export TEST_PROFILE_2_PRIVATE_KEY=$(
    aptos config show-private-key --profile test-profile-2 \
        | jq -r '.Result'
)
echo $TEST_PROFILE_2_PRIVATE_KEY

Otherwise, manually copy and paste:

Terminal
export TEST_PROFILE_2_PRIVATE_KEY=0x...

Rotate authentication key

Rotate the account address associated with test-profile-1 to authenticate via the private key from test-profile-2 private key:

Terminal
aptos account rotate-key \
    --new-private-key $TEST_PROFILE_2_PRIVATE_KEY \
    --profile test-profile-1 \
    --save-to-profile test-profile-1-rotated

Once the transaction completes, compare the profiles:

Terminal
aptos config show-profiles --profile test-profile-1
aptos config show-profiles --profile test-profile-1-rotated
aptos config show-profiles --profile test-profile-2

Note that test-profile-1 has a different public key from test-profile-1-rotated, which has the same public key as test-profile-2. This is because test-profile-1 is an outdated representation of the account that is now accurately represented by test-profile-1-rotated, which is authenticated via the same private key as test-profile-2.

🧠

If your machine has jq, you can easily compare the public keys via:

Terminal
export PROFILE_1_PUB_KEY=$(
    aptos config show-profiles --profile test-profile-1 \
        | jq -r '.Result["test-profile-1"].public_key'
)
export PROFILE_1_ROTATED_PUB_KEY=$(
    aptos config show-profiles --profile test-profile-1-rotated \
        | jq -r '.Result["test-profile-1-rotated"].public_key'
)
export PROFILE_2_PUB_KEY=$(
    aptos config show-profiles --profile test-profile-2 \
        | jq -r '.Result["test-profile-2"].public_key'
)
echo $PROFILE_1_PUB_KEY
echo $PROFILE_1_ROTATED_PUB_KEY
echo $PROFILE_2_PUB_KEY

Compare authentication keys listed onchain

First you’ll need to get the account addresses. Note that test-profile-1 and test-profile-1-rotated have the same account address.

🧠

If your machine has jq, you can easily store account addresses via the following:

Terminal
export TEST_ADDRESS_1=$(
    aptos config show-profiles --profile test-profile-1 \
        | jq -r '.Result["test-profile-1"].account'
)
export TEST_ADDRESS_2=$(
    aptos config show-profiles --profile test-profile-2 \
        | jq -r '.Result["test-profile-2"].account'
)
echo $TEST_ADDRESS_1
echo $TEST_ADDRESS_2

Otherwise, you’ll need to re-run the show-profiles commands from the last step and manually copy the addresses:

Terminal
export TEST_ADDRESS_1=0x...
export TEST_ADDRESS_2=0x...

To view the authentication keys of the two accounts onchain:

Terminal
aptos move view \
    --args address:0x$TEST_ADDRESS_1 \
    --function-id 0x1::account::get_authentication_key \
    --profile test-profile-1
aptos move view \
    --args address:0x$TEST_ADDRESS_2 \
    --function-id 0x1::account::get_authentication_key \
    --profile test-profile-1

Note that --profile test-profile-1 is repeated across both calls since in this case the profile is only used to specify the REST URL for the query.

Inspect lookup addresses

The onchain originating address table is a reverse lookup table that maps from an authentication key to an account address.

The originating address table is only updated upon key rotation, and maps from an authentication key to at most one account address, which means that theoretically a given private key can authenticate up to two accounts at the same time:

  1. The account address derived from the private key during standard account generation, assuming the account has not undergone any key rotations (test-profile-2).
  2. A second arbitrary address, which has had its authentication key rotated to the given private key (test-profile-1-rotated).

The command aptos account lookup-address checks if a there is an entry in the originating address table for a given private key, and if so, returns the reverse lookup address. If not, it simply returns the account address derived from the private key, hence the following commands all return TEST_ADDRESS_1:

Terminal
aptos account lookup-address --profile test-profile-1
aptos account lookup-address --profile test-profile-2
aptos account lookup-address --profile test-profile-1-rotated
Terminal
echo $TEST_ADDRESS_1

This is because the private key in test-profile-1 doesn’t have a corresponding authentication key entry in the originating address able, while the private key that authenticates both test-profile-2 and test-profile-1-rotated does have a corresponding entry, which maps to TEST_ADDRESS_1 due to the key rotation.

Attempt invalid rotations

Since the private key that authenticates test-profile-2 and test-profile-1-rotated is now in the originating address table, it is not possible to perform a key rotation operation that rotates either to or from the corresponding authentication key.

For example, test-profile-2 may not be rotated to authenticate with the private key of test-profile-1:

🧠

If your machine has jq, you can pipe the private key of test-profile-1 directly into an environment variable:

Terminal
export TEST_PROFILE_1_PRIVATE_KEY=$(
    aptos config show-private-key --profile test-profile-1 \
        | jq -r '.Result'
)
echo $TEST_PROFILE_1_PRIVATE_KEY

Otherwise, manually copy and paste:

Terminal
aptos config show-private-key --profile test-profile-1
Terminal
export TEST_PROFILE_1_PRIVATE_KEY=0x...

Attempt an invalid rotation from TEST_ADDRESS_2, which is authenticated by the private key that also authenticates TEST_ADDRESS_1:

Terminal
aptos account rotate-key \
    --new-private-key $TEST_PROFILE_1_PRIVATE_KEY \
    --profile test-profile-2 \
    --save-to-profile test-profile-2-rotated

This command fails because the underlying Move logic for key rotation expects that the originating address table maps from the given authentication key to the address that is rotating its authentication key, which is not the case here (because the table was initialized with an entry mapping to TEST_ADDRESS_1, not TEST_ADDRESS_2):

Similarly, it is not possible to rotate a different account address to the private key that authenticates test-profile-2 and test-profile-1-rotated.

Terminal
aptos account rotate-key \
    --new-private-key $TEST_PROFILE_2_PRIVATE_KEY \
    --profile test-profile-3 \
    --save-to-profile test-profile-3-rotated

Hence it is best practice to only authenticate one account with a given private key at a time.

Delete the test profiles

Terminal
aptos config delete-profile --profile test-profile-1
aptos config delete-profile --profile test-profile-2
aptos config delete-profile --profile test-profile-1-rotated
aptos config delete-profile --profile test-profile-3

TypeScript

This program creates two accounts on devnet, Alice and Bob, funds them, then rotates the Alice’s authentication key to that of Bob’s.

View the full example for this code here.

The function to rotate is very simple:

Commands to run the example script:

Navigate to the typescript SDK directory, install dependencies and run

rotate_key.ts

Terminal
cd ~/aptos-core/ecosystem/typescript/sdk/examples/typescript-esm
pnpm install && pnpm rotate_key

rotate_key.ts output

Terminal
Account Address Auth Key Private Key Public Key
------------------------------------------------------------------------------------------------
Alice 0x213d...031013 '0x213d...031013' '0x00a4...b2887b' '0x859e...08d2a9'
Bob 0x1c06...ac3bb3 0x1c06...ac3bb3 0xf2be...9486aa 0xbbc1...abb808
 
...rotating...
 
Alice 0x213d...031013 '0x1c06...ac3bb3' '0xf2be...9486aa' '0xbbc1...abb808'
Bob 0x1c06...ac3bb3 0x1c06...ac3bb3 0xf2be...9486aa 0xbbc1...abb808

Python

This program creates two accounts on devnet, Alice and Bob, funds them, then rotates the Alice’s authentication key to that of Bob’s.

View the full example for this code here.

Here’s the relevant code that rotates Alice’s keys to Bob’s:

Commands to run the example script:

Navigate to the python SDK directory, install dependencies and run

rotate_key.ts

Terminal
cd aptos-core/ecosystem/python/sdk
poetry install && poetry run python -m examples.rotate-key

rotate_key.py output

Terminal
Account Address Auth Key Private Key Public Key
------------------------------------------------------------------------------------------------
Alice 0x213d...031013 '0x213d...031013' '0x00a4...b2887b' '0x859e...08d2a9'
Bob 0x1c06...ac3bb3 0x1c06...ac3bb3 0xf2be...9486aa 0xbbc1...abb808
 
...rotating...
 
Alice 0x213d...031013 '0x1c06...ac3bb3' '0xf2be...9486aa' '0xbbc1...abb808'
Bob 0x1c06...ac3bb3 0x1c06...ac3bb3 0xf2be...9486aa 0xbbc1...abb808