How to securely store private keys

Set up Tatum KMS to manage your keys

Private keys and mnemonics are the only things that can unlock your crypto assets and approve transactions. If you lose access to them, you will lose access to your assets forever. Also, when someone else obtains access to your keys, they can steal all your funds. This is something that you must keep in mind to run your business successfully.

NEVER give access to your mnemonics or private keys to anyone. Your private keys should NEVER leave your secure perimeter and should not be sent over the Internet, not even via HTTPS connection. Tatum will never ask for your keys or mnemonics, and you should NEVER send them to the Tatum API.

There are public endpoints on Tatum API which accept or produce sensitive information like private key or mnemonics. These endpoints are only present for test use and quick prototyping, not for production usage. For production usage, you should leverage one of the following three options:

  • Tatum KMS - a key management system for your private keys. This tool stores the private keys and mnemonics on your server locally, and signs pending transactions periodically pulled from Tatum API.

  • Tatum Middleware - a local proxy REST API docker image that runs on your server and accepts every API request. It forwards non-sensitive API calls (create an account, get block) to Tatum API and resolves sensitive API calls (generate a wallet, send a transaction) locally. Private keys and mnemonics are part of the HTTP API request but never leave your perimeter.

  • Local libraries for different programming languages - The library takes care of the sensitive operations locally, usually on your local server where the backend of your application runs.

We recommend using Tatum KMS because it is the most secure and advanced tool available. In the following sections, you will learn how to set up the KMS and how the necessary operations in Tatum API look when leveraging the KMS.

Follow the guide below to learn how to use Tatum KMS, and also refer to our Crypto exchange part 2 workshop below for a demo on how to work with it.

How does Tatum KMS work?

Tatum KMS stores all your mnemonics and private keys in a wallet storage file. This storage file is an AEC encrypted file, for which only you know the encryption key.

Every wallet that is stored inside your KMS has a unique identifier, called signatureId. This signatureId is used in communication with Tatum API and represents the wallet used by the specific operation.

When you generate and store all the wallets you want to work with, you then enable the daemon mode in the KMS. This daemon mode periodically checks for the pending transactions to sign.

Every pending transaction has a signatureId present. When the pending transaction is matched with the wallet storage's specific wallet, it is signed locally and sent to the blockchain. Your wallet data are stored only in memory.

Setting up Tatum KMS

Tatum KMS is a command-line tool and provides two modes of operation:

  • daemon mode is responsible for periodically pulling pending transactions from the Tatum API

  • CLI mode is used to generate wallets or private keys

Tatum KMS is shipped as a Node.JS binary, and Node.JS 14+ should be installed on your server.

Your local server
Your local server
npm i -g @tatumio/tatum-kms

Generating your wallets

If you want to generate a wallet that is managed by the KMS, there is a generetemanagedwallet command in CLI mode.

Your local server
Your local server
tatum-kms generatemanagedwallet BTC
Enter password to access wallet storage:*****
{
"signatureId": "014073ce-af80-4f9c-8c7c-653ba5880afb",
"xpub": "xpub6FPGLmppWEemTJ56aq6wcSkjeZN4iEw1CBvQzkusgbJpqyoiPPJASLpbduzKrNF54i348moHyoVGkyz1H2TC3iEPLfacjPFEfTENkD6YzzZ"
}

You need to enter the password which decrypts your wallet storage. For the first time, when the storage file is empty, you have to set up your new password.

The wallet storage is encrypted with an AEC cipher and is stored on your local server. The password you provide is used to encrypt the mnemonics and private keys inside. If you lose your password, you will lose access to your mnemonics.

Enabling daemon mode

Once you have generated all your managed wallets, you need to start the KMS in daemon mode.

Your local server
Your local server
tatum-kms daemon --apiKey YOUR_API_KEY --chain=BTC
Enter password to access wallet storage:*****

You need to enter the password for unlocking the wallet storage. It is required whenever you start the daemon. If your daemon stops, you need to enter the password again when you start it up again.

Example usage of the API with Tatum KMS

Create an account or generate a blockchain address

The result of the generatemanagedwallet is the signatureId and the xpub for the wallet. This xpub can be used in the create account operations or for generating deposit addresses.

Create account
Generate deposit address
Create account
curl --location --request POST 'https://api-eu1.tatum.io/v3/ledger/account' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"currency": "BTC",
"xpub": "xpub6FPGLmppWEemTJ56aq6wcSkjeZN4iEw1CBvQzkusgbJpqyoiPPJASLpbduzKrNF54i348moHyoVGkyz1H2TC3iEPLfacjPFEfTENkD6YzzZ"
}'
Generate deposit address
curl --request GET \
--url https://api-eu1.tatum.io/v3/bitcoin/address/xpub6FPGLmppWEemTJ56aq6wcSkjeZN4iEw1CBvQzkusgbJpqyoiPPJASLpbduzKrNF54i348moHyoVGkyz1H2TC3iEPLfacjPFEfTENkD6YzzZ/1 \
--header 'x-api-key: YOUR_API_KEY'

Send a Bitcoin transaction

You can send a transaction with the same API endpoint as seen in the guide. The only difference is that instead of private keys, you enter the signatureId of the wallet you want to use.

Request - List of addresses as a source
Response
Request - List of addresses as a source
curl --location --request POST 'https://api-eu1.tatum.io/v3/bitcoin/transaction' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"fromAddress": [
{
"address": "mgSXLa5sJHvBpYTKZ62aW9z2YWQNTJ59Zm",
"signatureId": "014073ce-af80-4f9c-8c7c-653ba5880afb"
}
],
"to": [
{
"address": "mgSXLa5sJHvBpYTKZ62aW9z2YWQNTJ59Zm",
"value": 0.000006
},
{
"address": "mgSXLa5sJHvBpYTKZ62aW9z2YWQNTJ59Zm",
"value": 0.000009
}
]
}'
Response
{
"signatureId": "0fe373ce-af80-4f9c-9412-653ba5880afb"
}

Be aware that when a private key is in the request, you need to enter signatureId of the private key from the wallet storage. Private keys can be stored using the storemanagedprivatekey command. You can generate a specific private key from the managed stored wallet using the getprivatekey command. When there is a mnemonic, you need to enter the signatureId of the mnemonic from the wallet storage.

As you can see, there was no private key or mnemonic anywhere in this request, nor was any other sensitive information required.

But be aware that there is a change in the behavior of this operation. The transaction is not yet signed and sent to the blockchain. It is waiting in the Tatum to be processed by the KMS.

When the KMS detects a new pending transaction, it signs it locally and sends it to the blockchain. It must also mark the transaction as processed so that it will not be sent to the blockchain again.‌

This process is the same for every other send transaction method for every blockchain. The process is a little bit complicated at the beginning but provides you with the best security available.

Tatum KMS also supports integrations to Azure Key Vault or VGS so that you can store your keys and mnemonics there. More information can be found on the Tatum KMS GitHub pages, where all of the source code is available.