Using Azure Key Vault for Wallet Transactions using JavaScript
The most important piece of information for every Algorand wallet owner, is the private key. It is the most important because loss of that private key will result in the owner not being able to access the tokens associated to that wallet, without any possibility of recovery.
With Azure Key Vault one can store, retrieve and recover an account using your private key using the cloud, so you won’t loose it. In addition, iOS/Android wallets will be empty if you get a new phone when you transfer everything from the old phone to a new one. You will need your passphrase there too, for account restoration on the new phone wallet. And this can be easily retrieved from the Azure Key Vault.
This tutorial will provide the necessary information needed to sign Algorand transactions with a private key stored in Azure Key Vault.
RESOURCES
Requirements
- Algorand JavaScript SDK
- Vs Code or any IDE of your choice
- Node Package Manager
- Create Free Azure Account
- Azure KeyVault Secret and Azure Identity Client
Background
Azure Key Vault is a cloud service that provides a secure store for secrets. You can securely store keys, passwords, certificates, and other secrets. Azure key vaults may be created and managed through the Azure portal. In this tutorial, you create a key vault, then use it to store a secret and retrieve the secret to sign transactions on Algorand.
Azure Key Vault, and its Hardware Security Modules (HSM) offering, allows management and usage of cryptographic key pairs, without the private key ever leaving the vault, unless it’s for backup and restore operations, meaning, the risk of loss or exposure of the private key is reduced.
This tutorial will cover setting up of Azure account, creating Key Vault, Creating Payment Transaction, signing the transaction with secret key retrieved from Azure Key Vault and also recovering of private key.
Steps
- 1. Package Installation and Environment Setup
- 2. Azure Account Setup
- 3. Create Resource Group
- 4. Create Key Vault
- 5. Create Secret
- 6. Setup Environment Variables
- 7. Get Client Secret From Azure key Vault
- 8. Recover Account
- 9. Create Payment Transaction And Sign With Secret Retrieved From key Vault
- 10. Full Code
- 11. Run Code
- 12. Clear Resource
- 13. Next step
- 14. Conclusion
1. Package Installation and Environment Setup
To get started create a local folder on your machine for the code, cd (change directory) into that folder
do npm init
and install the following packages
npm install algosdk
This will install the Algorand JavaScript SDK. The algosdk ensures interactions with the Algorand blockchain.
Fig 1-1 Install algosdk
npm install --save @azure/identity
This will install the Azure Identity library. The Azure Identity library provides Azure Active Directory (Azure AD) token authentication through a set of convenient TokenCredential implementations.
npm install @azure/keyvault-secrets
Use the KeyVault Secrets client library to get access to Azure Key Vault.
Fig 1-2 Install Azure Identity and KeyVault Secrets
npm install dotenv --save
Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code. You will create a .env
file at the root of your project.
Fig 1-3 Install dotenv
On mac do `brew update && brew install azure-cli
This will enable interactions with azure portal from the command line. If you encounter any error while running the above command you can try to install from source with:
brew install --build-from-source [email protected]
.
If you are having problem installing the CLI this installation guide should be helpful.
Fig 1-4 Install azure-cli
File Structure
Note
Your file structure should look like this. Your .env
and node module
should be added to .gitignore
file so you don’t end up exposing your credentials when you push to github.
Fig 1-5 File Structure
2. Azure Account Setup
Create a free Azure account and login to the portal. Create account here. There are two types of account the free account and PayAsYouGo account. The free account gives you access to the Azure portal to access the Azure features for a trial period of 30 days.
Create Azure Account
Fig 2-1 Create Account
Login to Azure Portal
After successful account creation you can then login.
Fig 2-2 Login
3. Create Resource Group
A resource group is a container that holds related resources for an Azure solution.To create resource
click on Resource Groups on the left pane to bring up Resource groups.
Fig 3-1 Select Resource Group
Click on the create button to create a new resource group called azure-vault-rg
Fig 3-2 Create Resource Group
Note
When creating a resource in Azure, the naming convention is to end the name of the resource with -rg , this way one can easily identify it as resource group. Same w other names -vault, -secret , -vm, etc
Azure resources tagging allows you to assign a kind of metadata to a resource. Then, you can find all the resources that have the same tag !
A tag is a Key/Value pair. It can be applied to the resource groups or directly on the resources. It is searchable so it can be used to find resources or resource groups using Powershell or Azure Portal.
Fig 3-3 Resource Group Tag
4. Create Key Vault
Azure Key Vault is a cloud service that provides a secure store for secrets. You can securely store keys, passwords, certificates, and other secrets. Azure key vaults may be created and managed through the Azure portal.
There are several ways to create key vault from the azure portal. From your resource group you can hit the + button to create a new resource or you can search for Key Vault using the search bar.
Fig 4-1 Search Key Vault
Select the resource group name, enter the key vault name, select region and pricing tier. Then hit the review and create button.
Fig 4-2 Create Key Vault
Note
Purge protection is an optional Key Vault behavior and is not enabled by default. Purge protection can only be enabled once soft-delete is enabled. It can be turned on via CLI or PowerShell. Purge protection is recommended when using keys for encryption to prevent data loss.
Fig 4-3 Go to Resource
When you are done creating the key vault click on the Go to resource button. This will take you to the key vault overview page. Take note of the vault uri, this will be used later on the client app. The vault uri value will be used later in step 6.
Fig 4-4 Key Vault Overview
To check the details or properties of the key vault. Click on properties on the left hand panel.
Fig 4-5 Key Vault Properties
5. Create Secret
To follow up in this tutorial, you will store your mnemonic in secret. This secret will be retrieved later to sign transaction.
To create secret, click on secret and the + button to generate/import secret.
Fig 5-1 Create Secret
Enter the secret name and value. Set activation and expiration date and tag then hit the create button.
Fig 5-2 Create Secret Form
The highlighed secret is the secret name which you will use later in client app. This will be the value for the secret name in the environment variables in step 6.
Fig 5-3 Secrets
6. Setup Environment Variables
Note
Create .env
file at the root of your project to store sensitive information. Your .env
file should look like this. The values should not be quoted.
The Purestake client will be used to connect.The API_KEY is gotten from Purestake API. Once you create account, you will have access to the API Key.
The secret name is highlighted in fig 5-3 and the vault uri is highlighted in fig 4-4.
API_KEY = YOUR PURESTAKE API KEY
KEY_VAULT_URI = https://algo-vault.vault.azure.net/
SECRET_NAME = mnemonic-secret
ALGOD_SERVER = https://testnet-algorand.api.purestake.io/ps2/
PORT =
7. Get Client Secret From Azure key Vault
This handles connecting to the azure identity and secret client and making a request to get the secret.
// src/VaultSecret.js
// Azure authentication library to access Azure Key Vault
const { DefaultAzureCredential} = require("@azure/identity")
const { SecretClient } = require("@azure/keyvault-secrets")
require('dotenv').config({path: '../.env'})
const getSecret = async () =>{
try{
// Azure SDK clients accept the credential as a parameter
const credential = new DefaultAzureCredential();
const client = new SecretClient(process.env.KEY_VAULT_URI, credential)
const secret = await client.getSecret(process.env.SECRET_NAME)
const value = secret.value
console.log(value)
return value
}catch(err){
console.log(err)
}
}
getSecret()
module.exports ={
getSecret
}
8. Recover Account
This handles recovering of Algorand wallet using the secret from Azure Key Vault.
// src/RecoverAccount.js
const vault = require('./VaultSecret')
const algosdk = require('algosdk')
const recoverAccount = async () =>{
const mnomenic = await vault.getSecret()
const recover = algosdk.mnemonicToSecretKey(mnomenic)
console.log(recover.sk)
}
recoverAccount()
9. Create Payment Transaction And Sign With Secret Retrieved From key Vault
Connect your client
//src/Transaction.js
const algodToken = {"X-API-Key": process.env.API_KEY}
const algodServer = process.env.ALGOD_SERVER;
const algodPort = process.env.PORT;
let algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort);
//src/Transaction.js
The code here handles connecting to the Algorand Purestake API client, creating a payment transaction, Signing the transaction with secret from Azure Key Vault.
const vault = require('./VaultSecret')
const algosdk = require('algosdk')
require('dotenv').config({path: '../.env'})
async function paymentTransaction() {
const mnomenic = await vault.getSecret()
const account = algosdk.mnemonicToSecretKey(mnomenic)
const senderAddress = account.addr
try {
//Check your balance
let accountInfo = await algodClient.accountInformation(senderAddress).do();
console.log("Account balance: %d microAlgos", accountInfo.amount);
// Construct the transaction
let params = await algodClient.getTransactionParams().do();
// comment out the next two lines to use suggested fee
params.fee = algosdk.ALGORAND_MIN_TX_FEE;
params.flatFee = true;
// receiver defined as TestNet faucet address
const receiver = "HZ57J3K46JIJXILONBBZOHX6BKPXEM2VVXNRFSUED6DKFD5ZD24PMJ3MVA";
const enc = new TextEncoder();
const note = enc.encode("Hello World");
let amount = 1000000;
let sender = senderAddress;
let txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
from: sender,
to: receiver,
amount: amount,
note: note,
suggestedParams: params
});
// Sign the transaction
let signedTxn = txn.signTxn(account.sk);
let txId = txn.txID().toString();
console.log("Signed transaction with txID: %s", txId);
// Submit the transaction
await algodClient.sendRawTransaction(signedTxn).do();
// Wait for confirmation
let confirmedTxn = await algosdk.waitForConfirmation(algodClient, txId, 4);
//Get the completed Transaction
console.log("Transaction " + txId + " confirmed in round " + confirmedTxn["confirmed-round"]);
let string = new TextDecoder().decode(confirmedTxn.txn.txn.note);
console.log("Note field: ", string);
accountInfo = await algodClient.accountInformation(senderAddress).do();
console.log("Transaction Amount: %d microAlgos", confirmedTxn.txn.txn.amt);
console.log("Transaction Fee: %d microAlgos", confirmedTxn.txn.txn.fee);
console.log("Account balance: %d microAlgos", accountInfo.amount);
}
catch (err) {
console.log("err", err);
}
};
paymentTransaction()
10. Full Code
//src/VaultSecret.js
// Azure authentication library to access Azure Key Vault
const { DefaultAzureCredential} = require("@azure/identity")
const { SecretClient } = require("@azure/keyvault-secrets")
require('dotenv').config({path: '../.env'})
const getSecret = async () =>{
try{
// Azure SDK clients accept the credential as a parameter
const credential = new DefaultAzureCredential();
const client = new SecretClient(process.env.KEY_VAULT_URI, credential)
const secret = await client.getSecret(process.env.SECRET_NAME)
const value = secret.value
console.log(value)
return value
}catch(err){
console.log(err)
}
}
getSecret()
module.exports ={
getSecret
}
// src/RecoverAccount.js
const vault = require('./VaultSecret')
const algosdk = require('algosdk')
const recoverAccount = async () =>{
const mnomenic = await vault.getSecret()
const recover = algosdk.mnemonicToSecretKey(mnomenic)
console.log(recover.sk)
}
recoverAccount()
// src/Transaction.js
const vault = require('./VaultSecret')
const algosdk = require('algosdk')
require('dotenv').config({path: '../.env'})
async function paymentTransaction() {
const mnomenic = await vault.getSecret()
const account = algosdk.mnemonicToSecretKey(mnomenic)
const senderAddress = account.addr
try {
// Connect your client
const algodToken = {"X-API-Key": process.env.API_KEY}
const algodServer = 'https://testnet-algorand.api.purestake.io/ps2/';
const algodPort = "";
let algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort);
//Check your balance
let accountInfo = await algodClient.accountInformation(senderAddress).do();
console.log("Account balance: %d microAlgos", accountInfo.amount);
// Construct the transaction
let params = await algodClient.getTransactionParams().do();
// comment out the next two lines to use suggested fee
params.fee = algosdk.ALGORAND_MIN_TX_FEE;
params.flatFee = true;
// receiver defined as TestNet faucet address
const receiver = "HZ57J3K46JIJXILONBBZOHX6BKPXEM2VVXNRFSUED6DKFD5ZD24PMJ3MVA";
const enc = new TextEncoder();
const note = enc.encode("Hello World");
let amount = 1000000;
let sender = senderAddress;
let txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
from: sender,
to: receiver,
amount: amount,
note: note,
suggestedParams: params
});
// Sign the transaction
let signedTxn = txn.signTxn(account.sk);
let txId = txn.txID().toString();
console.log("Signed transaction with txID: %s", txId);
// Submit the transaction
await algodClient.sendRawTransaction(signedTxn).do();
// Wait for confirmation
let confirmedTxn = await algosdk.waitForConfirmation(algodClient, txId, 4);
//Get the completed Transaction
console.log("Transaction " + txId + " confirmed in round " + confirmedTxn["confirmed-round"]);
let string = new TextDecoder().decode(confirmedTxn.txn.txn.note);
console.log("Note field: ", string);
accountInfo = await algodClient.accountInformation(senderAddress).do();
console.log("Transaction Amount: %d microAlgos", confirmedTxn.txn.txn.amt);
console.log("Transaction Fee: %d microAlgos", confirmedTxn.txn.txn.fee);
console.log("Account balance: %d microAlgos", accountInfo.amount);
}
catch (err) {
console.log("err", err);
}
};
paymentTransaction()
11. Run Code
Note
To access the secret ensure you are logged in using the azure cli. Type az login
.
If you are not logged in and you try to retrieve the secret you will see something like fig 10-1 below.
Fig 10-1 Unauthorized Error
Upon successful login your response should look like fig 10-2 below
Fig 10-2 Successful Login
To run the below codes ensure you are in the src
folder
Run VaultSecret Code
Run the code using node VaultSecret.js
This will display your vault secret value.
Fig 10-3 Vault Secret
Run Recover Account Code
Run the code using node RecoverAccount.js
. The output will be the mnemonic value you stored in azure key vault secret.
Fig 10-4 Recover Account Output
Run Transaction Code
Run the code using node Transaction.js
Fig 10-5 Result
AlgoExplorer
Transaction id VMCTXSOCX3DSQUHMGGVMZOSYT4C6H4CXPN3SYSJ5FI2MO47HUBDA
you can check the details of the transaction on the explorer.
Fig 10-6 AlgoExplorer
12. Clear Resource
When no longer needed, delete the resource group, which deletes the Key Vault and related resources. To delete the resource group through the portal:
Enter the name of your resource group in the Search box at the top of the portal. When you see the resource group used in this tutorial in the search results, select it.Select Delete resource group.
In the TYPE THE RESOURCE GROUP NAME: box type in the name of the resource group and select Delete.
Note
It is important to note that once a secret, key, certificate, or key vault is deleted, it will remain recoverable for a configurable period of 7 to 90 calendar days. If no configuration is specified the default recovery period will be set to 90 days. This provides users with sufficient time to notice an accidental secret deletion and respond. For more information about deleting and recovering key vaults and key vault objects, see Azure Key Vault soft-delete overview.
13. Next step
To learn more on Azure Key Vault and Transactions on Algorand. Checkout the links below;
- Set and retrieve a secret from Azure Key Vault using the Azure portal
- Azure Key Vault JavaScript Library
- Azure Identity CLient Library
- Secure Access to Key Vault
- Use Key Vault with App Service Web App
- Azure Key Vault developer’s guide
- Key Vault security overview
- Deploying Sandbox to a Linux VM in Azure
- Creating your First Transaction on Algorand
14. Conclusion
This tutorial covers the basics on how to create Key Vault, sign transactions with retrieved secret value and recover private key.
Warning
This tutorial is intended for learning purposes only. It does not cover error checking and other edge cases. Therefore, it should not be used as a production application.