Como criptografar e descriptografar dados com uma chave simétrica

Neste tópico, mostramos como fazer o seguinte:

  • Criptografar texto ou conteúdo binário (texto simples) usando uma chave do Cloud KMS.
  • descriptografar texto cifrado que foi criptografado com uma chave do Cloud KMS.

Configuração

  • Antes de criptografar ou descriptografar dados, você precisa criar um keyring e uma chave, conforme descrito em Como criar keyrings e chaves.

    Por motivos de segurança, o material bruto da chave criptográfica representado por uma chave do Cloud KMS nunca é visto nem exportado. Só pode ser usado por um usuário autorizado para criptografar ou descriptografar dados quando eles invocam a API Cloud KMS.

  • Assegure-se de que o usuário que está chamando os métodos de criptografia e descriptografia tenha as permissões cloudkms.cryptoKeyVersions.useToEncrypt e cloudkms.cryptoKeyVersions.useToDecrypt para a chave usada na criptografia ou descriptografia.

    Uma maneira de permitir que um usuário criptografe ou descriptografe usando uma chave é adicioná-lo aos papéis de IAM roles/cloudkms.cryptoKeyEncrypter, roles/cloudkms.cryptoKeyDecrypter ou roles/cloudkms.cryptoKeyEncrypterDecrypter referentes a essa chave. Para mais informações, consulte Permissões e papéis.

  • Se você for usar bibliotecas de cliente para o Cloud KMS, instale a biblioteca de cliente do idioma de sua preferência.

  • Se você for usar a ferramenta de linha de comando gcloud para o Cloud KMS, instale o SDK do Google Cloud.

Criptografia

Linha de comando

Para criptografar dados, forneça as informações de chave apropriadas, especifique o nome do arquivo de texto simples a ser criptografado e o nome do arquivo com o conteúdo criptografado.

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

O arquivo de texto simples não pode ultrapassar 64 KiB.

O comando encrypt é compatível com uma sinalização --additional-authenticated-data- file opcional para especificar um arquivo com dados autenticados extras. O arquivo de dados autenticados adicionais não pode ultrapassar 64 KiB.

Caso o --plaintext-file ou --additional-authenticated-data-file esteja configurado para -, esse arquivo será lido a partir do stdin. Da mesma forma, caso o --ciphertext-file esteja configurado para -, o texto cifrado será gravado no stdout.

O comando encrypt é compatível com uma sinalização --version opcional para indicar a versão da chave a ser usada para criptografia. Por padrão, é usada a versão principal.

O exemplo encrypt a seguir mostra como especificar uma chave de versão e dados autenticados adicionais.

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

É preciso que o conteúdo a ser criptografado enviado para o Cloud KMS em JSON seja codificado em base64. Para informações sobre como codificar e descodificar usando base64, consulte codificação em base64.

Para criptografar os dados, faça uma solicitação POST e forneça o projeto apropriado e as informações de chaves, e especifique o texto codificado em base64 a ser criptografado no campo plaintext do corpo da solicitação. Substitua API_KEY por uma chave de API válida. Para informações sobre como gerar uma chave de API, consulte Como acessar a API.

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

Veja aqui um exemplo que 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

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

	// Build the request.
	req := &kmspb.EncryptRequest{
		Name:      keyName,
		Plaintext: plaintext,
	}
	// Call the API.
	resp, err := client.Encrypt(ctx, req)
	if err != nil {
		return nil, 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."""

    # 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}"
  

Descriptografia

Linha de comando

Para descriptografar dados, forneça as informações de chave apropriadas, especifique o nome do arquivo criptografado, ou seja, o arquivo cifrado a ser descriptografado e especifique o nome do arquivo com o conteúdo descriptografado.

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

O comando decrypt é compatível com uma sinalização --additional-authenticated-data- file opcional para especificar um arquivo com dados autenticados extras. O arquivo de dados autenticados adicionais não pode ultrapassar 64 KiB.

Quando --ciphertext-file ou --additional-authenticated-data-file está configurado para -, esse arquivo é lido a partir do stdin. Da mesma forma, quando --plaintext-file está configurado para -, o texto simples descriptografado é gravado em stdout.

O seguinte exemplo de decrypt mostra como especificar dados autenticados adicionais.

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

O texto descriptografado retornado no JSON a partir do Cloud KMS é codificado em base64. Para informações sobre como codificar e descodificar usando base64, consulte codificação em base64.

Para descriptografar os dados, faça uma solicitação POST e forneça o projeto apropriado e as informações de chaves e especifique o texto a ser descriptografado no campo ciphertext do corpo da solicitação. Substitua API_KEY por uma chave de API válida. Para informações sobre como gerar uma chave de API, consulte Como acessar a API.

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

Veja aqui um exemplo que 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

       
// decrypt will decrypt the input ciphertext bytes using the specified symmetric key
// example keyName: "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID"
func decryptSymmetric(keyName string, ciphertext []byte) ([]byte, error) {
	ctx := context.Background()
	client, err := cloudkms.NewKeyManagementClient(ctx)
	if err != nil {
		return nil, err
	}

	// Build the request.
	req := &kmspb.DecryptRequest{
		Name:       keyName,
		Ciphertext: ciphertext,
	}
	// Call the API.
	resp, err := client.Decrypt(ctx, req)
	if err != nil {
		return nil, 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."""

    # 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}"
  

Próximas etapas

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Cloud KMS