Blogs

How to authorize Flow Blockchain transactions with Google Cloud Key Management Service

Category
Software development
How to authorize Flow Blockchain transactions with Google Cloud Key Management Service

“If you want to keep a secret, you must also hide it from yourself.”

George Orwell, 1984

Using a service like GCP (Google Cloud Platform) or AWS (Amazon Web Service) to outsource private storage and manage secrets such as API and Encryption keys is becoming a common practice. It provides the developer with a cleaner code that has less chance of leaking sensitive information. 

Coincidentally, encryption and storage of private keys is especially important in the Flow blockchain (https://www.onflow.org/). This NFT based  blockchain requires a 128 character hexadecimal string public key to create an account and the corresponding private key to sign the account’s transactions.



This article will demonstrate how to make use of GCP KMS  (Google Cloud Platform Key Management Service) and a npm library I’ve recently created: fcl-kms-gcp-authorizer (https://github.com/lukaracki/fcl-kms-gcp-authorizer). I will explain how to use said library to create an authorization object in order to sign transactions on the flow blockchain via the Flow JavaScript SDK

A lot of fancy words, but actually it’s not that hard, so let’s get started:

The setup

Note:
For the sake of not having this guide be too long, I will assume that you already have a NodeJs based flow backend project setup, something like: https://github.com/onflow/kitty-items/tree/master/api. If that is not the case, please refer to the README.md file located in the root folder of the repository linked above, and follow the steps described there.

Before using the npm library fcl-kms-gcp-authorizer the steps described in the following sections have to be completed.

Library Installation

The first step is to install the library fcl-kms-gcp-authorizer npm library. To do so navigate to your project folder’s repository and execute the following bash script:

$ npm install fcl-gcp-kms-authorizer

This library uses ECDSA_P256, SHA2_256 based keys. In the next step of this blog post, we will need to generate a key in the GCP KMS with the following settings(*):

* Protection level: Software
* Purpose: Asymmetric sign
* Default algorithm: Elliptic Curve P-256 key, SHA256 Digest

GCP KMS Setup

Once we have the above-mentioned library installed it is time to set up our cloud infrastructure. Let’s start by configuring a GCP service account and obtaining a public key from the GCP KMS. 

Obviously, you can’t create a service account if you don’t already have a Google project, so you can go ahead and create a new Google project or use an existing one. (​​https://cloud.google.com/resource-manager/docs/creating-managing-projects)

For your application to be able to access and use GCP KMS, it will need a service account with correctly configured privileges and access rights. The first section in the following Google documentation contains a quick explanation on how to create a service account: https://cloud.google.com/docs/authentication/getting-started

Note:
After creating the service account, make sure to assign it the Cloud KMS Admin role. Here’s a helpful link from the Google docs: https://cloud.google.com/iam/docs/granting-changing-revoking-access 

Once you have done this, it’s time to proceed to the next step, which is creating a public key to use for the generation of your flow account. Again, Google provides detailed instructions on how to do it, so make sure to follow the steps from this tutorial: https://cloud.google.com/kms/docs/creating-asymmetric-keys

The appropriate settings to choose when creating the key are shown in the picture below.

Important!:
Make sure to set the previously noted settings(*) when creating the key, as shown in the image above:
Purpose: Asymmetric sign 
Key type and algorithm: Elliptic Curve P-256 key, SHA256 Digest

After you’ve created your key, copy the key’s resource ID and save it somewhere for later. This Google documentation page demonstrates how to get a key’s resource ID: https://cloud.google.com/kms/docs/getting-resource-ids

We will use this resource ID in a later step to create an instance of the GCP KMS Authorizer, so make sure to save it somewhere. Here’s a code snippet showing an example of saving and using the resource ID:

const resourceId: string = {yourResourceId}
const authorizer = new GcpKmsAuthorizer(resourceId);

Replace yourResourceName with (yes, indeed), your resource name.

For example:

yourResourceId = 'projects/your-project-name/locations/global/keyRings/flow/cryptoKeys/flow-minter-key'

Using the @google-cloud/kms library requires authentication with Google. It is recommended to use an environment variable to set up the authentication using a Google account authentication JSON file (one from the previous step while creating your service account). This variable only applies to your current shell session, so if you open a new session, set the variable again. If you need any help, check out the “Setting the environment variable” paragraph on the following link: https://cloud.google.com/docs/authentication/getting-started

Here’s bash example used to link the Google environment variable to your authentication JSON:

$ export GOOGLE_APPLICATION_CREDENTIALS= "PATH"

Replace PATH with the value with the path of the JSON file that contains your service account key.

For example:

# export GOOGLE_APPLICATION_CREDENTIALS= /home/user/Downloads/service-account-file.json

After completing all the steps above, we should be ready for the next step which is creating our Flow Account, using the GCP KMS Library & the Flow Blockchain.

Flow Account Creation using GCP KMS Raw Hex Key

To create an account on the Flow blockchain, you need to specify a 128 hexadecimal public key. You can obtain the 128 Raw Hex version of your GCP public key by asn1parsing your PEM formatted public key from GCP, and then removing the first 2 bytes. There’s a simpler way though, the npm fcl-gcp-kms-authorizer library can do that for you. 

Inside of your pre-existing Flow NodeJS backend project create a new TypeScript file and paste the following code:

import { GcpKmsAuthorizer } from ''fcl-gcp-kms-authorizer”;
async function main() {
  // Your GCP Resource Name Goes Here
  const resourceId: string =   'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1';
  const authorizer = new GcpKmsAuthorizer(resourceId);
  const publicKey = await authorizer.getPublicKey();
  console.log('\nFetched Raw Hex Public Key: ' + publicKey);
}
main().catch(e => console.error(e));

If everything was setup correctly, after compiling and executing, the program should output your raw hex formatted public key, the key should be in 128 hexadecimal format. 

For example: 

ee3df35fdb6aaa1e84ee27c2cb9dd98b57d951b74b64fef13a70b9ce2ac659b1a41f0f352824e2c1a3622d44db41we02192b49285de

Now that we got our key, we can finally create a flow account. There are several ways to create an account. For details, please refer to Flow documentation.

Using Flow CLI

Using Flow Testnet Faucet (for Testnet)

Using Flow Go SDK

Important!:
When creating your flow account using your fetched public key, make sure to use the same encryption algorithm that we used when we created our GCP public key.

Signature Algorithm: ECDSA_P256

Hash Algorithm: SHA2_256

Here’s a bash example for creating a public key with the SHA2_256 hash algorithm by using the Flow CLI, (the signature algorithm defaults to ECDSA_P256 so we don’t have to specify it when using the Flow CLI).

$ flow accounts create \ 
      --key ee3df35fdb6aaa1e84ee27c2cb9dd98b57d951b74b64fef13a70b9ce2ac659b1a41f0f352824e2c1a3622d44db417e02172b49285de5dee3c90ad612b990447c \
      --hash-algo SHA2_256

Once you’ve created your account by using your GCP KMS public key, you should’ve received your account’s address and you’re good to go! You can setup authentication inside your Flow project’s flow.json by adding the following lines:

Important!:
Make sure to replace the account address with your account’s address and the resourceID with your key’s resource name!

“accounts”:{
"admin-account": {
      "address": "0xfa5c16359bca3cfd", // <- Your account’s address
      "key": {
        "type": "google-kms",
        "index": 0,
        "signatureAlgorithm": "ECDSA_P256",
        "hashAlgorithm": "SHA2_256",
        "resourceID": "projects/your-project-name/locations/global/keyRings/flow/cryptoKeys/flow-minter-key" <- Your account’s resource name
      }
    }
}

By adding these lines to your flow.json, you’ve enabled Flow CLI to authenticate with the GCP KMS. In the next section, I’ll show you an example of how to create an authorization function by using the fcl-gcp-kms-authorizer library to authorize transactions inside of your NodeJS Flow backend application.

Usage example

We’ve finally completed the setup part, let’s get right into the example of creating an authorization function. It’s super easy. 

First we use our resource name to create an instance of the GCP KMS Authorizer.

const resourceId: string =    'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1'; <- Your GCP Resource Name
const authorizer = new GcpKmsAuthorizer(resourceId);

Then, to create an authorization function, we use our accounts address and key index (which we received after creating our account). 

const address = '0x01cf0e2f2f715450'; <- Your Flow Account Address
const keyIndex = 0; <- Your Flow Key Index
const authorization = authorizer.authorize(address, keyIndex);

After that, we can simply use the authorization function to authorize transactions inside the Flow Javascript SDK:

const response = await fcl.send([
    fcl.transaction`
      transaction {
        prepare(signer: AuthAccount) {
          log("Test transaction signed by fcl-gcp-kms-authorizer")
        }
      }
    `,
    fcl.args([]),
    fcl.proposer(authorization),
    fcl.authorizations([authorization]),
    fcl.payer(authorization),
    fcl.limit(9999),
  ]);

Finally, here’s a full code example of using all the functions from the fcl-gcp-kms-authorize library.

Note:
In the following code example I’m using an emulator created account and I’m connecting to the emulator api access node which is run on my localhost. I’ve previously created a flow emulator account by using the flow accounts create bash command.

import { GcpKmsAuthorizer } from '../src/auth/authorizer';
import * as fcl from '@onflow/fcl';
// emulator url
const apiUrl = 'http://localhost:8080';
fcl.config().put('accessNode.api', apiUrl);
async function main() {
// Your GCP resource name
  const resourceId: string = 'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1';
// Your account key (emulator or testnet)
// Create account first using flow accounts create --key {yourRawHexPublicKey}
  const address = '0x01cf0e2f2f715450';
  const keyIndex = 0;
  const authorizer = new GcpKmsAuthorizer(resourceId);
  const authorization = authorizer.authorize(address, keyIndex);
  const response = await fcl.send([
    fcl.transaction`
      transaction {
        prepare(signer: AuthAccount) {
          log("Test transaction signed by fcl-gcp-kms-authorizer")
        }
      }
    `,
    fcl.args([]),
    fcl.proposer(authorization),
    fcl.authorizations([authorization]),
    fcl.payer(authorization),
    fcl.limit(9999),
  ]);
  console.log('=====Transaction Succeeded=====\n');
  const publicKey = await authorizer.getPublicKey();
  const flowPublicKey = await authorizer.getFlowPublicKey();
  console.log('\nFetched Raw Hex Public Key: ' + publicKey);
  console.log('\nFetched Flow Public Key: ' + flowPublicKey + '\n');
}
main().catch(e => console.error(e));

Conclusion

Concluding this blog post, hopefully you’ve learned how to authenticate your Flow transactions by using the GCP KMS.

Special thanks to https://github.com/doublejumptokyo for creating the AWS version of this library and who inspired me to make the GCP version! He’s been a huge help as I’ve forked most of his code and adjusted it to work with the Google Cloud Platform. The npm package is currently in it’s 0.0.1 version and I will keep updating it and adding new features as the Flow blockchain ecosystem keeps developing.

Thank you for reading this through! I hope you enjoyed it and can make use of the knowledge you’ve received. 

Next

Blog

Off-the-shelf vs Custom-Made Software

Company

Our people really love it here

How it all started

Est. in 2014., gathering eight employees with eyes set on the future. No matter how set they were, they couldn’t predict the success and extent of growth that would ensue. Today there are more than 100 of us, and people are here to stay.

Stability in unstable times

The turmoil of 2020 caused great inconvenience for people all over the world. However, this did not affect our business. Quite the opposite — we not only kept all jobs and salaries intact, but we also grew in size. And we keep expanding. 

Contact

We’d love to hear from you