检索公钥

您可以使用 Google Cloud Platform Console、gcloud 命令行工具和 Cloud KMS API 检索非对称密钥版本的公钥部分。

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

将检索公钥的用户或服务需要具有密钥版本的 cloudkms.cryptoKeyVersions.viewPublicKey 权限。您可以参阅权限和角色,了解 Cloud KMS 测试版中的权限。

控制台

要下载现有非对称密钥版本的公钥,请执行以下操作:

  1. 打开 GCP Console 中的加密密钥页面。
  2. 点击包含非对称密钥的密钥环的名称。
  3. 点击包含密钥版本的密钥的名称。
  4. 找到要检索其公钥的密钥版本,点击旁边的更多图标(3 个垂直点)。
  5. 点击获取公钥。随即将显示公钥,您可以将公钥复制到剪贴板或下载公钥。(如果您没有看到获取公钥选项,请验证密钥是否为非对称密钥,并验证您是否具有 cloudkms.cryptoKeyVersions.viewPublicKey 权限。)

    公钥

从 GCP Console 下载的公钥文件名的格式为 [KEY_RING]-[KEY]-[CRYPTO_KEY_VERSION].pub。

命令行

gcloud kms keys versions \
  get-public-key CRYPTO_KEY_VERSION \
  --location LOCATION \
  --keyring KEY_RING \
  --key KEY \
  --output-file ~/mykey.pub

API

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

指定所要检索公钥的密钥版本的资源 ID

Go

import (
	"context"
	"crypto/x509"
	"encoding/pem"
	"fmt"

	cloudkms "cloud.google.com/go/kms/apiv1"
	kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
)

// getAsymmetricPublicKey retrieves the public key from a saved asymmetric key pair on KMS.
func getAsymmetricPublicKey(name string) (interface{}, error) {
	// name: "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1"
	ctx := context.Background()
	client, err := cloudkms.NewKeyManagementClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("cloudkms.NewKeyManagementClient: %v", err)
	}

	// Build the request.
	req := &kmspb.GetPublicKeyRequest{
		Name: name,
	}
	// Call the API.
	response, err := client.GetPublicKey(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("GetPublicKey: %v", err)
	}
	// Parse the key.
	keyBytes := []byte(response.Pem)
	block, _ := pem.Decode(keyBytes)
	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, fmt.Errorf("x509.ParsePKIXPublicKey: %v", err)
	}
	return publicKey, nil
}

Java

/**
 * Retrieves the public key from a saved asymmetric key pair on Cloud KMS
 *
 * Example keyName:
 *   "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1"
 */
public static PublicKey getAsymmetricPublicKey(String keyName)
    throws IOException, GeneralSecurityException {

  // Create the Cloud KMS client.
  try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
    com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName);

    // Convert a PEM key to DER without taking a dependency on a third party library
    String pemKey = pub.getPem();
    pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", "");
    pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", "");
    pemKey = pemKey.replaceAll("\\s", "");
    byte[] derKey = BaseEncoding.base64().decode(pemKey);

    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);

    if (pub.getAlgorithm().name().contains("RSA")) {
      return KeyFactory.getInstance("RSA").generatePublic(keySpec);
    } else if (pub.getAlgorithm().name().contains("EC")) {
      return KeyFactory.getInstance("EC").generatePublic(keySpec);
    } else {
      throw new UnsupportedOperationException(String.format(
          "key at path '%s' is of unsupported type '%s'.", keyName, pub.getAlgorithm()));
    }
  }
}

Python

def get_asymmetric_public_key(key_name):
    """
    Retrieves the public key from a saved asymmetric key pair on Cloud KMS

    Example key_name:
      "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
              /KEY_ID/cryptoKeyVersions/1"

    Requires:
      cryptography.hazmat.backends.default_backend
      cryptography.hazmat.primitives.serialization
    """

    client = kms_v1.KeyManagementServiceClient()
    response = client.get_public_key(key_name)

    key_txt = response.pem.encode('ascii')
    key = serialization.load_pem_public_key(key_txt, default_backend())
    return key