Use KMS to Store Private Keys and Sign Transactions on Bitcoin

Generate wallets, private keys, blockchain addresses, and sign transactions locally

In this guide, you will learn how to generate wallets, private keys, blockchain addresses, and sign transactions locally using Tatum Key Management System (KMS).

This guide shows how to start using KMS on Bitcoin and similar blockchains.

KMS works on any supported blockchain - and the process is even easier on some.

Process overview and prerequisites

Before you start, we recommend that your review the following sections:

You will work on the Bitcoin testnet.

With KMS installed, you will go through the following steps:

  1. Generate a managed wallet.

  2. Create a private key.

  3. Generate an address.

  4. Store the private key to your wallet.

  5. Send some test BTC to your new address.

  6. Enable daemon mode.

  7. Initiate a transaction and let KMS sign it.

  8. Get transaction details.

Step 1 - Generate a managed wallet

To generate a wallet that is managed by the KMS, use the generatemanagedwallet command in CLI mode.

Request

tatum-kms --path=wallet.dat --testnet generatemanagedwallet BTC

Enter password to access wallet storage:*****

When you first use KMS, you will be prompted to enter a password to encrypt your data. This password is created the first time you enter it, and you should store it in a safe place.

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.

Response

The response contains your wallet mnemonic's signature ID as the first parameter:

{
  "xxx-59be-4792-81c5-yyy": {
    "mnemonic": "urge pulp usage sister evidence arrest palm math please chief egg abuse",
    "xpub": "tpubBCDEF"
  }
}

Step 2 - Create a private key

In this step, you will generate a private key for your wallet locally.

Private keys are used to authorize transfers of funds from blockchain addresses. Use the getprivatekey command to generate a private key:

Request

tatum-kms --path=wallet.dat --testnet getprivatekey xxx-59be-4792–81c5-yyy 0

The required parameters are:

  • Your wallet mnemonic's signature ID Signature ID is the first parameter in the Response from Step 1 - Generate a managed wallet.

Response

The response is the private key of the derivation index that you have specified:

{
  "privateKey": "XXXNAV3tX3vWPG4uThixuqdYYY"
}

Step 3 - Generate an address

In this step, you will create an address for the private key that you just generated. You can receive funds to the address and use the private key to send them from the address.

Use the getaddress **** command to generate an address for the same derivation index (0) that you specified in Step 2 - Create a private key:

Request

tatum-kms --path=wallet.dat --testnet getaddress xxx-59be-4792–81c5-yyy 0

The parameters required are:

  • Your wallet mnemonic's signature ID

  • The derivation index of the address you are generating — the same derivation index that you specified in Step 2 - Create a private key.

The response will contain the address you have just generated:

{
  "address": "AAAA3JPvMuwgpKovMTjBBB"
}

Step 4 - Store the private key to your wallet

You will now store the private key that you have just generated to the wallet using the storemanagedprivatekey command:

Request

tatum-kms --path=wallet.dat --testnet storemanagedprivatekey BTC

When prompted, enter the private key and the password that you created earlier in this guide:

Enter password + private key

Enter private key to store:XXXNAV3tX3vWPG4uThixuqdYYY

Enter password to access wallet store:******

Response

The response will contain the signature ID of the private key, which you can then use to sign transactions.

{
 "signatureId": "QQQ-4b41-4ec9-b66c-WWW"
}

You can now export the wallet and review it. Enter the following to export:

Request

tatum-kms --path=wallet.dat --testnet export

When prompted, enter your password.

Response

The response will give you details about your wallet:

{
 "QQQ-4b41-4ec9-b66c-WWW": {
   "privateKey": "XXXNAV3tX3vWPG4uThixuqdYYY",
   "chain": "BTC",
   "testnet": true
 },
 "xxx-59be-4792-81c5-yyy": {
   "mnemonic": "urge pulp usage sister evidence arrest palm math please chief egg abuse",
   "xpub": "tpubBCDEF",
   "chain": "BTC",
   "testnet": true
 }
}

Step 5 - Send test BTC to your new address

Use a Bitcoin testnet faucet to send some test BTC to your address. You can use any faucet (mobile example).

Send the test BTC to the Bitcoin address that you generated in Step 3 - Generate an address (AAAA3JPvMuwgpKovMTjBBB).

Step 6 - Enable daemon mode

Daemon mode is essentially KMS running in the background and listening for pending transactions to sign and broadcast them.

  • Transactions are identified by your API key.

  • You can filter transactions by blockchain.

To enable daemon mode, enter the following code on your local server:

tatum-kms daemon --path=wallet.dat --testnet --chain=BTC --api-key=your-testnet-api-key --period=10

You must enter the password to unlock the wallet storage. The password is required whenever you start the daemon or restart the daemon after it stopped.

By default, Tatum KMS checks for the pending transactions every 5 seconds using this API call. One API call consumes 1 credit from your monthly credit allowance.

You can change the frequency of the check using the period parameter.

Step 7 - Initiate a transaction and let KMS sign it

You can now send bitcoin from your address to any other address.

To do so, send a bitcoin transaction API request to Tatum.

Request (cURL)

Instead of a privateKey, enter a signatureId field that contains your signature ID from Step 4 - Store the private key to your wallet:

curl --location --request POST 'https://api.tatum.io/v3/bitcoin/transaction' \
--header 'x-api-key: your-tesnet-api-key-from-tatum' \
--header 'Content-Type: application/json' \
--data-raw '{
"fromAddress": [
       {
           "address": "AAAA3JPvMuwgpKovMTjBBB", -> FROM STEP 3
           "signatureId": "QQQ-4b41-4ec9-b66c-WWW" -> FROM STEP 4
       }
   ],
   "to": [
       {
           "address": "testnet-bitcoin-address",
           "value": 0.00001 -> AMOUNT OF BTC TO SEND
       },
       {
           "address": "AAAA3JPvMuwgpKovMTjBBB",
           "value": 0.00007 -> AMOUNT OF BTC TO CHANGE 
       }
   ]
}'

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

KMS now detects a new pending transaction, signs it locally and sends the transaction to the blockchain.

KMS must also mark the transaction as processed so that it will not be sent to the blockchain again

Response

When KMS picks up the pending transaction, it will output something like the following sample:

Processing pending transaction - {
  "withdrawalId": null,
  "chain": "BTC",
  "serializedTransaction": "{\"hash\":\"81e62bdfbfc7bcb66c2a2f17335d033fd98b84c1188a7bb379a2dce9f1cda989\",\"version\":2,\"inputs\":[{\"prevTxId\":\"121702fd7acd1b2cca6bd19658009140730ba26ca67cd222c00f952a111e11f4\",\"outputIndex\":0,\"sequenceNumber\":4294967295,\"script\":\"\",\"scriptString\":\"\",\"output\":{\"satoshis\":2000,\"script\":\"76a914c8e668ee829837a2355c1e234a41f53f86b8156c88ac\"}}],\"outputs\":[{\"satoshis\":1000,\"script\":\"001487c70889f0a1d2f632d216a01472dde71f062aa7\"}],\"nLockTime\":0}",
  "hashes": [
    "b8eb99cd-ba04-4031-a65f-11d6420ebdd1"
  ],
  "index": null,
  "withdrawalResponses": null,
  "id": "61fe7c68cf2fbc595cbb89dd"
}.

Step 8 - Get transaction details

Using the KMS transaction ID from the id field of the response to the previous request (61fe7c68cf2fbc595cbb89dd in the example above), you can now use the Get transaction details endpoint to acquire the details of the transaction you have just performed.

Request

curl --request GET
--url https://api.tatum.io/v3/kms/61fe7c68cf2fbc595cbb89dd
--header 'x-api-key: your-testnet-api-key-from-tatum'

Response

The response will contain the details of your transaction:

{
 "withdrawalId": null,
 "chain": "BTC",
 "serializedTransaction": "{\"hash\":\"81e62bdfbfc7bcb66c2a2f17335d033fd98b84c1188a7bb379a2dce9f1cda989\",\"version\":2,\"inputs\":[{\"prevTxId\":\"121702fd7acd1b2cca6bd19658009140730ba26ca67cd222c00f952a111e11f4\",\"outputIndex\":0,\"sequenceNumber\":4294967295,\"script\":\"\",\"scriptString\":\"\",\"output\":{\"satoshis\":2000,\"script\":\"76a914c8e668ee829837a2355c1e234a41f53f86b8156c88ac\"}}],\"outputs\":[{\"satoshis\":1000,\"script\":\"001487c70889f0a1d2f632d216a01472dde71f062aa7\"}],\"nLockTime\":0}",
 "hashes": [
   "b8eb99cd-ba04-4031-a65f-11d6420ebdd1"
 ],
 "index": null,
 "withdrawalResponses": null,
 "txId": "f7572ef070d381612b7594940cc73ec008e796b37a73ff031f3855d2a23c9ade",
 "id": "61fe7c68cf2fbc595cbb89dd"

The response contains a Bitcoin transaction ID in the txId field (f7572ef070d381612b7594940cc73ec008e796b37a73ff031f3855d2a23c9ade in the example above), which you can use to view the blockchain transaction in any Bitcoin blockchain explorer.

Last updated