Rekeying accounts
Rekeying is a powerful protocol feature that enables an Algorand account holder to maintain a static public address while dynamically rotating the authoritative private spending key(s). This is accomplished by issuing a rekey-to transaction
which sets the authorized address field within the account object. Future transaction authorization using the account’s public address must be provided by the spending key(s) associated with the authorized address, which may be a single key address, MultiSig address, or LogicSig program address. Key management is a critical concept, and Algorand provides tools to securely accomplish relevant tasks.
Quick start videos
If you prefer videos, watch this 4-minute Learn About Algorand Account Rekeying guide.
Account Review
The keys and signing page introduces keys, addresses, and accounts. During initial account generation, a public key and corresponding private spending key are created to derive the Algorand address. This public address is commonly displayed within wallet software and remains static for each account. When you receive Algo or other assets, they will be sent to your public Algorand address. When you send from your account, the transaction must be authorized using the appropriate private spending key(s).
Authorized Addresses
The balance record of every account includes the “auth-addr” field, which, when populated, defines the required authorized address to be evaluated during transaction validation. Initially, the “auth-addr” field is implicitly set to the account’s “address” field, and the only valid private spending key is created during account generation. The “auth-addr” field is only stored and displayed to conserve resources after the network confirms an authorized rekey-to transaction.
Conceptually illustrated in the image below, a “standard” account uses its private spending key to authorize from its public address. A “rekeyed” account defines the authorized address that references a distinct “foreign” address and thus requires the private spending key(s) thereof to authorize future transactions.

Standard Account
Use the following code sample to view a standard account on BetaNet:
goal account dump --address NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU`
Response:
{ "addr": "NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU", "algo": 100000, [...]}
Notice that the response includes the “add” field, which is the public address. Only the spending key associated with this address may authorize transactions for this account.
Rekeyed Account
Next, modify your command slightly to display results for this rekeyed account:
L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU
Response:
{ "addr": "L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU", "algo": 100000, "spend": "NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU", [...]}
This response includes the addition of the “spend” field. This is the “auth-addr” within the account object and signifies any transactions from L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU
must now be authorized by NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU
to be confirmed by the network.
Rekey-to Transaction
A rekey-to transaction is a transaction that includes the rekey-to
parameter set to a well-formed Algorand address. The existing authorized address must provide authorization for this transaction. As shown in the first example account above, the authorized address is implicitly the “addr” field of this account even though the “auth-addr” field is not explicitly defined. Only the private spending key of this “addr” address may be used to authorize a rekey-to transaction.
The rekey-to transaction workflow is as follows:
Construct a transaction that specifies an address for the rekey-to
parameter
Add the required signature(s) from the current authorized address
Send and confirm the transaction on the network
Construct Transaction
The following commands will construct an unsigned transaction file rekey.txn
and inspect the contents:
goal clerk send --from L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU \ --to L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU \ --amount 0 \ --rekey-to NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU \ --out rekey.txngoal clerk inspect rekey.txn
Response:
rekey.txn[0]{ "txn": { "fee": 1000, "fv": 4921687, "gen": "betanet-v1.0", "gh": "mFgazF+2uRS1tMiL9dsj01hJGySEmPN28B/TjjvpVW0=", "lv": 4922687, "note": "bbD6hjNZNdg=", "rcv": "L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU", "rekey": "NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU", "snd": "L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU", "type": "pay" }}
Construction of the rekey-to transaction includes the rekey-to
parameter and the value "NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU"
. Notice the resulting unsigned transaction output includes the “rekey” field and this value.
Add Authorized Signature(s)
Adding the currently authorized signature(s) to a rekey-to transaction is required before sending it to the network for confirmation. The “snd” field provides the address to the account object where the “auth-addr” field is defined.
Send and Confirm
Once all required signatures are gathered into a single signed transaction, it may be sent to the network for confirmation. The result for the sample account is as follows:
{ "addr": "L42DW7MSHP4PMIAZSDAXYTZVHTE756KGXCJYGFKCET5XHIAWLBYYNSMZQU", "algo": 100000, "spend": "NFFMZJC6H52JLEAITTJ7OIML3XCJFKIRXYRJLO4WLWIJZB7N6CTWESRAZU", [...]}
Conclusion
The result of a confirmed rekey-to transaction will be the “auth-addr” field of the account object is defined, modified, or removed. Defining or modifying means only the corresponding authorized address’s private spending key(s) may authorize future transactions for this public address. Removing the “auth-addr” field is an explicit assignment of the authorized address back to the “addr” field of the account object (observed implicitly because the field is not displayed).
To provide maximum flexibility in key management options, the “auth-addr” may be specified within a rekey-to transaction as a distinct foreign address representing a single key address, MultiSig address, or LogicSig program address.
Use Case Scenarios
Below are a series of potential use cases for rekeying various accounts.
1 - Rekey to Single Address
The first scenario rekeys a single key account with address “A” to a distinct single key account with address “B.” This requires two single key accounts at time t0. The result from time t1 is that transactions for address “A” must be authorized by address “B.”

Generate and Fund Accounts
Refer to the Getting Started guide to learn how to generate two accounts and fund their respective address from the Faucet. This example uses the following public addresses:
ADDR_A="UGAGADYHIUGFGRBEPHXRFI6Z73HUFZ25QP32P5FV4H6B3H3DS2JII5ZF3Q"ADDR_B="LOWE5DE25WOXZB643JSNWPE6MGIJNBLRPU2RBAVUNI4ZU22E3N7PHYYHSY"
View the initial authorized address for Account A using goal
:
goal account dump --address $ADDR_A
Response:
{ "addr": "UGAGADYHIUGFGRBEPHXRFI6Z73HUFZ25QP32P5FV4H6B3H3DS2JII5ZF3Q", "algo": 100000, [...]}
The authorized address is defined as the “addr” field displayed here.
Rekey to Single Address
Account A intends to rekey its authorized address to $ADDR_B,
which is the public address of Account “B”. This can be accomplished in a single goal
command:
goal clerk send --from $ADDR_A --to $ADDR_A --amount 0 --rekey-to $ADDR_B
Results of
goal account dump --address $ADDR_A
will now display:
{ "addr": "UGAGADYHIUGFGRBEPHXRFI6Z73HUFZ25QP32P5FV4H6B3H3DS2JII5ZF3Q", "algo": 199000, [...] "spend": "LOWE5DE25WOXZB643JSNWPE6MGIJNBLRPU2RBAVUNI4ZU22E3N7PHYYHSY"}
The populated “spend” field instructs the validation protocol to only approve transactions for this account object when authorized by that address’s spending key(s). Validators will ignore all other attempted authorizations, including those from the public address defined in the “addr” field.
TEST: Send with Auth A
The following transaction will fail because, by default, goal
attempts to add the authorization using the --from
parameter. However, the protocol will reject this because it is expecting the authorization from $ADDR_B
due to the confirmed rekeying transaction above.
goal clerk send --from $ADDR_A --to $ADDR_B --amount 100000
Send from the Authorized Address
Sending from the authorized address of Account “A” requires:
Construct an unsigned transaction from $ADDR_A
Sign using authorized address $ADDR_B
Send authorized transaction
Construct Unsigned Transaction
First, construct an unsigned transaction using goal
with the --outfile
flag to write the unsigned transaction to a file:
goal clerk send --from $ADDR_A --to $ADDR_B --amount 100000 --out send-single.txn
Sign Using Authorized Address
Next, locate the wallet containing the private spending key for Account “B”. The goal clerk sign
command provides the flag --signer
, which specifies the proper required authorized address $ADDR_B
. Notice the infile
flag reads in the unsigned transaction file from above and the --outfile
flag writes the signed transaction to a separate file.
goal clerk sign --signer $ADDR_B --infile send-single.txn --outfile send-single.stxn
TEST: Send with Auth B
Finally, send the the signed transaction file using goal
:
goal clerk rawsend --filename send-single.stxn
This will succeed, sending the 100000 microAlgos from $ADDR_A
to $ADDR_B
using the private spending key of Account “B”.
2 - Rekey to MultiSig Address
The second scenario rekeys a single key account with public address “A” to a MultiSig address “BC_T1”. This scenario reuses both Accounts “A” and “B”, adds a third Account “C” and creates a MultiSig Account “BC_T1” comprised of addresses “B” and “C” with a threshold of 1. The result will be the private spending key for $ADDR_B
or $ADDR_C
may authorize transaction from $ADDR_A
.

Generate Additional Account
Follow the same procedure as above to generate a third account for use as “C”.
Generate a New MultiSig Account
Reference the documentation to generate a MultiSig account. Ensure it uses both $ADDR_B
and the new $ADDR_C
with a threshold of 1 (so either “B” or “C” may authorize). Set the resulting account address to the $ADDR_BC_T1
environment variable for use below.
Rekey to MultiSig Address
Recall from scenario 1 that Account “A” has already rekeyed to $ADDR_B
.
Construct Unsigned Transaction
The rekey transaction constructed for this scenario requires authorization from $ADDR_B
.
goal clerk send --from $ADDR_A --to $ADDR_A --amount 0 --rekey-to $ADDR_BC_T1 --out rekey-multisig.txn
Sign Rekey Transaction
goal clerk sign --signer $ADDR_B --infile rekey-multisig.txn --outfile rekey-multisig.stxn
Send and Confirm Rekey to MultiSig
goal clerk rawsend --filename rekey-multisig.stxngoal account dump --address $ADDR_A
The rekey transaction will confirm, resulting in the “spend” field update within the account object:
{ "addr": "UGAGADYHIUGFGRBEPHXRFI6Z73HUFZ25QP32P5FV4H6B3H3DS2JII5ZF3Q", "algo": 199000, [...] "spend": "NEWMULTISIGADDRESSBCT1..."}
TEST: Send with Auth BC_T1
Use the established pattern:
Construct unsigned transaction
Sign transaction
Confirm transaction
goal clerk send --from $ADDR_A --to $ADDR_B --amount 100000 --msig-params="1 $ADDR_B $ADDR_C" --out send-multisig-bct1.txngoal clerk multisig sign --tx send-multisig-bct1.txn --address $ADDR_Cgoal clerk rawsend --filename send-multisig-bct1.txn
This transaction will succeed as a private spending key for $ADDR_C
provided the authorization and meets the threshold requirement for the MultiSig account.
Utils Example
In the following example, Account 1 is rekeyed to Account 2. The code then illustrates that signing a transaction from Account 1 will fail if signed with Account 1’s private key and succeed if signed with Account 2’s private key.
1 /**2 * Rekey an account to use a different address for signing.3 * This allows account A to be controlled by account B's private key.4 */5 await algorand.account.rekeyAccount(randomAccountA, randomAccountB)6
7 // Send a payment transaction from account A8 // which will automatically sign the transaction with account B's private key9 await algorand.send.payment({10 sender: randomAccountA,11 receiver: randomAccountC,12 amount: algo(1),13 })
1 algorand_client, dispenser, account_a, account_b, _ = setup_localnet_environment()2
3 """4 Rekey an account to use a different address for signing.5 This allows account 1 to be controlled by account 2's private key.6 """7 algorand_client.account.rekey_account(account=account_a.address, rekey_to=account_b)8
9 payment_txn_result = algorand_client.send.payment(10 PaymentParams(11 sender=account_a.address,12 receiver=account_b.address,13 amount=AlgoAmount(algo=1),14 )15 )16
17 unsigned_payment_txn = algorand_client.create_transaction.payment(18 PaymentParams(19 sender=account_a.address,20 receiver=account_b.address,21 amount=AlgoAmount(algo=1),22 signer=account_b.signer,23 first_valid_round=algorand_client.get_suggested_params().first + 1,24 )25 )26
27 """28 The unsigned transaction can be signed by the signer when sending with the `add_transaction` method.29 """30 result = (31 algorand_client.new_group()32 .add_transaction(transaction=unsigned_payment_txn, signer=account_b.signer)33 .send()34 )