Mengenkripsi dan mendekripsi data dengan kunci asimetris

Topik ini memberikan informasi tentang cara membuat dan menggunakan kunci untuk enkripsi asimetris menggunakan kunci RSA. Jika Anda ingin menggunakan kunci asimetris untuk membuat dan memvalidasi tanda tangan, lihat Membuat dan memvalidasi tanda tangan digital. Jika Anda ingin menggunakan kunci simetris untuk enkripsi dan dekripsi, lihat Mengenkripsi dan mendekripsi data.

Enkripsi asimetris menggunakan bagian kunci publik dari kunci asimetris dan dekripsi menggunakan bagian kunci pribadi dari kunci tersebut. Cloud Key Management Service menyediakan fungsi untuk mengambil kunci publik dan fungsi untuk mendekripsi ciphertext yang dienkripsi dengan kunci publik. Cloud KMS tidak mengizinkan akses langsung ke kunci pribadi.

Sebelum memulai

  • Topik ini memberikan contoh yang berjalan di command line. Untuk menyederhanakan penggunaan contoh, gunakan Cloud Shell. Contoh enkripsi menggunakan OpenSSL, yang sudah diinstal sebelumnya di Cloud Shell.

  • Buat kunci asimetris dengan tujuan penggunaan kunci ASYMMETRIC_DECRYPT. Untuk melihat algoritma yang didukung untuk tujuan kunci ASYMMETRIC_DECRYPT, lihat Algoritma enkripsi asimetris. Anda tidak dapat mengikuti prosedur ini dengan kunci yang memiliki tujuan ASYMMETRIC_SIGN.

  • Jika Anda akan menggunakan command line, instal OpenSSL jika Anda belum memilikinya. Jika Anda menggunakan Cloud Shell, OpenSSL sudah diinstal.

  • Pengguna macOS: Versi OpenSSL yang diinstal di macOS tidak mendukung flag yang digunakan untuk mendekripsi data dalam topik ini. Untuk mengikuti langkah-langkah ini di macOS, instal OpenSSL dari Homebrew.

Kontrol akses ke kunci

  • Untuk pengguna atau layanan yang akan mengambil kunci publik, berikan izin cloudkms.cryptoKeyVersions.viewPublicKey pada kunci asimetris. Kunci publik diperlukan untuk mengenkripsi data.

  • Untuk pengguna atau layanan yang akan mendekripsi data yang dienkripsi dengan kunci publik, berikan izin cloudkms.cryptoKeyVersions.useToDecrypt pada kunci asimetris.

Pelajari izin dan peran di Cloud KMS di Izin dan Peran.

Mengenkripsi data

Untuk mengenkripsi data menggunakan kunci enkripsi asimetris, ambil kunci publik dan gunakan kunci publik untuk mengenkripsi data.

gcloud

Contoh ini mengharuskan OpenSSL diinstal di sistem lokal Anda.

Download kunci publik

Download kunci publik:

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

Ganti key-version dengan versi kunci yang memiliki kunci publik. Ganti key dengan nama kunci. Ganti key-ring dengan nama key ring tempat kunci berada. Ganti location dengan lokasi Cloud KMS untuk key ring. Ganti public-key-path dengan lokasi untuk menyimpan kunci publik di sistem lokal.

Mengenkripsi data

Enkripsi data menggunakan kunci publik yang baru saja Anda download dan simpan output ke 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
  • Ganti cleartext-data-input-file dengan jalur dan nama file yang akan dienkripsi.

  • Ganti public-key-path dengan jalur dan nama file tempat Anda mendownload kunci publik.

  • Ganti encrypted-data-output-file dengan jalur dan nama file untuk menyimpan data terenkripsi.

C#

Untuk menjalankan kode ini, siapkan lingkungan pengembangan C# terlebih dahulu dan instal SDK C# 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

Untuk menggunakan Cloud KMS di command line, Instal atau upgrade ke versi terbaru Google Cloud CLI terlebih dahulu.

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

Untuk menjalankan kode ini, siapkan lingkungan pengembangan Java terlebih dahulu dan instal Cloud KMS Java SDK.

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