Encripta y desencripta datos con una clave simétrica

En este tema, se muestra cómo realizar las siguientes operaciones con claves simétricas:

  • Encriptar texto o contenido binario (texto sin formato) con una clave de Cloud KMS
  • Desencriptar cifrado que se encriptó con una clave de Cloud KMS

Si, en cambio, deseas usar una clave asimétrica para la encriptación, consulta Encripta y desencripta datos con una clave asimétrica.

Antes de comenzar

  1. Crea un llavero de claves y una clave como se describe en Crea claves y llaveros de claves.

  2. Asegúrate de que el usuario que llama a los métodos de encriptación y desencriptación tenga los permisos cloudkms.cryptoKeyVersions.useToEncrypt y cloudkms.cryptoKeyVersions.useToDecrypt sobre la clave que se usó para encriptar o desencriptar.

    Una forma de permitirle a un usuario que encripte o desencripte es agregar el usuario a las funciones de IAM roles/cloudkms.cryptoKeyEncrypter, roles/cloudkms.cryptoKeyDecrypter o roles/cloudkms.cryptoKeyEncrypterDecrypter para esa clave. Para obtener más información, consulta Permisos y funciones.

  3. Si vas a usar las bibliotecas cliente para Cloud KMS, instala la biblioteca cliente del lenguaje que prefieras (opcional).

  4. Si vas a usar la herramienta de línea de comandos de gcloud, instala el SDK de Cloud (opcional).

Encripta

Línea de comandos

Para encriptar datos, proporciona la información de clave correcta, especifica el nombre del archivo de texto sin formato que encriptarás y también el nombre del archivo que incluirá el contenido encriptado.

gcloud kms encrypt \
  --location=[LOCATION]  \
  --keyring=[KEY_RING] \
  --key=[KEY] \
  --plaintext-file=[FILEPATH_AND_FILENAME_TO_ENCRYPT] \
  --ciphertext-file=[FILEPATH_AND_FILENAME].enc

Por ejemplo, si text.txt es el nombre del archivo de texto sin formato para encriptar, usa el siguiente comando:

gcloud kms encrypt \
  --location global \
  --keyring my_keyring \
  --key my_key \
  --plaintext-file text.txt \
  --ciphertext-file text.enc

El tamaño del archivo de texto sin formato no debe superar los 64 KiB.

El comando encrypt admite una marca --additional-authenticated-data- file opcional para especificar un archivo que contiene datos autenticados adicionales. El tamaño del archivo de datos autenticados adicionales no debe superar los 64 KiB.

Si --plaintext-file o --additional-authenticated-data-file se configura como -, ese archivo se lee desde stdin. De manera similar, si --ciphertext-file se configura como -, el texto cifrado se escribe en stdout. Cuando utilices la entrada estándar, ten en cuenta que los caracteres de espacio en blanco proporcionados (por ejemplo, otros comandos de shell o saltos de líneas producidos por echo) se incluirán en el cifrado resultante de la encriptación.

El comando encrypt admite una marca --version opcional para indicar la versión de la clave que se utilizará en la encriptación. Según la configuración predeterminada, se usa la versión principal.

En el siguiente ejemplo de encrypt, se muestra cómo especificar una clave de versión y datos autenticados adicionales.

gcloud kms encrypt \
  --location=[LOCATION]  \
  --keyring=[KEY_RING] \
  --key=[KEY] \
  --version=[KEY_VERSION] \
  --additional-authenticated-data-file=[ADDITIONAL_AUTHENTICATED_DATA_FILEPATH_AND_FILENAME] \
  --plaintext-file=[FILEPATH_AND_FILENAME_TO_ENCRYPT] \
  --ciphertext-file=[FILEPATH_AND_FILENAME].enc

Protocolo

El contenido que se debe encriptar y que se envía a Cloud KMS en formato JSON debe estar codificado en Base64. Para obtener más información sobre la codificación y decodificación en Base64, consulta Codificación en Base64.

Para encriptar datos, realiza una solicitud POST, proporciona la información del proyecto y la clave que corresponda, y especifica el texto codificado en Base64 que se encriptará en el campo plaintext del cuerpo de la solicitud. Reemplaza API_KEY por una clave de API válida. Consulta Accede a la API para obtener información sobre cómo generar una clave de API.

POST https://cloudkms.googleapis.com/v1/projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[keyring_name]/cryptoKeys/[key_name]:encrypt&key=API_KEY
{
  "plaintext": "U3VwZXIgc2VjcmV0IHRleHQgdGhhdCBtdXN0IGJlIGVuY3J5cHRlZAo=",
}

En este ejemplo, se usa curl:

curl -s -X POST "https://cloudkms.googleapis.com/v1/projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING_NAME]/cryptoKeys/[KEY_NAME]:encrypt" \
  -d "{\"plaintext\":\"[BASE64_ENCODED_INPUT]\"}" \
  -H "Authorization:Bearer [API_KEY]"\
  -H "Content-Type:application/json"

C#

        public static void Encrypt(string projectId, string locationId, string keyRingId, string cryptoKeyId,
string plaintextFile, string ciphertextFile)
        {
            KeyManagementServiceClient client = KeyManagementServiceClient.Create();
            CryptoKeyName cryptoKeyName =
                new CryptoKeyName(projectId, locationId, keyRingId, cryptoKeyId);

            byte[] plaintext = File.ReadAllBytes(plaintextFile);
            CryptoKeyPathName pathName = CryptoKeyPathName.Parse(cryptoKeyName.ToString());
            EncryptResponse result = client.Encrypt(pathName, ByteString.CopyFrom(plaintext));

            // Output encrypted data to a file.
            File.WriteAllBytes(ciphertextFile, result.Ciphertext.ToByteArray());
            Console.Write($"Encrypted file created: {ciphertextFile}");
        }

Go

import (
	"context"
	"fmt"

	cloudkms "cloud.google.com/go/kms/apiv1"
	kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
)

// encryptSymmetric will encrypt the input plaintext with the specified symmetric key.
func encryptSymmetric(name string, plaintext []byte) ([]byte, error) {
	// name := "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID"
	// plaintext := []byte("Sample message")
	ctx := context.Background()
	client, err := cloudkms.NewKeyManagementClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("cloudkms.NewKeyManagementClient: %v", err)
	}

	// Build the request.
	req := &kmspb.EncryptRequest{
		Name:      name,
		Plaintext: plaintext,
	}
	// Call the API.
	resp, err := client.Encrypt(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("Encrypt: %v", err)
	}
	return resp.Ciphertext, nil
}

Java


/**
 * Encrypts the given plaintext using the specified crypto key.
 */
public static byte[] encrypt(
    String projectId, String locationId, String keyRingId, String cryptoKeyId, byte[] plaintext)
    throws IOException {

  // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup.
  try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {

    // The resource name of the cryptoKey
    String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId);

    // Encrypt the plaintext with Cloud KMS.
    EncryptResponse response = client.encrypt(resourceName, ByteString.copyFrom(plaintext));

    // Extract the ciphertext from the response.
    return response.getCiphertext().toByteArray();
  }
}

Node.js

async function encrypt(
  projectId = 'your-project-id', // Your GCP projectId
  keyRingId = 'my-key-ring', // Name of the crypto key's key ring
  cryptoKeyId = 'my-key', // Name of the crypto key, e.g. "my-key"
  plaintextFileName = './path/to/plaintext.txt',
  ciphertextFileName = './path/to/plaintext.txt.encrypted'
) {
  const fs = require('fs');
  const {promisify} = require('util');

  // Import the library and create a client
  const kms = require('@google-cloud/kms');
  const client = new kms.KeyManagementServiceClient();

  // The location of the crypto key's key ring, e.g. "global"
  const locationId = 'global';

  // Reads the file to be encrypted
  const readFile = promisify(fs.readFile);
  const contentsBuffer = await readFile(plaintextFileName);
  const plaintext = contentsBuffer.toString('base64');
  const name = client.cryptoKeyPath(
    projectId,
    locationId,
    keyRingId,
    cryptoKeyId
  );

  // Encrypts the file using the specified crypto key
  const [result] = await client.encrypt({name, plaintext});
  const writeFile = promisify(fs.writeFile);
  await writeFile(ciphertextFileName, Buffer.from(result.ciphertext, 'base64'));
  console.log(`Encrypted ${plaintextFileName} using ${result.name}.`);
  console.log(`Result saved to ${ciphertextFileName}.`);
}

PHP

use Google\Cloud\Kms\V1\KeyManagementServiceClient;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $locationId = 'The location ID of the crypto key. Can be "global", "us-west1", etc.';
// $keyRingId = 'The KMS key ring ID';
// $cryptoKeyId = 'The KMS key ID';
// $plaintextFileName = 'The path to the file containing plaintext to encrypt';
// $ciphertextFileName = 'The path to write the ciphertext';

$kms = new KeyManagementServiceClient();

// The resource name of the CryptoKey.
$cryptoKeyName = $kms->cryptoKeyName($projectId, $locationId, $keyRingId, $cryptoKeyId);

$plaintext = file_get_contents($plaintextFileName);
$response = $kms->encrypt($cryptoKeyName, $plaintext);

// Write the encrypted text to a file.
file_put_contents($ciphertextFileName, $response->getCiphertext());
printf('Saved encrypted text to %s' . PHP_EOL, $ciphertextFileName);

Python

def encrypt_symmetric(project_id, location_id, key_ring_id, crypto_key_id,
                      plaintext):
    """Encrypts input plaintext data using the provided symmetric CryptoKey."""

    from google.cloud import kms_v1

    # Creates an API client for the KMS API.
    client = kms_v1.KeyManagementServiceClient()

    # The resource name of the CryptoKey.
    name = client.crypto_key_path_path(project_id, location_id, key_ring_id,
                                       crypto_key_id)

    # Use the KMS API to encrypt the data.
    response = client.encrypt(name, plaintext)
    return response.ciphertext

Ruby

# project_id      = "Your Google Cloud project ID"
# location_id     = "The location of the key ring"
# key_ring_id     = "The ID of the key ring"
# crypto_key_id   = "The ID of the crypto key"
# plaintext_file  = "File to encrypt"
# ciphertext_file = "File to store encrypted input data"

require "google/cloud/kms/v1"
CloudKMS = Google::Cloud::Kms::V1

# Initialize the client
client = CloudKMS::KeyManagementServiceClient.new

# The crypto key to use
crypto_key = CloudKMS::KeyManagementServiceClient.crypto_key_path(
  project_id, location_id, key_ring_id, crypto_key_id
)

# Read the secret data from the file
plaintext = File.open(plaintext_file, "rb", &:read)

# Use the KMS API to encrypt the data
response = client.encrypt crypto_key, plaintext

# Write the encrypted binary data to the output file
File.open(ciphertext_file, "wb") { |f| f.write response.ciphertext }

puts "Saved encrypted #{plaintext_file} as #{ciphertext_file}"

Desencripta

Línea de comandos

Para desencriptar los datos, proporciona la información de la clave adecuada, especifica el nombre del archivo encriptado (archivo cifrado) que se desencriptará y el nombre del archivo en el que se guardará el contenido desencriptado.

gcloud kms decrypt \
  --location=[LOCATION] \
  --keyring=[KEY_RING] \
  --key=[KEY] \
  --ciphertext-file=[FILEPATH_AND_FILENAME_TO_DECRYPT] \
  --plaintext-file=[FILEPATH_AND_FILENAME_TO_DECRYPT].dec

Por ejemplo, si el nombre del archivo de texto cifrado para desencriptar es text.enc, usa un comando como el siguiente:

gcloud kms decrypt \
  --location=global \
  --keyring=my_keyring \
  --key=my_key \
  --ciphertext-file=text.enc \
  --plaintext-file=text.dec

El comando decrypt admite una marca --additional-authenticated-data- file opcional para especificar un archivo que contiene datos autenticados adicionales. El tamaño del archivo de datos autenticados adicionales no debe superar los 64 KiB.

Si --ciphertext-file o --additional-authenticated-data-file se configura como -, ese archivo se lee desde stdin. De manera similar, si --plaintext-file se configura como -, el texto sin formato desencriptado se escribe en stdout. Cuando utilices la entrada estándar, ten en cuenta que los caracteres de espacios en blanco proporcionados (por ejemplo, otros comandos de shell o saltos de líneas producidos por echo) se incluirán en el intento de desencriptación.

En el siguiente ejemplo de decrypt, se muestra cómo especificar datos autenticados adicionales.

gcloud kms decrypt \
  --location=[LOCATION] \
  --keyring=[KEY_RING] \
  --key=[KEY] \
  --additional-authenticated-data-file=[ADDITIONAL_AUTHENTICATED_DATA_FILEPATH_AND_FILENAME] \
  --ciphertext-file=[FILEPATH_AND_FILENAME_TO_DECRYPT] \
  --plaintext-file=[FILEPATH_AND_FILENAME_TO_DECRYPT].dec

Protocolo

El texto desencriptado que se muestra en el archivo JSON de Cloud KMS está codificado en Base64. Para obtener más información sobre la codificación y decodificación en Base64, consulta Codificación en Base64.

Para desencriptar datos, haz una solicitud POST y proporciona la información del proyecto y de la clave correspondientes, y especifica el texto encriptado (cifrado) que se desencriptará en el campo ciphertext del cuerpo de la solicitud. Reemplaza API_KEY por una clave de API válida. Consulta Accede a la API para obtener información sobre cómo generar una clave de API.

POST https://cloudkms.googleapis.com/v1/projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING_NAME]/cryptoKeys/[KEY_NAME]:decrypt&key=API_KEY
{
  "ciphertext": "CiQAhMwwBo61cHas7dDgifrUFs5zNzBJ2uZtVFq4ZPEl6fUVT4kSmQ...",
}

En este ejemplo, se usa curl:

curl -s -X POST "https://cloudkms.googleapis.com/v1/projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING_NAME]/cryptoKeys/[KEY_NAME]:decrypt" \
  -d "{\"ciphertext\":\"[ENCRYPTED_CONTENT]\"}" \
  -H "Authorization:Bearer [API_KEY]"\
  -H "Content-Type:application/json"

C#

        public static void Decrypt(string projectId, string locationId, string keyRingId, string cryptoKeyId,
    string ciphertextFile, string plaintextFile)
        {
            KeyManagementServiceClient client = KeyManagementServiceClient.Create();
            CryptoKeyName cryptoKeyName =
                new CryptoKeyName(projectId, locationId, keyRingId, cryptoKeyId);

            byte[] ciphertext = File.ReadAllBytes(ciphertextFile);
            DecryptResponse result = client.Decrypt(cryptoKeyName, ByteString.CopyFrom(ciphertext));

            // Output decrypted data to a file.
            File.WriteAllBytes(plaintextFile, result.Plaintext.ToByteArray());
            Console.Write($"Decrypted file created: {plaintextFile}");
        }

Go

import (
	"context"
	"fmt"

	cloudkms "cloud.google.com/go/kms/apiv1"
	kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
)

// decryptSymmetric will decrypt the input ciphertext bytes using the specified symmetric key.
func decryptSymmetric(name string, ciphertext []byte) ([]byte, error) {
	// name := "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID"
	// cipherBytes, err := encryptRSA(rsaDecryptPath, []byte("Sample message"))
	// if err != nil {
	//   return nil, fmt.Errorf("encryptRSA: %v", err)
	// }
	// ciphertext := base64.StdEncoding.EncodeToString(cipherBytes)
	ctx := context.Background()
	client, err := cloudkms.NewKeyManagementClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("cloudkms.NewKeyManagementClient: %v", err)
	}

	// Build the request.
	req := &kmspb.DecryptRequest{
		Name:       name,
		Ciphertext: ciphertext,
	}
	// Call the API.
	resp, err := client.Decrypt(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("Decrypt: %v", err)
	}
	return resp.Plaintext, nil
}

Java


/**
 * Decrypts the provided ciphertext with the specified crypto key.
 */
public static byte[] decrypt(
    String projectId, String locationId, String keyRingId, String cryptoKeyId, byte[] ciphertext)
    throws IOException {

  // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup.
  try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {

    // The resource name of the cryptoKey
    String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId);

    // Decrypt the ciphertext with Cloud KMS.
    DecryptResponse response = client.decrypt(resourceName, ByteString.copyFrom(ciphertext));

    // Extract the plaintext from the response.
    return response.getPlaintext().toByteArray();
  }
}

Node.js

async function decrypt(
  projectId = 'your-project-id', // Your GCP projectId
  keyRingId = 'my-key-ring', // Name of the crypto key's key ring
  cryptoKeyId = 'my-key', // Name of the crypto key, e.g. "my-key"
  ciphertextFileName = './path/to/plaintext.txt.encrypted',
  plaintextFileName = './path/to/plaintext.txt.decrypted'
) {
  const fs = require('fs');
  const {promisify} = require('util');

  // Import the library and create a client
  const kms = require('@google-cloud/kms');
  const client = new kms.KeyManagementServiceClient();

  // The location of the crypto key's key ring, e.g. "global"
  const locationId = 'global';

  // Reads the file to be decrypted
  const readFile = promisify(fs.readFile);
  const contentsBuffer = await readFile(ciphertextFileName);
  const name = client.cryptoKeyPath(
    projectId,
    locationId,
    keyRingId,
    cryptoKeyId
  );
  const ciphertext = contentsBuffer.toString('base64');

  // Decrypts the file using the specified crypto key
  const [result] = await client.decrypt({name, ciphertext});

  // Writes the decrypted file to disk
  const writeFile = promisify(fs.writeFile);
  await writeFile(plaintextFileName, Buffer.from(result.plaintext, 'base64'));
  console.log(
    `Decrypted ${ciphertextFileName}, result saved to ${plaintextFileName}.`
  );
}

PHP

use Google\Cloud\Kms\V1\KeyManagementServiceClient;
use Google\Cloud\Kms\V1\CryptoKey;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $locationId = 'The location ID of the crypto key. Can be "global", "us-west1", etc.';
// $keyRingId = 'The KMS key ring ID';
// $cryptoKeyId = 'The KMS key ID';
// $ciphertextFileName = 'The path to the file containing ciphertext to decrypt';
// $plaintextFileName = 'The path to write the plaintext';

$kms = new KeyManagementServiceClient();

// The resource name of the CryptoKey.
$cryptoKey = new CryptoKey();
$cryptoKeyName = $kms->cryptoKeyName($projectId, $locationId, $keyRingId, $cryptoKeyId);

$ciphertext = file_get_contents($ciphertextFileName);
$response = $kms->decrypt($cryptoKeyName, $ciphertext);

// Write the encrypted text to a file.
file_put_contents($plaintextFileName, $response->getPlaintext());
printf('Saved decrypted text to %s' . PHP_EOL, $plaintextFileName);

Python

def decrypt_symmetric(project_id, location_id, key_ring_id, crypto_key_id,
                      ciphertext):
    """Decrypts input ciphertext using the provided symmetric CryptoKey."""

    from google.cloud import kms_v1

    # Creates an API client for the KMS API.
    client = kms_v1.KeyManagementServiceClient()

    # The resource name of the CryptoKey.
    name = client.crypto_key_path_path(project_id, location_id, key_ring_id,
                                       crypto_key_id)
    # Use the KMS API to decrypt the data.
    response = client.decrypt(name, ciphertext)
    return response.plaintext

Ruby

# project_id    = "Your Google Cloud project ID"
# location_id   = "The location of the key ring"
# key_ring_id   = "The ID of the key ring"
# crypto_key_id = "The ID of the crypto key"
# ciphertext_file = "File to decrypt"
# plaintext_file  = "File to store decrypted data"

require "google/cloud/kms/v1"
CloudKMS = Google::Cloud::Kms::V1

# Initialize the client
client = CloudKMS::KeyManagementServiceClient.new

# The crypto key to use
crypto_key = CloudKMS::KeyManagementServiceClient.crypto_key_path(
  project_id, location_id, key_ring_id, crypto_key_id
)

# Read the encrypted data from the file
ciphertext = File.open(ciphertext_file, "rb", &:read)

# Use the KMS API to decrypt the data
response = client.decrypt crypto_key, ciphertext

# Write the decrypted text to the output file
File.open(plaintext_file, "wb") { |f| f.write response.plaintext }

puts "Saved decrypted #{ciphertext_file} as #{plaintext_file}"

Qué sigue

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Cloud KMS