透過非對稱金鑰加密及解密資料

本主題提供建立及使用金鑰以使用 RSA 金鑰進行非對稱式加密的相關資訊。如果您要使用非對稱金鑰建立及驗證簽名,請參閱建立及驗證數位簽名一文。如果您要使用對稱金鑰進行加密與解密,請參閱加密及解密資料一文。

非對稱式加密使用非對稱金鑰的公開金鑰部分,而解密則使用金鑰的私密金鑰部分。Cloud Key Management Service 提供擷取公開金鑰的功能,以及對已使用公開金鑰加密的密文進行解密的功能。Cloud KMS 不允許直接存取私密金鑰。

事前準備

  • 本主題提供的範例使用指令列執行。如要簡化範例的使用程序,請使用 Cloud Shell。加密範例使用的是 OpenSSL,已經預先安裝在 Cloud Shell 中。

  • 建立非對稱金鑰,且金鑰用途ASYMMETRIC_DECRYPT。如要查看金鑰用途 ASYMMETRIC_DECRYPT 支援的演算法,請參閱非對稱式加密演算法一節。您無法使用用途為 ASYMMETRIC_SIGN 的金鑰執行此程序。

  • 如果您要使用指令列,請安裝 OpenSSL (若尚未安裝)。如果使用 Cloud Shell,則 OpenSSL 已安裝。

  • macOS 使用者: macOS 安裝的 OpenSSL 版本不支援本主題中用於解密資料的標記。如要在 macOS 上執行這些步驟,請從 Homebrew 安裝 OpenSSL。

金鑰的存取權控管

  • 如果使用者或服務將擷取公開金鑰,請授予非對稱金鑰的 cloudkms.cryptoKeyVersions.viewPublicKey 權限。加密資料必須使用公開金鑰。

  • 如果使用者或服務將對已使用公開金鑰加密的資料進行解密,請授予非對稱金鑰的 cloudkms.cryptoKeyVersions.useToDecrypt 權限。

請參閱權限與角色一文,進一步瞭解 Cloud KMS 的權限和角色。

加密資料

如要使用非對稱加密金鑰加密資料,請擷取公開金鑰,並使用公開金鑰加密資料。

gcloud

這個範例需要在本機系統上安裝 OpenSSL

下載公開金鑰

下載公開金鑰:

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

key-version 替換為含有公開金鑰的金鑰版本。 將 key 替換為金鑰名稱。將 key-ring 替換為金鑰所在金鑰環的名稱。請將 location 改為金鑰環的 Cloud KMS 位置。將 public-key-path 替換為要在本機系統上儲存公開金鑰的位置。

加密資料

使用剛下載的公開金鑰加密資料,並將輸出內容儲存至檔案:

 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 
  • cleartext-data-input-file 替換為要加密的路徑和檔案名稱。

  • public-key-path 替換為您下載公開金鑰的路徑和檔案名稱。

  • 請將 encrypted-data-output-file 替換為要儲存加密資料的路徑和檔案名稱。

C#

如要執行這段程式碼,請先設定 C# 開發環境,然後安裝 Cloud KMS C# SDK

 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

如要在指令列上使用 Cloud KMS,請先安裝或升級至最新版 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

如要執行這段程式碼,請先設定 Java 開發環境,然後安裝 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 = 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 = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));       System.out.printf("Ciphertext: %s%n", ciphertext);     }   }    // Converts a base64-encoded PEM certificate like the one returned from Cloud   // KMS into a DER formatted certificate for use with the Java APIs.   private byte[] convertPemToDer(String pem) {     BufferedReader bufferedReader = new BufferedReader(new StringReader(pem));     String encoded =         bufferedReader             .lines()             .filter(line -> !line.startsWith("-----BEGIN") && !line.startsWith("-----END"))             .collect(Collectors.joining());     return Base64.getDecoder().decode(encoded);   } }

Node.js

如要執行這段程式碼,請先設定 Node.js 開發環境,然後安裝 Cloud KMS Node.js SDK

// // 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'; // const versionId = '123'; // const plaintextBuffer = Buffer.from('...');  // Imports the Cloud KMS library const {KeyManagementServiceClient} = require('@google-cloud/kms');  // Instantiates a client const client = new KeyManagementServiceClient();  // Build the key version name const versionName = client.cryptoKeyVersionPath(   projectId,   locationId,   keyRingId,   keyId,   versionId );  async function encryptAsymmetric() {   // Get public key from Cloud KMS   const [publicKey] = await client.getPublicKey({     name: versionName,   });    // Optional, but recommended: perform integrity verification on publicKey.   // For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:   // https://cloud.google.com/kms/docs/data-integrity-guidelines   const crc32c = require('fast-crc32c');   if (publicKey.name !== versionName) {     throw new Error('GetPublicKey: request corrupted in-transit');   }   if (crc32c.calculate(publicKey.pem) !== Number(publicKey.pemCrc32c.value)) {     throw new Error('GetPublicKey: response corrupted in-transit');   }    // Import and setup crypto   const crypto = require('crypto');    // Encrypt plaintext locally using the public key. This example uses a key   // that was configured with sha256 hash with OAEP padding. Update these   // values to match the Cloud KMS key.   //   // NOTE: In Node < 12, this function does not properly consume the OAEP   // padding and thus produces invalid ciphertext. If you are using Node to do   // public key encryption, please use version 12+.   const ciphertextBuffer = crypto.publicEncrypt(     {       key: publicKey.pem,       oaepHash: 'sha256',       padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,     },     plaintextBuffer   );    console.log(`Ciphertext: ${ciphertextBuffer.toString('base64')}`);   return ciphertextBuffer; }  return encryptAsymmetric();

PHP

如要執行這段程式碼,請先瞭解如何在 Google Cloud上使用 PHP,並安裝 Cloud KMS PHP SDK

function encrypt_asymmetric(     string $projectId = 'my-project',     string $locationId = 'us-east1',     string $keyRingId = 'my-key-ring',     string $keyId = 'my-key',     string $versionId = '123',     string $plaintext = '...' ): void {     // PHP has limited support for asymmetric encryption operations.     // Specifically, openssl_public_encrypt() does not allow customizing     // algorithms or padding. Thus, it is not currently possible to use PHP     // core for asymmetric operations on RSA keys.     //     // Third party libraries like phpseclib may provide the required     // functionality. Google does not endorse this external library. }

Python

如要執行這段程式碼,請先設定 Python 開發環境,然後安裝 Cloud KMS Python SDK

 # Import base64 for printing the ciphertext. import base64  # Import cryptographic helpers from the cryptography package. from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import padding  # Import the client library. from google.cloud import kms   def encrypt_asymmetric(     project_id: str,     location_id: str,     key_ring_id: str,     key_id: str,     version_id: str,     plaintext: str, ) -> bytes:     """     Encrypt plaintext using the public key portion of an asymmetric key.      Args:         project_id (string): Google Cloud project ID (e.g. 'my-project').         location_id (string): Cloud KMS location (e.g. 'us-east1').         key_ring_id (string): ID of the Cloud KMS key ring (e.g. 'my-key-ring').         key_id (string): ID of the key to use (e.g. 'my-key').         version_id (string): ID of the key version to use (e.g. '1').         plaintext (string): message to encrypt      Returns:         bytes: Encrypted ciphertext.      """      # Convert the plaintext to bytes.     plaintext_bytes = plaintext.encode("utf-8")      # Create the client.     client = kms.KeyManagementServiceClient()      # Build the key version name.     key_version_name = client.crypto_key_version_path(         project_id, location_id, key_ring_id, key_id, version_id     )      # Get the public key.     public_key = client.get_public_key(request={"name": key_version_name})      # Extract and parse the public key as a PEM-encoded RSA key.     pem = public_key.pem.encode("utf-8")     rsa_key = serialization.load_pem_public_key(pem, default_backend())      # Construct the padding. Note that the padding differs based on key choice.     sha256 = hashes.SHA256()     mgf = padding.MGF1(algorithm=sha256)     pad = padding.OAEP(mgf=mgf, algorithm=sha256, label=None)      # Encrypt the data using the public key.     ciphertext = rsa_key.encrypt(plaintext_bytes, pad)     print(f"Ciphertext: {base64.b64encode(ciphertext)!r}")     return ciphertext  

Ruby

如要執行這段程式碼,請先設定 Ruby 開發環境,然後安裝 Cloud KMS Ruby SDK

# Ruby has limited support for asymmetric encryption operations. Specifically, # public_encrypt() does not allow customizing the MGF hash algorithm. Thus, it # is not currently possible to use Ruby core for asymmetric encryption # operations on RSA keys from Cloud KMS. # # Third party libraries may provide the required functionality. Google does # not endorse these external libraries.

解密資料

使用 Cloud KMS 執行解密。

gcloud

如要在指令列上使用 Cloud KMS,請先安裝或升級至最新版 Google Cloud CLI

 gcloud kms asymmetric-decrypt \     --version key-version \     --key key \     --keyring key-ring \     --location location  \     --ciphertext-file file-path-with-encrypted-data \     --plaintext-file file-path-to-store-plaintext 

key-version 換成金鑰版本,或省略 --version 旗標,自動偵測版本。將 key 替換為要用於解密的金鑰名稱。將 key-ring 替換為金鑰所在金鑰環的名稱。將 location 替換為金鑰環的 Cloud KMS 位置。將 file-path-with-encrypted-datafile-path-to-store-plaintext 替換為讀取加密資料和儲存解密輸出內容的本機檔案路徑。

如要瞭解所有旗標和可能的值,請使用 --help 旗標執行指令。

如要顯示已解密檔案的內容,請在編輯器或終端機中開啟檔案。以下範例顯示如何使用 cat 指令查看檔案內容:

 cat ./my-file.txt 

C#

如要執行這段程式碼,請先設定 C# 開發環境,然後安裝 Cloud KMS C# SDK

 using Google.Cloud.Kms.V1; using Google.Protobuf; using System.Text;  public class DecryptAsymmetricSample {     public string DecryptAsymmetric(       string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key", string keyVersionId = "123",       byte[] ciphertext = null)     {         // Create the client.         KeyManagementServiceClient client = KeyManagementServiceClient.Create();          // Build the key version name.         CryptoKeyVersionName keyVersionName = new CryptoKeyVersionName(projectId, locationId, keyRingId, keyId, keyVersionId);          // Call the API.         AsymmetricDecryptResponse result = client.AsymmetricDecrypt(keyVersionName, ByteString.CopyFrom(ciphertext));          // Get the plaintext. Cryptographic plaintexts and ciphertexts are         // always byte arrays.         byte[] plaintext = result.Plaintext.ToByteArray();          // Return the result.         return Encoding.UTF8.GetString(plaintext);     } }

Go

如要執行這段程式碼,請先設定 Go 開發環境,並安裝 Cloud KMS Go SDK

import ( 	"context" 	"fmt" 	"hash/crc32" 	"io"  	kms "cloud.google.com/go/kms/apiv1" 	"cloud.google.com/go/kms/apiv1/kmspb" 	"google.golang.org/protobuf/types/known/wrapperspb" )  // decryptAsymmetric will attempt to decrypt a given ciphertext with an // 'RSA_DECRYPT_OAEP_2048_SHA256' key from Cloud KMS. func decryptAsymmetric(w io.Writer, name string, ciphertext []byte) error { 	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key/cryptoKeyVersions/123" 	// ciphertext := []byte("...")  // result of an asymmetric encryption call  	// 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()  	// Optional but recommended: Compute ciphertext's CRC32C. 	crc32c := func(data []byte) uint32 { 		t := crc32.MakeTable(crc32.Castagnoli) 		return crc32.Checksum(data, t) 	} 	ciphertextCRC32C := crc32c(ciphertext)  	// Build the request. 	req := &kmspb.AsymmetricDecryptRequest{ 		Name:             name, 		Ciphertext:       ciphertext, 		CiphertextCrc32C: wrapperspb.Int64(int64(ciphertextCRC32C)), 	}  	// Call the API. 	result, err := client.AsymmetricDecrypt(ctx, req) 	if err != nil { 		return fmt.Errorf("failed to decrypt ciphertext: %w", err) 	}  	// Optional, but recommended: perform integrity verification on result. 	// 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 result.VerifiedCiphertextCrc32C == false { 		return fmt.Errorf("AsymmetricDecrypt: request corrupted in-transit") 	} 	if int64(crc32c(result.Plaintext)) != result.PlaintextCrc32C.Value { 		return fmt.Errorf("AsymmetricDecrypt: response corrupted in-transit") 	}  	fmt.Fprintf(w, "Decrypted plaintext: %s", result.Plaintext) 	return nil } 

Java

如要執行這段程式碼,請先設定 Java 開發環境,然後安裝 Cloud KMS Java SDK

import com.google.cloud.kms.v1.AsymmetricDecryptResponse; import com.google.cloud.kms.v1.CryptoKeyVersionName; import com.google.cloud.kms.v1.KeyManagementServiceClient; import com.google.protobuf.ByteString; import java.io.IOException;  public class DecryptAsymmetric {    public void decryptAsymmetric() throws IOException {     // 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";     byte[] ciphertext = null;     decryptAsymmetric(projectId, locationId, keyRingId, keyId, keyVersionId, ciphertext);   }    // Decrypt data that was encrypted using the public key component of the given   // key version.   public void decryptAsymmetric(       String projectId,       String locationId,       String keyRingId,       String keyId,       String keyVersionId,       byte[] ciphertext)       throws IOException {     // 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);        // Decrypt the ciphertext.       AsymmetricDecryptResponse response =           client.asymmetricDecrypt(keyVersionName, ByteString.copyFrom(ciphertext));       System.out.printf("Plaintext: %s%n", response.getPlaintext().toStringUtf8());     }   } }

Node.js

如要執行這段程式碼,請先設定 Node.js 開發環境,然後安裝 Cloud KMS Node.js SDK

// // 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'; // const versionId = '123'; // 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 version name const versionName = client.cryptoKeyVersionPath(   projectId,   locationId,   keyRingId,   keyId,   versionId );  // Optional, but recommended: compute plaintext's CRC32C. const crc32c = require('fast-crc32c'); const ciphertextCrc32c = crc32c.calculate(ciphertext);  async function decryptAsymmetric() {   const [decryptResponse] = await client.asymmetricDecrypt({     name: versionName,     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 (!decryptResponse.verifiedCiphertextCrc32c) {     throw new Error('AsymmetricDecrypt: request corrupted in-transit');   }   if (     crc32c.calculate(decryptResponse.plaintext) !==     Number(decryptResponse.plaintextCrc32c.value)   ) {     throw new Error('AsymmetricDecrypt: response corrupted in-transit');   }    // NOTE: The ciphertext must be properly formatted. In Node < 12, the   // crypto.publicEncrypt() function does not properly consume the OAEP   // padding and thus produces invalid ciphertext. If you are using Node to do   // public key encryption, please use version 12+.   const plaintext = decryptResponse.plaintext.toString('utf8');    console.log(`Plaintext: ${plaintext}`);   return plaintext; }  return decryptAsymmetric();

PHP

如要執行這段程式碼,請先瞭解如何在 Google Cloud上使用 PHP,並安裝 Cloud KMS PHP SDK

use Google\Cloud\Kms\V1\AsymmetricDecryptRequest; use Google\Cloud\Kms\V1\Client\KeyManagementServiceClient;  function decrypt_asymmetric(     string $projectId = 'my-project',     string $locationId = 'us-east1',     string $keyRingId = 'my-key-ring',     string $keyId = 'my-key',     string $versionId = '123',     string $ciphertext = '...' ) {     // Create the Cloud KMS client.     $client = new KeyManagementServiceClient();      // Build the key version name.     $keyVersionName = $client->cryptoKeyVersionName($projectId, $locationId, $keyRingId, $keyId, $versionId);      // Call the API.     $asymmetricDecryptRequest = (new AsymmetricDecryptRequest())         ->setName($keyVersionName)         ->setCiphertext($ciphertext);     $decryptResponse = $client->asymmetricDecrypt($asymmetricDecryptRequest);     printf('Plaintext: %s' . PHP_EOL, $decryptResponse->getPlaintext());      return $decryptResponse; }

Python

如要執行這段程式碼,請先設定 Python 開發環境,然後安裝 Cloud KMS Python SDK

from google.cloud import kms   def decrypt_asymmetric(     project_id: str,     location_id: str,     key_ring_id: str,     key_id: str,     version_id: str,     ciphertext: bytes, ) -> kms.DecryptResponse:     """     Decrypt the ciphertext using an asymmetric key.      Args:         project_id (string): Google Cloud project ID (e.g. 'my-project').         location_id (string): Cloud KMS location (e.g. 'us-east1').         key_ring_id (string): ID of the Cloud KMS key ring (e.g. 'my-key-ring').         key_id (string): ID of the key to use (e.g. 'my-key').         version_id (string): ID of the key version to use (e.g. '1').         ciphertext (bytes): Encrypted bytes to decrypt.      Returns:         DecryptResponse: Response including plaintext.      """      # Create the client.     client = kms.KeyManagementServiceClient()      # Build the key version name.     key_version_name = client.crypto_key_version_path(         project_id, location_id, key_ring_id, key_id, version_id     )      # Optional, but recommended: compute ciphertext's CRC32C.     # See crc32c() function defined below.     ciphertext_crc32c = crc32c(ciphertext)      # Call the API.     decrypt_response = client.asymmetric_decrypt(         request={             "name": key_version_name,             "ciphertext": ciphertext,             "ciphertext_crc32c": ciphertext_crc32c,         }     )      # Optional, but recommended: perform integrity verification on decrypt_response.     # 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 not decrypt_response.verified_ciphertext_crc32c:         raise Exception("The request sent to the server was corrupted in-transit.")     if not decrypt_response.plaintext_crc32c == crc32c(decrypt_response.plaintext):         raise Exception(             "The response received from the server was corrupted in-transit."         )     # End integrity verification      print(f"Plaintext: {decrypt_response.plaintext!r}")     return decrypt_response   def crc32c(data: bytes) -> int:     """     Calculates the CRC32C checksum of the provided data.     Args:         data: the bytes over which the checksum should be calculated.     Returns:         An int representing the CRC32C checksum of the provided bytes.     """     import crcmod  # type: ignore      crc32c_fun = crcmod.predefined.mkPredefinedCrcFun("crc-32c")     return crc32c_fun(data)  

Ruby

如要執行這段程式碼,請先設定 Ruby 開發環境,然後安裝 Cloud KMS Ruby SDK

# TODO(developer): uncomment these values before running the sample. # project_id  = "my-project" # location_id = "us-east1" # key_ring_id = "my-key-ring" # key_id      = "my-key" # version_id  = "123" # ciphertext  = "..."  # Require the library. require "google/cloud/kms"  # Create the client. client = Google::Cloud::Kms.key_management_service  # Build the key version name. key_version_name = client.crypto_key_version_path project:            project_id,                                                   location:           location_id,                                                   key_ring:           key_ring_id,                                                   crypto_key:         key_id,                                                   crypto_key_version: version_id  # Call the API. response = client.asymmetric_decrypt key_version_name, ciphertext puts "Plaintext: #{response.plaintext}"

API

這些範例使用 curl 做為 HTTP 用戶端,示範如何使用 API。如要進一步瞭解存取權控管,請參閱「存取 Cloud KMS API」一文。

請使用 CryptoKeyVersions.asymmetricDecrypt 方法。

疑難排解

incorrect key purpose: ASYMMETRIC_SIGN

您只能使用金鑰用途ASYMMETRIC_DECRYPT 的金鑰解密資料。

invalid parameter 在 macOS 上解密時

macOS 安裝的 OpenSSL 版本不支援本主題中用於解密資料的旗標。如要在 macOS 上執行這些步驟,請從 Homebrew 安裝 OpenSSL。

data too large for key size

RSA 解密作業的酬載大小上限取決於金鑰大小和填補演算法。Cloud KMS 使用的所有 RSA 加密格式都採用 OAEP,此格式已在 RFC 2437 中標準化。如需快速參考,下列演算法支援的酬載大小上限如下 (maxMLen,以位元組為單位):

演算法 參數 訊息長度上限
RSA_DECRYPT_OAEP_2048_SHA256 k = 256; hLen = 32; maxMLen = 190
RSA_DECRYPT_OAEP_3072_SHA256 k = 384; hLen = 32; maxMLen = 318
RSA_DECRYPT_OAEP_4096_SHA256 k = 512; hLen = 32; maxMLen = 446
RSA_DECRYPT_OAEP_4096_SHA512 k = 512; hLen = 64; maxMLen = 382

如果訊息長度不一,且可能超過這些限制,建議不要使用非對稱式加密。建議改用混合式加密。 Tink 是一種採用這種做法的密碼編譯程式庫。