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!
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:
ENCRYPT_DECRYPT
purpose (if like me, you're trying to do this using Terraform, there's some documentation hereOnce 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();