检索公钥

本页介绍了如何检索已启用的非对称密钥版本的公钥部分。

公钥采用隐私权保密增强电子邮件 (PEM) 格式。如需了解详情,请参阅 RFC 7468 部分中的一般注意事项正文公钥信息的文本编码

所需的角色

如需获得检索公钥所需的权限,请让您的管理员为您授予对密钥或父级资源的 Cloud KMS CryptoKey Public Key Viewer (roles/cloudkms.publicKeyViewer) IAM 角色。 如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

此预定义角色包含检索公钥所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

检索公钥需要以下权限:

  • cloudkms.cryptoKeyVersions.viewPublicKey
  • cloudkms.locations.get
  • cloudkms.locations.list
  • resourcemanager.projects.get

您也可以使用自定义角色或其他预定义角色来获取这些权限。

检索公钥

如需下载已启用的非对称密钥版本的公钥,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,前往密钥管理页面。

    前往“密钥管理”

  2. 点击包含您要检索公钥的非对称密钥的密钥环的名称。

  3. 点击要检索公钥的密钥的名称。

  4. 在与要检索公钥的密钥版本对应的行中,点击查看更多

  5. 点击获取公钥

  6. 公钥显示在提示中。您可以将公钥复制到剪贴板。要下载公钥,请点击下载

如果您没有看到获取公钥选项,请验证以下各项:

  • 该密钥是非对称密钥。
  • 密钥版本已启用。
  • 您拥有 cloudkms.cryptoKeyVersions.viewPublicKey 权限。

从 Google Cloud 控制台下载的公钥的文件名格式为:

KEY_RING-KEY_NAME-KEY_VERSION.pub

文件名的每个部分由连字符分隔,例如 ringname-keyname-version.pub

gcloud

如需在命令行上使用 Cloud KMS,请先安装或升级到最新版本的 Google Cloud CLI

gcloud kms keys versions get-public-key KEY_VERSION \
    --key KEY_NAME \
    --keyring KEY_RING \
    --location LOCATION \
    --output-file OUTPUT_FILE_PATH

替换以下内容:

  • KEY_VERSION:密钥版本号。
  • KEY_NAME:密钥的名称。
  • KEY_RING:包含密钥的密钥环的名称。
  • LOCATION:密钥环的 Cloud KMS 位置。
  • OUTPUT_FILE_PATH:您要保存公钥文件的路径,例如 public-key.pub

如需了解所有标志和可能值,请使用 --help 标志运行命令。

C#

要运行此代码,请先设置 C# 开发环境安装 Cloud KMS C# SDK


using Google.Cloud.Kms.V1;

public class GetPublicKeySample
{
    public PublicKey GetPublicKey(string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key", string keyVersionId = "123")
    {
        // Create the client.
        KeyManagementServiceClient client = KeyManagementServiceClient.Create();

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

        // Call the API.
        PublicKey result = client.GetPublicKey(keyVersionName);

        // Return the ciphertext.
        return result;
    }
}

Go

要运行此代码,请先设置 Go 开发环境安装 Cloud KMS Go SDK

import (
	"context"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"hash/crc32"
	"io"

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

// getPublicKey retrieves the public key from an asymmetric key pair on
// Cloud KMS.
func getPublicKey(w io.Writer, name string) error {
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key/cryptoKeyVersions/123"

	// 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()

	// Build the request.
	req := &kmspb.GetPublicKeyRequest{
		Name: name,
	}

	// Call the API.
	result, err := client.GetPublicKey(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to get public key: %w", err)
	}

	// The 'Pem' field is the raw string representation of the public key.
	// Convert 'Pem' into bytes for further processing.
	key := []byte(result.Pem)

	// 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
	crc32c := func(data []byte) uint32 {
		t := crc32.MakeTable(crc32.Castagnoli)
		return crc32.Checksum(data, t)
	}
	if int64(crc32c(key)) != result.PemCrc32C.Value {
		return fmt.Errorf("getPublicKey: response corrupted in-transit")
	}

	// Optional - parse the public key. This transforms the string key into a Go
	// PublicKey.
	block, _ := pem.Decode(key)
	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse public key: %w", err)
	}
	fmt.Fprintf(w, "Retrieved public key: %v\n", publicKey)
	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.IOException;
import java.security.GeneralSecurityException;

public class GetPublicKey {

  public void getPublicKey() 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";
    getPublicKey(projectId, locationId, keyRingId, keyId, keyVersionId);
  }

  // Get the public key associated with an asymmetric key.
  public void getPublicKey(
      String projectId, String locationId, String keyRingId, String keyId, String keyVersionId)
      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);
      System.out.printf("Public key: %s%n", publicKey.getPem());
    }
  }
}

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';

// 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 getPublicKey() {
  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');
  }

  console.log(`Public key pem: ${publicKey.pem}`);

  return publicKey;
}

return getPublicKey();

PHP

要运行此代码,请先了解如何在 Google Cloud 上使用 PHP安装 Cloud KMS PHP SDK

use Google\Cloud\Kms\V1\Client\KeyManagementServiceClient;
use Google\Cloud\Kms\V1\GetPublicKeyRequest;

function get_public_key(
    string $projectId = 'my-project',
    string $locationId = 'us-east1',
    string $keyRingId = 'my-key-ring',
    string $keyId = 'my-key',
    string $versionId = '123'
) {
    // Create the Cloud KMS client.
    $client = new KeyManagementServiceClient();

    // Build the key version name.
    $keyVersionName = $client->cryptoKeyVersionName($projectId, $locationId, $keyRingId, $keyId, $versionId);

    // Call the API.
    $getPublicKeyRequest = (new GetPublicKeyRequest())
        ->setName($keyVersionName);
    $publicKey = $client->getPublicKey($getPublicKeyRequest);
    printf('Public key: %s' . PHP_EOL, $publicKey->getPem());

    return $publicKey;
}

Python

要运行此代码,请先设置 Python 开发环境安装 Cloud KMS Python SDK

from google.cloud import kms


def get_public_key(
    project_id: str, location_id: str, key_ring_id: str, key_id: str, version_id: str
) -> kms.PublicKey:
    """
    Get the public key for 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 to use (e.g. '1').

    Returns:
        PublicKey: Cloud KMS public key response.

    """

    # 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
    )

    # Call the API.
    public_key = client.get_public_key(request={"name": key_version_name})

    # Optional, but recommended: perform integrity verification on public_key.
    # 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 public_key.name == key_version_name:
        raise Exception("The request sent to the server was corrupted in-transit.")
    # See crc32c() function defined below.
    if not public_key.pem_crc32c == crc32c(public_key.pem.encode("utf-8")):
        raise Exception(
            "The response received from the server was corrupted in-transit."
        )
    # End integrity verification

    print(f"Public key: {public_key.pem}")
    return public_key


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"

# 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.
public_key = client.get_public_key name: key_version_name
puts "Public key: #{public_key.pem}"

API

这些示例使用 curl 作为 HTTP 客户端来演示如何使用 API。如需详细了解访问权限控制,请参阅访问 Cloud KMS API

通过调用 CryptoKeyVersions.getPublicKey 方法检索公钥。

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/KEY_VERSION/publicKey" \
    --request "GET" \
    --header "authorization: Bearer TOKEN"

替换以下内容:

  • PROJECT_ID:包含密钥环的项目的 ID。
  • LOCATION:密钥环的 Cloud KMS 位置。
  • KEY_RING:包含密钥的密钥环的名称。
  • KEY_NAME:密钥的名称。
  • KEY_VERSION:密钥版本号。

输出应类似如下所示:

{
  "pem": "-----BEGIN PUBLIC KEY-----\nQ29uZ3JhdHVsYXRpb25zLCB5b3UndmUgZGlzY292ZX
          JlZCB0aGF0IHRoaXMgaXNuJ3QgYWN0dWFsbHkgYSBwdWJsaWMga2V5ISBIYXZlIGEgbmlj
          ZSBkYXkgOik=\n-----END PUBLIC KEY-----\n",
  "algorithm": "ALGORITHM",
  "pemCrc32c": "2561089887",
  "name": "projects/PROJECT_ID/locations/LOCATION/keyRings/
           KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/
           KEY_VERSION",
  "protectionLevel": "PROTECTION_LEVEL"
}