ARCs:specs:arc-0035.md•6.28 kB
---
arc: 35
title: Algorand Offline Wallet Backup Protocol
description: Wallet-agnostic backup protocol for multiple accounts
author: Yigit Guler (@yigitguler)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/156
status: Final
type: Standards Track
category: Interface
sub-category: Wallet
created: 2023-01-03
---
# Algorand Secure Offline Wallet Backup Protocol
## Abstract
This document outlines the high-level requirements for a wallet-agnostic backup protocol that can be used across all wallets on the Algorand ecosystem.
## Specification
The key words "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**", "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**" in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt">RFC-2119</a>.
### Requirements
At a high-level, offline wallet backup protocol has the following requirements:
* Wallet applications should allow backing up and storing multiple accounts at the same time.
Account information should be encrypted with a user-defined secret key, utilizing NaCl SecretBox method (audited and endorsed by Algorand).
* Encrypted final string should be easily copyable to be stored digitally.
When importing, wallet applications should be able to detect already imported accounts and gracefully ignore them.
### Format
Before encryption, account information should be converted to the following JSON format:
```
{
"device_id": "UNIQUE IDENTIFIER FOR DEVICE (OPTIONAL)",
"provider_name": "PROVIDER NAME (OPTIONAL, i.e. Pera Wallet)",
"accounts": [
{
"address": "ACCOUNT PUBLIC ADDRESS (REQUIRED)",
"name": "USER DEFINED ACCOUNT NAME (OPTIONAL)",
"account_type": "TYPE OF ACCOUNT: single, multisig, watch, contact, ledger (REQUIRED)",
"private_key": "PRIVATE KEY AS BASE64 ENCODING OF 64 BYTE ALGORAND PRIVATE KEY as encoded by algosdk (NOT PASSPHRASE, REQUIRED for user-owned accounts, can be omitted in case of watch, contact, multisig, ledger accounts)",
"metadata": "ANY ADDITIONAL CONTENT (OPTIONAL)",
"multisig": "Multisig information (only required if the account_type is multisig)",
"ledger": {
"device_id": "device id",
"index": <index of the account on device, integer>,
"connection_type": "bluetooth|usb"
},
},
...
]
}
```
*Clients must accept additional fields in the JSON document.*
Here is an example with a single account:
```
{
"device_id": "2498232091970170817",
"provider_name": "Pera Wallet",
"accounts": [
{
"address": "ELWRE6HZ7KIUT46EQ6PBISGD3ND6QSCBVWICYR2QR2Y7LOBRZRCAIKLWDE",
"name": "My NFT Account",
"account_type": "single",
"private_key": "w0HG2VH7tAYz9PD4SYX0flC4CKh1OONCB6U5bP7cXGci7RJ4+fqRSfPEh54USMPbR+hIQa2QLEdQjrH1uDHMRA=="
}
],
}
```
Here is an example with a single multi-sig account:
```
{
"device_id": "2498232091970170817",
"provider_name": "Pera Wallet",
"accounts": [
{
"address": "ELWRE6HZ7KIUT46EQ6PBISGD3ND6QSCBVWICYR2QR2Y7LOBRZRCAIKLWDE",
"name": "Our Multisig Account",
"account_type": "multisig",
"multisig": {
version: 1,
threshold: 2,
addrs: [
account1.addr,
account2.addr,
account3.addr,
],
},
}
],
}
```
### Encryption
Once the input JSON is ready, as specified above, it needs to be encrypted. Even if it is assumed that the user is going to store this information in a secure location, copy-pasting it without encryption is not secure since multiple applications can access the clipboard.
The information needs to be encrypted using a very long passphrase. 12 words mnemonic will be used as the key. 12-word mnemonic is secure and it will not create confusion with the 25-word mnemonics that are used to encrypt accounts.
The wallet applications should not allow users to copy the 12-word mnemonic nor allow taking screenshots. The users should note it visually.
The encryption should be made as follows:
1. The wallet generates a random 16-byte string S (using a cryptographically secure random number generator)
2. The wallet derives a 32-byte key: `key = HMAC-SHA256(key="Algorand export 1.0", input=S)`
On libsodium, use https://libsodium.gitbook.io/doc/advanced/hmac-sha2#hmac-sha-256,
`crypto_auth_hmacsha256_init` / `crypto_auth_hmacsha256_update` / `crypto_auth_hmacsha256_final`
3. The wallet encrypts the input JSON using `crypto_secretbox_easy` from libsodium (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretbox)
4. The wallet outputs the following output JSON:
```
{
"version": "1.0",
"suite": "HMAC-SHA256:sodium_secretbox_easy",
"ciphertext": <base64 of the ciphertext>
}
```
This JSON document (will be referred as ciphertext envelope JSON) needs to be encoded with base64 again in order to make it easier to copy-paste & store.
5. S is encoded as a 12-word mnemonic (according to BIP-39) and displayed to the user.
The user will be responsible for keeping the 12-word mnemonic and the base64 output of the ciphertext envelope JSON in safe locations. Note that step 5 is the default approach, however, the wallets can support other methods other than mnemonics as well, as long as they are secure.
### Importing
When importing, wallet applications should ask the user for the base64 output of the envelope JSON and the 12-word mnemonic. After getting these values, it should attempt to decrypt the encrypted string using the 12-word mnemonic. On successful decryption, accounts that can be imported can be processed.
## Rationale
There are many benefits to having an openly documented format:
* Better interoperability across wallets, allowing users to use multiple wallets easily by importing all of their accounts using a single format.
* Easy and secure backup of all wallet data at a user-defined location, including secure storage in digital environments.
* Ability to transfer data from device to device securely, such as when moving data from one mobile device to another.
## Security Considerations
Tbd
## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.