0

I've been trying to read documentation, and watching a few of their videos but I'm not entirely clear on how I store a private key using GCP's Cloud KMS.

Is the idea for me to store the private key in storage, then use Cloud KMS to encrypt it? How can I make this key available as a secret to my application?

I know this is a very basic question, but I couldn't find an easy breakdown on how to do this - I'm looking for a simple explanation about the concept. Thanks!

nkhil
  • 1,452
  • 1
  • 18
  • 37

2 Answers2

3

Please read for yourself: https://cloud.google.com/kms/docs ...maybe you'll come up with a more focused question. And I think that there's a slight misunderstanding - you'd only be able to retrieve these on the server-side, but not client-side (else the client would need to have the RSA private key of the service account, which has access to Cloud KMS, which is a security breach by itself). So this is generally only useful for a) server-side applications and b) eg. Google Cloud Build.

Generally one has to:

  1. create the keyring with gcloud kms keyrings create

  2. create the key with gcloud kms keys create

  3. then use gcloud kms encrypt and gcloud kms decrypt

I can also provide a usage example (it assumes a key-ring with a key). Just to show, that one doesn't necessarily have to setup secrets. gcloud kms can well provide build secrets - assuming that one can use a service-account with role roles/cloudkms.cryptoKeyEncrypterDecrypter. The given example decrypts all kinds of build secrets - without having to deal with any base64 encoded binary files in meta-data (which is rather a workaround than an actual solution).

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
1

This is a high level description of storing a private key on Google Cloud Platform (GCP):

I ended up using Google KMS, specifically asymmetric encryption feature.

The general steps to create an asymmetric key are:

  • Create a keyring within your project
  • Create a key with ENCRYPT_DECRYPT purpose (if like me, you're trying to do this using Terraform, there's some documentation here

Once we've created the key, we can now encrypt some data we want to secure using the public key from the asymmetric key we created in the previous step.

It is important to note that with an asymmetric key, there is a public-private key pair, and we never handle the private key (i.e. only GCP knows the private key).

Here's how you'd encrypt some data from your local computer:

echo -n my-secret-password | gcloud kms encrypt \
> --project my-project \
> --location us-central1 \
> --keyring my-key-ring \
> --key my-crypto-key \
> --plaintext-file - \
> --ciphertext-file - \
> | base64

This will output some cyphertext with base64 encoding, for eg:

CiQAqD+xX4SXOSziF4a8JYvq4spfAuWhhYSNul33H85HnVtNQW4SOgDu2UZ46dQCRFl5MF6ekabviN8xq+F+2035ZJ85B+xTYXqNf4mZs0RJitnWWuXlYQh6axnnJYu3kDU=

This cyphertext then needs to be stored as a secret. Once stored as a secret, we need to do the following in our application code in order to decrypt the cyphertext into a usable format.

Here is an example of decrypting the cyphertext using the @google-cloud/kms module: https://cloud.google.com/kms/docs/hsm#kms-decrypt-symmetric-nodejs

This is what it looks like in Nodejs:

//
// TODO(developer): Uncomment these variables before running the sample.
//
// const projectId = 'my-project';
// const locationId = 'us-east1';
// const keyRingId = 'my-key-ring';
// const keyId = 'my-key';
// Ciphertext must be either a Buffer object or a base-64 encoded string
// const ciphertext = Buffer.from('...');

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the key name
const keyName = client.cryptoKeyPath(projectId, locationId, keyRingId, keyId);

// Optional, but recommended: compute ciphertext's CRC32C.
const crc32c = require('fast-crc32c');
const ciphertextCrc32c = crc32c.calculate(ciphertext);

async function decryptSymmetric() {
  const [decryptResponse] = await client.decrypt({
    name: keyName,
    ciphertext: ciphertext,
    ciphertextCrc32c: {
      value: ciphertextCrc32c,
    },
  });

  // Optional, but recommended: perform integrity verification on decryptResponse.
  // For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
  // https://cloud.google.com/kms/docs/data-integrity-guidelines
  if (
    crc32c.calculate(decryptResponse.plaintext) !==
    Number(decryptResponse.plaintextCrc32c.value)
  ) {
    throw new Error('Decrypt: response corrupted in-transit');
  }

  const plaintext = decryptResponse.plaintext.toString();

  console.log(`Plaintext: ${plaintext}`);
  return plaintext;
}

return decryptSymmetric();
nkhil
  • 1,452
  • 1
  • 18
  • 37
  • is private key ever revealed to us ? and suppose let say we want to move from google cloud to aws how do we do that ? – prt Jan 02 '23 at 09:54
  • @prt The main feature of using KMS to encrypt/decrypt data is that you never get the private key (in the context of your code). You make a network request to KMS where your data is encrypted/decrypted and the result is returned. In other words, the private key used to encrypt/decrypt your data never leaves KMS. To answer your question about migrating to AWS, I do not know the answer to this. – nkhil Jan 03 '23 at 13:47
  • Thanks a lot! I talked to a friend, he suggested during migration i have to decrypt entire data using current key and then migrate un encrypted data to aws. There is no meaning of migrating private key as it will create 2 source of truth. – prt Jan 04 '23 at 00:59