Retrieving a public key

You can retrieve the public key portion of an asymmetric key version by using the Google Cloud Console, the gcloud command-line tool, and the Cloud Key Management Service API.

The public key is in the Privacy-enhanced Electronic Mail (PEM) format. For more information, see the RFC 7468 sections for General Considerations and Textual Encoding of Subject Public Key Info.

The user or service that will retrieve the public key requires cloudkms.cryptoKeyVersions.viewPublicKey permission on the key version. You can learn about permissions in the Cloud KMS beta release at Permissions and Roles.

Console

To download the public key for an existing asymmetric key version:

  1. Open the Cryptographic Keys page in the Cloud Console.
  2. Click the name of the key ring that contains the asymmetric key.
  3. Click the name of the key that contains the key version.
  4. For the key version whose public key you want to retrieve, click the More icon (3 vertical dots).
  5. Click Get public key. The public key is displayed, and you can copy the public key to your clipboard or download the public key. (If you do not see the Get public key option, verify the key is an asymmetric key, and verify you have the cloudkms.cryptoKeyVersions.viewPublicKey permission.)

    Public key

The file name of a public key downloaded from the Cloud Console is of the form [key-ring]-[key-name]-[key-version].pub. Each portion of the file name is separated by a hyphen. For that reason, placeholder text is surrounded by square bracket ([ and ]) characters.

Command-line

gcloud kms keys versions \
  get-public-key key-version \
  --location location \
  --keyring key-ring \
  --key key \
  --output-file key-name.pub

API

Retrieve the public key by calling the CryptoKeyVersions.getPublicKey method.

Specify the resource ID of the key version for the public key you want to retrieve.

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()));
    }
  }
}

Node.js

async function getPublicKey(
  projectId = 'your-project-id', // Your GCP projectId
  keyRingId = 'my-key-ring', // Name of the crypto key's key ring
  cryptoKeyId = 'my-key', // Name of the crypto key, e.g. "my-key"
  cryptoKeyVersionId = '1' // Version of the crypto key to fetch
) {
  // Import the library and create a client
  const kms = require('@google-cloud/kms');
  const client = new kms.KeyManagementServiceClient();

  // The location of the crypto key's key ring, e.g. "global"
  const locationId = 'global';

  // Construct the cyrpto key version ID
  const name = client.cryptoKeyVersionPath(
    projectId,
    locationId,
    keyRingId,
    cryptoKeyId,
    cryptoKeyVersionId
  );

  // Get public key from Cloud KMS
  const [publicKey] = await client.getPublicKey({name: name});

  // Return the public key pem
  return publicKey.pem;
}

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