Crittografia e decriptazione dei dati con una chiave asimmetrica

Questo argomento fornisce informazioni sulla creazione e sull'utilizzo di una chiave per la crittografia asimmetrica utilizzando una chiave RSA. Se vuoi utilizzare chiavi asimmetriche per creare e convalidare le firme, consulta Creazione e convalida di firme digitali. Se vuoi utilizzare chiavi simmetriche per la crittografia e la decrittografia, consulta Crittografia e decrittografia dei dati.

La crittografia asimmetrica utilizza la parte della chiave pubblica della chiave asimmetrica, mentre la decrittografia utilizza la parte della chiave privata della chiave. Cloud Key Management Service fornisce funzionalità per recuperare la chiave pubblica e per decriptare il testo crittografato con la chiave pubblica. Cloud KMS non consente l'accesso diretto alla chiave privata.

Prima di iniziare

  • Questo argomento fornisce esempi che vengono eseguiti nella riga di comando. Per semplificare l'utilizzo degli esempi, utilizza Cloud Shell. L'esempio di crittografia utilizza OpenSSL, che è preinstallato in Cloud Shell.

  • Crea una chiave asimmetrica con scopo della chiave di ASYMMETRIC_DECRYPT. Per vedere quali algoritmi sono supportati per lo scopo della chiave ASYMMETRIC_DECRYPT, consulta Algoritmi di crittografia asimmetrica. Non puoi seguire questa procedura con una chiave con lo scopo ASYMMETRIC_SIGN.

  • Se utilizzerai la riga di comando, installa OpenSSL se non l'hai già fatto. Se utilizzi Cloud Shell, OpenSSL è già installato.

  • Utenti macOS: La versione di OpenSSL installata su macOS non supporta i flag utilizzati per decriptare i dati in questo argomento. Per seguire questi passaggi su macOS, installa OpenSSL da Homebrew.

Controllo dell'accesso alla chiave

  • Per un utente o un servizio che recupererà la chiave pubblica, concedi l'autorizzazione cloudkms.cryptoKeyVersions.viewPublicKey sulla chiave asimmetrica. La chiave pubblica è necessaria per criptare i dati.

  • Per un utente o un servizio che decripterà i dati criptati con la chiave pubblica, concedi l'autorizzazione cloudkms.cryptoKeyVersions.useToDecrypt sulla chiave asimmetrica.

Scopri di più su autorizzazioni e ruoli in Cloud KMS in Autorizzazioni e ruoli.

Criptare i dati

Per criptare i dati utilizzando una chiave di crittografia asimmetrica, recupera la chiave pubblica e utilizzala per criptare i dati.

gcloud

Questo esempio richiede l'installazione di OpenSSL sul sistema locale.

Scaricare la chiave pubblica

Scarica la chiave pubblica:

gcloud kms keys versions get-public-key key-version \
    --key key \
    --keyring key-ring \
    --location location  \
    --output-file public-key-path

Sostituisci key-version con la versione della chiave che contiene la chiave pubblica. Sostituisci key con il nome della chiave. Sostituisci key-ring con il nome del keyring in cui si trova la chiave. Sostituisci location con la località Cloud KMS per il keyring. Sostituisci public-key-path con la località in cui salvare la chiave pubblica sul sistema locale.

Criptare i dati

Cripta i dati utilizzando la chiave pubblica appena scaricata e salva l'output in un file:

openssl pkeyutl -in cleartext-data-input-file \
    -encrypt \
    -pubin \
    -inkey public-key-path \
    -pkeyopt rsa_padding_mode:oaep \
    -pkeyopt rsa_oaep_md:sha256 \
    -pkeyopt rsa_mgf1_md:sha256 \
    > encrypted-data-output-file
  • Sostituisci cleartext-data-input-file con il percorso e il nome del file da criptare.

  • Sostituisci public-key-path con il percorso e il nome del file in cui hai scaricato la chiave pubblica.

  • Sostituisci encrypted-data-output-file con il percorso e il nome del file in cui salvare i dati criptati.

C#

Per eseguire questo codice, devi innanzitutto configurare un ambiente di sviluppo C# e installare l'SDK C# di Cloud KMS.


using Google.Cloud.Kms.V1;
using System;
using System.Security.Cryptography;
using System.Text;

public class EncryptAsymmetricSample
{
    public byte[] EncryptAsymmetric(
      string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key", string keyVersionId = "123",
      string message = "Sample message")
    {
        // Create the client.
        KeyManagementServiceClient client = KeyManagementServiceClient.Create();

        // Build the key version name.
        CryptoKeyVersionName keyVersionName = new CryptoKeyVersionName(projectId, locationId, keyRingId, keyId, keyVersionId);

        // Get the public key.
        PublicKey publicKey = client.GetPublicKey(keyVersionName);

        // Split the key into blocks and base64-decode the PEM parts.
        string[] blocks = publicKey.Pem.Split("-", StringSplitOptions.RemoveEmptyEntries);
        byte[] pem = Convert.FromBase64String(blocks[1]);

        // Create a new RSA key.
        RSA rsa = RSA.Create();
        rsa.ImportSubjectPublicKeyInfo(pem, out _);

        // Convert the message into bytes. Cryptographic plaintexts and
        // ciphertexts are always byte arrays.
        byte[] plaintext = Encoding.UTF8.GetBytes(message);

        // Encrypt the data.
        byte[] ciphertext = rsa.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256);
        return ciphertext;
    }
}

Go

Per utilizzare Cloud KMS nella riga di comando, devi prima installare o eseguire l'upgrade all'ultima versione di Google Cloud CLI.

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
	"cloud.google.com/go/kms/apiv1/kmspb"
)

// encryptAsymmetric encrypts data on your local machine using an
// 'RSA_DECRYPT_OAEP_2048_SHA256' public key retrieved from Cloud KMS.
func encryptAsymmetric(w io.Writer, name string, message string) error {
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key/cryptoKeyVersions/123"
	// message := "Sample message"

	// Create the client.
	ctx := context.Background()
	client, err := kms.NewKeyManagementClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create kms client: %w", err)
	}
	defer client.Close()

	// Retrieve the public key from Cloud KMS. This is the only operation that
	// involves Cloud KMS. The remaining operations take place on your local
	// machine.
	response, err := client.GetPublicKey(ctx, &kmspb.GetPublicKeyRequest{
		Name: name,
	})
	if err != nil {
		return fmt.Errorf("failed to get public key: %w", err)
	}

	// Parse the public key. Note, this example assumes the public key is in the
	// RSA format.
	block, _ := pem.Decode([]byte(response.Pem))
	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse public key: %w", err)
	}
	rsaKey, ok := publicKey.(*rsa.PublicKey)
	if !ok {
		return fmt.Errorf("public key is not rsa")
	}

	// Convert the message into bytes. Cryptographic plaintexts and
	// ciphertexts are always byte arrays.
	plaintext := []byte(message)

	// Encrypt data using the RSA public key.
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsaKey, plaintext, nil)
	if err != nil {
		return fmt.Errorf("rsa.EncryptOAEP: %w", err)
	}
	fmt.Fprintf(w, "Encrypted ciphertext: %s", ciphertext)
	return nil
}

Java

Per eseguire questo codice, devi innanzitutto configurare un ambiente di sviluppo Java e installare l'SDK Java di Cloud KMS.

import com.google.cloud.kms.v1.CryptoKeyVersionName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.PublicKey;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.stream.Collectors;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;

public class EncryptAsymmetric {

  public void encryptAsymmetric() throws IOException, GeneralSecurityException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String locationId = "us-east1";
    String keyRingId = "my-key-ring";
    String keyId = "my-key";
    String keyVersionId = "123";
    String plaintext = "Plaintext to encrypt";
    encryptAsymmetric(projectId, locationId, keyRingId, keyId, keyVersionId, plaintext);
  }

  // Encrypt data that was encrypted using the public key component of the given
  // key version.
  public void encryptAsymmetric(
      String projectId,
      String locationId,
      String keyRingId,
      String keyId,
      String keyVersionId,
      String plaintext)
      throws IOException, GeneralSecurityException {
    // Initialize client that will be used to send requests. This client only
    // needs to be created once, and can be reused for multiple requests. After
    // completing all of your requests, call the "close" method on the client to
    // safely clean up any remaining background resources.
    try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
      // Build the key version name from the project, location, key ring, key,
      // and key version.
      CryptoKeyVersionName keyVersionName =
          CryptoKeyVersionName.of(projectId, locationId, keyRingId, keyId, keyVersionId);

      // Get the public key.
      PublicKey publicKey = client.getPublicKey(keyVersionName);

      // Convert the public PEM key to a DER key (see helper below).
      byte[] derKey = convertPemToDer(publicKey.getPem());
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
      java.security.PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);

      // Encrypt plaintext for the 'RSA_DECRYPT_OAEP_2048_SHA256' key.
      // For other key algorithms:
      // https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html
      Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
      OAEPParameterSpec oaepParams =
          new OAEPParameterSpec(
              "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
      cipher.init(Cipher.ENCRYPT_MODE, rsaKey, oaepParams);
      byte[] ciphertext