Import a key version into Cloud KMS

This topic shows you how to import a cryptographic key into Cloud HSM or Cloud Key Management Service as a new key version.

For more details about importing keys, including limitations and restrictions, see key import.

You can complete the steps in this topic in 5 to 10 minutes, not including the Before you begin steps. Wrapping the key manually adds complexity to the task.

Before you begin

We recommend that you create a new project to test this feature, to ease clean-up after testing and to ensure that you have adequate Identity and Access Management (IAM) permissions to import a key.

Before you can import a key, you need to prepare the project, the local system, and the key itself.

Preparing the project

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the required API.

    Enable the API

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the required API.

    Enable the API

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. The user performing the import needs the following IAM permissions to create key rings, keys, and import jobs. If the user is not the project owner, you can assign both of the following two predefined roles to the user:

    • roles/editor
    • roles/cloudkms.importer

    For more information about available IAM roles and permissions for Cloud KMS, refer to Permissions and roles.

Preparing the local system

Prepare the local system by choosing one of the following options. Automatic key wrapping is recommended for most users.

  • If you want to allow the Google Cloud CLI to wrap your keys automatically before transmitting them to Google Cloud, you must install the Pyca cryptography library on your local system. The Pyca library is used by the import job that wraps and protects the key locally before sending it to Google Cloud.
  • If you want to wrap your keys manually, you must configure OpenSSL for manual key wrapping.

Preparing the key

Verify that your key's algorithm and length are supported. Allowable algorithms for a key depend upon whether the key is used for symmetric encryption, asymmetric encryption or asymmetric signing, as well as whether the key is stored in software or an HSM. You specify the key's algorithm as part of the import request.

Separately, you must also verify how the key is encoded, and make adjustments if necessary.

The following can't be changed for a key version after it is created or imported:

  • The protection level indicates whether the key persists in software, in an HSM, or in an external key management system. Key material cannot be moved from one of these storage environments to another. All versions of a key have the same protection level.

  • The purpose indicates whether versions of the key are used for symmetric encryption, asymmetric encryption, or asymmetric signing. The purpose of the key limits the possible algorithms that can be used to create versions of that key. All versions of a key have the same purpose.

If you don't have a key to import but want to validate the procedure for importing keys, you can create a symmetric key on the local system, using the following command:

openssl rand 32 > ${HOME}/test.bin

Use this key for testing only. A key created this way might not be appropriate for production use.

If you need to wrap the key manually, do that before continuing with the procedures in this topic.

Create the target key and key ring

A Cloud KMS key is a container object that contains zero or more key versions. Each key version contains a cryptographic key.

When you import a key into Cloud KMS or Cloud HSM, the imported key becomes a new key version on an existing Cloud KMS or Cloud HSM key. In the rest of this topic, this key is called the target key. The target key must exist before you can import key material into it.

Importing a key version has no effect on that key's existing versions. However, It is recommended to create an empty key when testing key import. An empty key has no version, isn't active, and can't be used.

You may optionally specify that your newly created key may only contain imported versions, which prevents accidental generation of new versions in Cloud KMS.

A key exists on a key ring; in this topic, this key ring is called the target key ring. The location of the target key ring determines the location where the key material is available after import. Cloud HSM keys cannot be created or imported in some locations. After a key is created, it cannot be moved to a different key ring or location.

Follow these steps to create an empty key on a new key ring using the Google Cloud CLI or the Google Cloud console.

Console

  1. In the Google Cloud console, go to the Key Management page.

    Go to Key Management

  2. Click Create key ring.

  3. In the Key ring name field, enter the name for your key ring.

  4. Under Location type, select a location type and location.

  5. Click Create. The Create key page opens.

  6. In the Key name field, enter the name for your key.

  7. For Protection level, select either Software or HSM, and then click Continue.

  8. For Key material, select Imported key and then click Continue. This prevents an initial key version from being created.

  9. Set the Purpose and Algorithm for the key and then click Continue.

  10. Optional: If you want this key to contain only imported key versions, select Restrict key versions to import only. This prevents you from accidentally creating new key versions in Cloud KMS.

  11. Optional: For imported keys, automatic rotation is disabled by default. To enable automatic rotation, select a value from the Key rotation period field.

    If you enable automatic rotation, new key versions will be generated in Cloud KMS, and the imported key version will no longer be the default key version after a rotation.

  12. Click Create.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

  1. Create the target key ring. If you intend to import into a Cloud HSM key, select a location with support for Cloud HSM.

    gcloud kms keyrings create KEY_RING \
      --location LOCATION
    

    You can learn more about creating key rings.

  2. Create the target key.

    • Specify the key's purpose.
    • Prevent an initial version from being created by using the --skip-initial-version-creation flag.
    • Optional: Prevent new versions from being created in Cloud KMS by using the --import-only flag.
    • Optional: Do not specify a rotation policy. If you enable automatic rotation, new key versions will be generated in Cloud KMS, and the imported key version will no longer be the default key version after a rotation. You may not specify a rotation policy if you specified the --import-only flag.
    gcloud kms keys create KEY_NAME \
      --location LOCATION \
      --keyring KEY_RING \
      --purpose PURPOSE \
      --skip-initial-version-creation \
      --import-only
    

    You can learn more about creating Cloud KMS keys or Cloud HSM keys.

Go

To run this code, first set up a Go development environment and install the Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

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

// createKeyForImport creates a new asymmetric signing key in Cloud HSM.
func createKeyForImport(w io.Writer, parent, id string) error {
	// parent := "projects/my-project/locations/us-east1/keyRings/my-key-ring"
	// id := "my-imported-key"

	// 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.CreateCryptoKeyRequest{
		Parent:      parent,
		CryptoKeyId: id,
		CryptoKey: &kmspb.CryptoKey{
			Purpose: kmspb.CryptoKey_ASYMMETRIC_SIGN,
			VersionTemplate: &kmspb.CryptoKeyVersionTemplate{
				ProtectionLevel: kmspb.ProtectionLevel_HSM,
				Algorithm:       kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256,
			},
			// Ensure that only imported versions may be added to this key.
			ImportOnly: true,
		},
		SkipInitialVersionCreation: true,
	}

	// Call the API.
	result, err := client.CreateCryptoKey(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to create key: %w", err)
	}
	fmt.Fprintf(w, "Created key: %s\n", result.Name)
	return nil
}

Java

To run this code, first set up a Java development environment and install the Cloud KMS Java SDK.

import com.google.cloud.kms.v1.CreateCryptoKeyRequest;
import com.google.cloud.kms.v1.CryptoKey;
import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose;
import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm;
import com.google.cloud.kms.v1.CryptoKeyVersionTemplate;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.cloud.kms.v1.ProtectionLevel;
import java.io.IOException;

public class CreateKeyForImport {

  public void createKeyForImport() 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 id = "my-import-key";
    createKeyForImport(projectId, locationId, keyRingId, id);
  }

  // Create a new crypto key to hold imported key versions.
  public void createKeyForImport(String projectId, String locationId, String keyRingId, String id)
      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 parent name from the project, location, and key ring.
      KeyRingName keyRingName = KeyRingName.of(projectId, locationId, keyRingId);

      // Create the crypto key.
      CryptoKey createdKey =
          client.createCryptoKey(
              CreateCryptoKeyRequest.newBuilder()
                  .setParent(keyRingName.toString())
                  .setCryptoKeyId(id)
                  .setCryptoKey(
                      CryptoKey.newBuilder()
                          .setPurpose(CryptoKeyPurpose.ASYMMETRIC_SIGN)
                          .setVersionTemplate(
                              CryptoKeyVersionTemplate.newBuilder()
                                  .setProtectionLevel(ProtectionLevel.HSM)
                                  .setAlgorithm(CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256))
                          // Ensure that only imported versions may be
                          // added to this key.
                          .setImportOnly(true))
                  .setSkipInitialVersionCreation(true)
                  .build());

      System.out.printf("Created crypto key %s%n", createdKey.getName());
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the 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 id = 'my-imported-key';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the parent key ring name
const keyRingName = client.keyRingPath(projectId, locationId, keyRingId);

async function createKeyForImport() {
  const [key] = await client.createCryptoKey({
    parent: keyRingName,
    cryptoKeyId: id,
    cryptoKey: {
      purpose: 'ENCRYPT_DECRYPT',
      versionTemplate: {
        algorithm: 'GOOGLE_SYMMETRIC_ENCRYPTION',
        protectionLevel: 'HSM',
      },
      // Optional: ensure that only imported versions may be added to this
      // key.
      importOnly: true,
    },
    // Do not allow KMS to generate an initial version of this key.
    skipInitialVersionCreation: true,
  });

  console.log(`Created key for import: ${key.name}`);
  return key;
}

return createKeyForImport();

Python

To run this code, first set up a Python development environment and install the Cloud KMS Python SDK.

from google.cloud import kms


def create_key_for_import(
    project_id: str, location_id: str, key_ring_id: str, crypto_key_id: str
) -> None:
    """

    Sets up an empty CryptoKey within a KeyRing for import.


    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').
        crypto_key_id (string): ID of the key to import (e.g. 'my-asymmetric-signing-key').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Build the key. For more information regarding allowed values of these fields, see:
    # https://googleapis.dev/python/cloudkms/latest/_modules/google/cloud/kms_v1/types/resources.html
    purpose = kms.CryptoKey.CryptoKeyPurpose.ASYMMETRIC_SIGN
    algorithm = kms.CryptoKeyVersion.CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256
    protection_level = kms.ProtectionLevel.HSM
    key = {
        "purpose": purpose,
        "version_template": {
            "algorithm": algorithm,
            "protection_level": protection_level,
        },
    }

    # Build the parent key ring name.
    key_ring_name = client.key_ring_path(project_id, location_id, key_ring_id)

    # Call the API.
    created_key = client.create_crypto_key(
        request={
            "parent": key_ring_name,
            "crypto_key_id": crypto_key_id,
            "crypto_key": key,
            # Do not allow KMS to generate an initial version of this key.
            "skip_initial_version_creation": True,
        }
    )
    print(f"Created hsm key: {created_key.name}")

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

  1. Create a new key ring:

    curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings?keyRingId=KEY_RING" \
        --request "POST" \
        --header "authorization: Bearer TOKEN" \
        --header "content-type: application/json" \
        --header "x-goog-user-project: PROJECT_ID" \
        --data "{}"
    

    See the KeyRing.create API documentation for more information.

  2. Create an empty, import-only key:

    curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys?cryptoKeyId=KEY_NAME&skipInitialVersionCreation=true&importOnly=true" \
        --request "POST" \
        --header "authorization: Bearer TOKEN" \
        --header "content-type: application/json" \
        --header "x-goog-user-project: PROJECT_ID" \
        --data "{"purpose":"PURPOSE", "versionTemplate":{"protectionLevel":"PROTECTION_LEVEL","algorithm":"ALGORITHM"}}"
    

    See the CryptoKey.create API documentation for more information.

The key ring and key now exist, but the key contains no key material, has no version, and is not active. Next, you create an import job.

Create the import job

An import job defines the characteristics of the keys it imports, including properties that cannot be changed after the key is imported.

The protection level defines whether keys imported by this import job will reside in software, in a HSM, or in an external key management system. The protection level can't be changed after the key is eventually imported.

The import method defines the algorithm used to create the wrapping key that protects imported keys during transit from your local system to the target Google Cloud project. You can choose a 3072-bit or a 4096- bit RSA key. Unless you have specific requirements, the 3072-bit wrapping key is recommended.

You can create an import job using the gcloud CLI, the Google Cloud console, or the Cloud Key Management Service API.

Console

  1. Go to the Key Management page in the Google Cloud console.

    Go to the Key Management page

  2. Click the name of the target key ring.

  3. Set the Protection level to either Software or HSM. Use the same protection level as you set for the target key.

  4. Click Create import job.

  5. In the Name field, enter the name for your import job.

  6. From the Import method dropdown, set the import method to either 3072 bit RSA or 4096 bit RSA.

  7. Click Create.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

Use a command like the following to create an import job.

gcloud kms import-jobs create IMPORT_JOB \
  --location LOCATION \
  --keyring KEY_RING \
  --import-method IMPORT_METHOD \
  --protection-level PROTECTION_LEVEL
  • Use the same key ring and location as the target key.
  • Set the protection level to either software or hsm.
  • Set the import method to either rsa-oaep-3072-sha1-aes-256 rsa-oaep-4096-sha1-aes-256, rsa-oaep-3072-sha256-aes-256, rsa-oaep-4096-sha256-aes-256, rsa-oaep-3072-sha256, or rsa-oaep-4096-sha256.

Go

To run this code, first set up a Go development environment and install the Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

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

// createImportJob creates a new job for importing keys into KMS.
func createImportJob(w io.Writer, parent, id string) error {
	// parent := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring"
	// id := "my-import-job"

	// 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.CreateImportJobRequest{
		Parent:      parent,
		ImportJobId: id,
		ImportJob: &kmspb.ImportJob{
			// See allowed values and their descriptions at
			// https://cloud.google.com/kms/docs/algorithms#protection_levels
			ProtectionLevel: kmspb.ProtectionLevel_HSM,
			// See allowed values and their descriptions at
			// https://cloud.google.com/kms/docs/key-wrapping#import_methods
			ImportMethod: kmspb.ImportJob_RSA_OAEP_3072_SHA1_AES_256,
		},
	}

	// Call the API.
	result, err := client.CreateImportJob(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to create import job: %w", err)
	}
	fmt.Fprintf(w, "Created import job: %s\n", result.Name)
	return nil
}

Java

To run this code, first set up a Java development environment and install the Cloud KMS Java SDK.

import com.google.cloud.kms.v1.ImportJob;
import com.google.cloud.kms.v1.ImportJob.ImportMethod;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.cloud.kms.v1.ProtectionLevel;
import java.io.IOException;

public class CreateImportJob {

  public void createImportJob() 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 id = "my-import-job";
    createImportJob(projectId, locationId, keyRingId, id);
  }

  // Create a new import job.
  public void createImportJob(String projectId, String locationId, String keyRingId, String id)
      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 parent name from the project, location, and key ring.
      KeyRingName keyRingName = KeyRingName.of(projectId, locationId, keyRingId);

      // Build the import job to create, with parameters.
      ImportJob importJob =
          ImportJob.newBuilder()
              // See allowed values and their descriptions at
              // https://cloud.google.com/kms/docs/algorithms#protection_levels
              .setProtectionLevel(ProtectionLevel.HSM)
              // See allowed values and their descriptions at
              // https://cloud.google.com/kms/docs/key-wrapping#import_methods
              .setImportMethod(ImportMethod.RSA_OAEP_3072_SHA1_AES_256)
              .build();

      // Create the import job.
      ImportJob createdImportJob = client.createImportJob(keyRingName, id, importJob);
      System.out.printf("Created import job %s%n", createdImportJob.getName());
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the 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 id = 'my-import-job';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the parent key ring name
const keyRingName = client.keyRingPath(projectId, locationId, keyRingId);

async function createImportJob() {
  const [importJob] = await client.createImportJob({
    parent: keyRingName,
    importJobId: id,
    importJob: {
      protectionLevel: 'HSM',
      importMethod: 'RSA_OAEP_3072_SHA256',
    },
  });

  console.log(`Created import job: ${importJob.name}`);
  return importJob;
}

return createImportJob();

Python

To run this code, first set up a Python development environment and install the Cloud KMS Python SDK.

from google.cloud import kms


def create_import_job(
    project_id: str, location_id: str, key_ring_id: str, import_job_id: str
) -> None:
    """
    Create a new import job in Cloud KMS.

    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').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified key_ring string.
    key_ring_name = client.key_ring_path(project_id, location_id, key_ring_id)

    # Set paramaters for the import job, allowed values for ImportMethod and ProtectionLevel found here:
    # https://googleapis.dev/python/cloudkms/latest/_modules/google/cloud/kms_v1/types/resources.html

    import_method = kms.ImportJob.ImportMethod.RSA_OAEP_3072_SHA1_AES_256
    protection_level = kms.ProtectionLevel.HSM
    import_job_params = {
        "import_method": import_method,
        "protection_level": protection_level,
    }

    # Call the client to create a new import job.
    import_job = client.create_import_job(
        {
            "parent": key_ring_name,
            "import_job_id": import_job_id,
            "import_job": import_job_params,
        }
    )

    print(f"Created import job: {import_job.name}")

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

To create an import job, use the ImportJobs.create method:

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/importJobs?import_job_id=IMPORT_JOB_ID" \
    --request "POST" \
    --header "authorization: Bearer TOKEN" \
    --header "content-type: application/json" \
    --data '{"import_method": "IMPORT_METHOD", "protection_level": "PROTECTION_LEVEL"}'

Replace the following:

Checking the state of the import job

The initial state for an import job is PENDING_GENERATION. When the state is ACTIVE, you can use it to import keys.

An import job expires after three days. If the import job is expired, you must create a new one.

You can check the status of an import job using the Google Cloud CLI, the Google Cloud console, or the Cloud Key Management Service API.

Console

  1. Go to the Key Management page in the Google Cloud console.

    Go to the Key Management page

  2. Click the name of the key ring that contains your import job.

  3. Click the Import Jobs tab at the top of the page.

  4. The state will be visible under Status next to your import job's name.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

When an import job is active, you can use it to import keys. This may take a few minutes. Use this command to verify that the import job is active. Use the location and keyring where you created the import job.

gcloud kms import-jobs describe IMPORT_JOB \
  --location LOCATION \
  --keyring KEY_RING \
  --format="value(state)"

The output is similar to the following:

state: ACTIVE

Go

To run this code, first set up a Go development environment and install the Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

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

// checkStateImportJob checks the state of an ImportJob in KMS.
func checkStateImportJob(w io.Writer, name string) error {
	// name := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/importJobs/my-import-job"

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

	// Call the API.
	result, err := client.GetImportJob(ctx, &kmspb.GetImportJobRequest{
		Name: name,
	})
	if err != nil {
		return fmt.Errorf("failed to get import job: %w", err)
	}
	fmt.Fprintf(w, "Current state of import job %q: %s\n", result.Name, result.State)
	return nil
}

Java

To run this code, first set up a Java development environment and install the Cloud KMS Java SDK.

import com.google.cloud.kms.v1.ImportJob;
import com.google.cloud.kms.v1.ImportJobName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import java.io.IOException;

public class CheckStateImportJob {

  public void checkStateImportJob() 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 importJobId = "my-import-job";
    checkStateImportJob(projectId, locationId, keyRingId, importJobId);
  }

  // Check the state of an import job in Cloud KMS.
  public void checkStateImportJob(
      String projectId, String locationId, String keyRingId, String importJobId)
      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 parent name from the project, location, and key ring.
      ImportJobName importJobName = ImportJobName.of(projectId, locationId, keyRingId, importJobId);

      // Retrieve the state of an existing import job.
      ImportJob importJob = client.getImportJob(importJobName);
      System.out.printf(
          "Current state of import job %s: %s%n", importJob.getName(), importJob.getState());
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the 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 importJobId = 'my-import-job';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the import job name
const importJobName = client.importJobPath(
  projectId,
  locationId,
  keyRingId,
  importJobId
);

async function checkStateImportJob() {
  const [importJob] = await client.getImportJob({
    name: importJobName,
  });

  console.log(
    `Current state of import job ${importJob.name}: ${importJob.state}`
  );
  return importJob;
}

return checkStateImportJob();

Python

To run this code, first set up a Python development environment and install the Cloud KMS Python SDK.

from google.cloud import kms


def check_state_import_job(
    project_id: str, location_id: str, key_ring_id: str, import_job_id: str
) -> None:
    """
    Check the state of an import job in Cloud KMS.

    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').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified import_job string.
    import_job_name = client.import_job_path(
        project_id, location_id, key_ring_id, import_job_id
    )

    # Retrieve the state from an existing import job.
    import_job = client.get_import_job(name=import_job_name)

    print(f"Current state of import job {import_job.name}: {import_job.state}")

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

To check the state of an import job, use the ImportJobs.get method:

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/importJobs/IMPORT_JOB_ID" \
    --request "GET" \
    --header "authorization: Bearer TOKEN"

As soon as the import job is active, you can make a request to import a key.

Preventing modification of import jobs

The import job determines many characteristics of the imported key, including the key's algorithm and whether an imported key is an HSM key or a software key. You can configure IAM permissions to prevent users from creating import jobs, while allowing them to use import jobs to import keys.

  1. Grant the importjobs.create permission only to key administrators.
  2. Grant the importjobs.useToImport permission for a specific import job to the operator who will use that job to import keys.
  3. When you create the import job, specify the protection level and algorithm for key versions imported using it.

Until the import job expires, users who have the importjobs.useToImport and do not have the importjobs.create permission for a given import job can import keys, but cannot modify the characteristics of the import job.

Import the key

After checking the status of the import job, you can make an import request.

You use different flags to make the import request, depending on whether you want the Google Cloud CLI to wrap your key automatically or if you have already wrapped your key manually.

Regardless of whether you wrapped your key manually or automatically, you must set the algorithm to a supported algorithm that matches the length of the actual key to be imported, and specifies the key's purpose.

  • Keys with purpose ENCRYPT_DECRYPT use the google-symmetric-encryption algorithm, and have a length of 32.

  • Keys with purpose ASYMMETRIC_DECRYPT or ASYMMETRIC_SIGN support a variety of algorithms and lengths.

    A key's purpose cannot be changed after the key is created, but subsequent key versions can be created at different lengths than the initial key version.

Automatically wrapping and importing a key

If you want to use automatic wrapping, you must use the Google Cloud CLI. Use a command like the following. Set --target-key-file to the location of the unwrapped key to wrap and import. Do not set --wrapped-key-file.

You can optionally set the --public-key-file flag to the location where the public key has already been downloaded. When importing a large number of keys, this prevents the public key from being downloaded during each import. For example, you could write a script that downloaded the public key once, then provided its location when importing each key.

gcloud kms keys versions import \
    --import-job IMPORT_JOB \
    --location LOCATION \
    --keyring KEY_RING \
    --key KEY_NAME \
    --algorithm ALGORITHM \
    --target-key-file PATH_TO_UNWRAPPED_KEY

The key is wrapped by the wrapping key associated with the import job, transmitted to Google Cloud, and imported as a new key version on the target key.

Importing a manually-wrapped key

Use the instructions in this section to import a key that you have wrapped manually. Set --wrapped-key-file to the location of key that you manually wrapped. Do not set --target-key-file.

You can optionally set the --public-key-file flag to the location where the public key has already been downloaded. When importing a large number of keys, this prevents the public key from being downloaded during each import. For example, you could write a script that downloaded the public key once, then provided its location when importing each key.

Console

  1. Open the Key Management page in the Google Cloud console.

  2. Click the name of the key ring that contains your import job. The target key is shown, along with any other keys on the key ring.

  3. Click the name of the target key, then click Import key version.

  4. Select your import job from the Select import job dropdown.

  5. In the Upload the wrapped key selector, select the key that you have already wrapped.

  6. If you are importing an asymmetric key, select the algorithm from the Algorithm dropdown. Your Import key version page should look similar to:

    Import key version

  7. Click Import.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

Use a command like the following.

gcloud kms keys versions import \
  --import-job IMPORT_JOB \
  --location LOCATION \
  --keyring KEY_RING \
  --key KEY_NAME \
  --algorithm ALGORITHM \
  --wrapped-key-file PATH_TO_WRAPPED_KEY

For more information, see the output of the gcloud kms keys versions import --help command.

Go

To run this code, first set up a Go development environment and install the Cloud KMS Go SDK.

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
	"cloud.google.com/go/kms/apiv1/kmspb"
	"github.com/google/tink/go/kwp/subtle"
)

// importManuallyWrappedKey wraps key material and imports it into KMS.
func importManuallyWrappedKey(w io.Writer, importJobName, cryptoKeyName string) error {
	// importJobName := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/importJobs/my-import-job"
	// cryptoKeyName := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/cryptoKeys/my-imported-key"

	// Generate a ECDSA keypair, and format the private key as PKCS #8 DER.
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return fmt.Errorf("failed to generate keypair: %w", err)
	}
	keyBytes, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		return fmt.Errorf("failed to format private key: %w", err)
	}

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

	// Generate a temporary 32-byte key for AES-KWP and wrap the key material.
	kwpKey := make([]byte, 32)
	if _, err := rand.Read(kwpKey); err != nil {
		return fmt.Errorf("failed to generate AES-KWP key: %w", err)
	}
	kwp, err := subtle.NewKWP(kwpKey)
	if err != nil {
		return fmt.Errorf("failed to create KWP cipher: %w", err)
	}
	wrappedTarget, err := kwp.Wrap(keyBytes)
	if err != nil {
		return fmt.Errorf("failed to wrap target key with KWP: %w", err)
	}

	// Retrieve the public key from the import job.
	importJob, err := client.GetImportJob(ctx, &kmspb.GetImportJobRequest{
		Name: importJobName,
	})
	if err != nil {
		return fmt.Errorf("failed to retrieve import job: %w", err)
	}
	pubBlock, _ := pem.Decode([]byte(importJob.PublicKey.Pem))
	pubAny, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse import job public key: %w", err)
	}
	pub, ok := pubAny.(*rsa.PublicKey)
	if !ok {
		return fmt.Errorf("unexpected public key type %T, want *rsa.PublicKey", pubAny)
	}

	// Wrap the KWP key using the import job key.
	wrappedWrappingKey, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, pub, kwpKey, nil)
	if err != nil {
		return fmt.Errorf("failed to wrap KWP key: %w", err)
	}

	// Concatenate the wrapped KWP key and the wrapped target key.
	combined := append(wrappedWrappingKey, wrappedTarget...)

	// Build the request.
	req := &kmspb.ImportCryptoKeyVersionRequest{
		Parent:     cryptoKeyName,
		ImportJob:  importJobName,
		Algorithm:  kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256,
		WrappedKey: combined,
	}

	// Call the API.
	result, err := client.ImportCryptoKeyVersion(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to import crypto key version: %w", err)
	}
	fmt.Fprintf(w, "Created crypto key version: %s\n", result.Name)
	return nil
}

Java

To run this code, first set up a Java development environment and install the Cloud KMS Java SDK.

import com.google.cloud.kms.v1.CryptoKeyName;
import com.google.cloud.kms.v1.CryptoKeyVersion;
import com.google.cloud.kms.v1.ImportCryptoKeyVersionRequest;
import com.google.cloud.kms.v1.ImportJob;
import com.google.cloud.kms.v1.ImportJobName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.crypto.tink.subtle.Kwp;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;

public class ImportManuallyWrappedKey {

  public void importManuallyWrappedKey() throws GeneralSecurityException, 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 cryptoKeyId = "my-crypto-key";
    String importJobId = "my-import-job";
    importManuallyWrappedKey(projectId, locationId, keyRingId, cryptoKeyId, importJobId);
  }

  // Generates and imports local key material into Cloud KMS.
  public void importManuallyWrappedKey(
      String projectId, String locationId, String keyRingId, String cryptoKeyId, String importJobId)
      throws GeneralSecurityException, IOException {

    // Generate a new ECDSA keypair, and format the private key as PKCS #8 DER.
    KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
    generator.initialize(new ECGenParameterSpec("secp256r1"));
    KeyPair kp = generator.generateKeyPair();
    byte[] privateBytes = kp.getPrivate().getEncoded();

    // 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 crypto key and import job names from the project, location,
      // key ring, and ID.
      final CryptoKeyName cryptoKeyName =
          CryptoKeyName.of(projectId, locationId, keyRingId, cryptoKeyId);
      final ImportJobName importJobName =
          ImportJobName.of(projectId, locationId, keyRingId, importJobId);

      // Generate a temporary 32-byte key for AES-KWP and wrap the key material.
      byte[] kwpKey = new byte[32];
      new SecureRandom().nextBytes(kwpKey);
      Kwp kwp = new Kwp(kwpKey);
      final byte[] wrappedTargetKey = kwp.wrap(privateBytes);

      // Retrieve the public key from the import job.
      ImportJob importJob = client.getImportJob(importJobName);
      String publicKeyStr = importJob.getPublicKey().getPem();
      // Manually convert PEM to DER. :-(
      publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "");
      publicKeyStr = publicKeyStr.replace("-----END PUBLIC KEY-----", "");
      publicKeyStr = publicKeyStr.replaceAll("\n", "");
      byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
      PublicKey publicKey =
          KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));

      // Wrap the KWP key using the import job key.
      Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
      cipher.init(
          Cipher.ENCRYPT_MODE,
          publicKey,
          new OAEPParameterSpec(
              "SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT));
      byte[] wrappedWrappingKey = cipher.doFinal(kwpKey);

      // Concatenate the wrapped KWP key and the wrapped target key.
      ByteString combinedWrappedKeys =
          ByteString.copyFrom(wrappedWrappingKey).concat(ByteString.copyFrom(wrappedTargetKey));

      // Import the wrapped key material.
      CryptoKeyVersion version =
          client.importCryptoKeyVersion(
              ImportCryptoKeyVersionRequest.newBuilder()
                  .setParent(cryptoKeyName.toString())
                  .setImportJob(importJobName.toString())
                  .setAlgorithm(CryptoKeyVersion.CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256)
                  .setRsaAesWrappedKey(combinedWrappedKeys)
                  .build());

      System.out.printf("Imported: %s%n", version.getName());
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the 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 cryptoKeyId = 'my-imported-key';
// const importJobId = 'my-import-job';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the crypto key and importjob resource names
const cryptoKeyName = client.cryptoKeyPath(
  projectId,
  locationId,
  keyRingId,
  cryptoKeyId
);
const importJobName = client.importJobPath(
  projectId,
  locationId,
  keyRingId,
  importJobId
);

async function wrapAndImportKey() {
  // Generate a 32-byte key to import.
  const crypto = require('crypto');
  const targetKey = crypto.randomBytes(32);

  const [importJob] = await client.getImportJob({name: importJobName});

  // Wrap the target key using the import job key
  const wrappedTargetKey = crypto.publicEncrypt(
    {
      key: importJob.publicKey.pem,
      oaepHash: 'sha256',
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
    },
    targetKey
  );

  // Import the target key version
  const [version] = await client.importCryptoKeyVersion({
    parent: cryptoKeyName,
    importJob: importJobName,
    algorithm: 'GOOGLE_SYMMETRIC_ENCRYPTION',
    wrappedKey: wrappedTargetKey,
  });

  console.log(`Imported key version: ${version.name}`);
  return version;
}

return wrapAndImportKey();

Python

To run this code, first set up a Python development environment and install the Cloud KMS Python SDK.

import os

# Import the client library and Python standard cryptographic libraries.
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import keywrap
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import padding
from google.cloud import kms


def import_manually_wrapped_key(
    project_id: str,
    location_id: str,
    key_ring_id: str,
    crypto_key_id: str,
    import_job_id: str,
) -> None:
    """
    Generates and imports local key material to Cloud KMS.

    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').
        crypto_key_id (string): ID of the key to import (e.g. 'my-asymmetric-signing-key').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Generate some key material in Python and format it in PKCS #8 DER as
    # required by Google Cloud KMS.
    key = ec.generate_private_key(ec.SECP256R1, backends.default_backend())
    formatted_key = key.private_bytes(
        serialization.Encoding.DER,
        serialization.PrivateFormat.PKCS8,
        serialization.NoEncryption(),
    )

    print(f"Generated key bytes: {formatted_key!r}")

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified crypto_key and import_job string.
    crypto_key_name = client.crypto_key_path(
        project_id, location_id, key_ring_id, crypto_key_id
    )
    import_job_name = client.import_job_path(
        project_id, location_id, key_ring_id, import_job_id
    )

    # Generate a temporary 32-byte key for AES-KWP and wrap the key material.
    kwp_key = os.urandom(32)
    wrapped_target_key = keywrap.aes_key_wrap_with_padding(
        kwp_key, formatted_key, backends.default_backend()
    )

    # Retrieve the public key from the import job.
    import_job = client.get_import_job(name=import_job_name)
    import_job_pub = serialization.load_pem_public_key(
        bytes(import_job.public_key.pem, "UTF-8"), backends.default_backend()
    )

    # Wrap the KWP key using the import job key.
    wrapped_kwp_key = import_job_pub.encrypt(
        kwp_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA1()),
            algorithm=hashes.SHA1(),
            label=None,
        ),
    )

    # Import the wrapped key material.
    client.import_crypto_key_version(
        {
            "parent": crypto_key_name,
            "import_job": import_job_name,
            "algorithm": kms.CryptoKeyVersion.CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256,
            "rsa_aes_wrapped_key": wrapped_kwp_key + wrapped_target_key,
        }
    )

    print(f"Imported: {import_job.name}")

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

Use the cryptoKeyVersions.import method to import a key.

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions:import" \
    --request "POST" \
    --header "authorization: Bearer TOKEN" \
    --header "content-type: application/json" \
    --data '{"importJob": "IMPORT_JOB_ID", "algorithm": "ALGORITHM", "wrappedKey": "WRAPPED_KEY"}'

Replace the following:

  • IMPORT_JOB_ID: the full resource name of the corresponding import job.

  • ALGORITHM: the algorithm of the key being imported, which is of type CryptoKeyVersionAlgorithm.

  • WRAPPED_KEY: the manually-wrapped key in base64 format.

The key-import request is initiated. You can monitor its status.

Check the state of the imported key version

The initial state for an imported key version is PENDING_IMPORT. When the state is ENABLED, the key version has been imported successfully. If the import fails, the status is IMPORT_FAILED.

You can check the status of an import request using the Google Cloud CLI, the Google Cloud console, or the Cloud Key Management Service API.

Console

  1. Open the Key Management page in the Google Cloud console.

  2. Click the name of the key ring that contains your import job.

  3. Click the Import Jobs tab at the top of the page.

  4. The state will be visible under Status next to your import job's name.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

Use the versions list command to check the state. Use the same location, target key ring, and target key that you created earlier in this topic.

gcloud kms keys versions list \
  --keyring KEY_RING \
  --location LOCATION \
  --key KEY_NAME

Go

To run this code, first set up a Go development environment and install the Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

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

// checkStateImportedKey checks the state of a CryptoKeyVersion in KMS.
func checkStateImportedKey(w io.Writer, name string) error {
	// name := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/cryptoKeys/my-imported-key/cryptoKeyVersions/1"

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

	// Call the API.
	result, err := client.GetCryptoKeyVersion(ctx, &kmspb.GetCryptoKeyVersionRequest{
		Name: name,
	})
	if err != nil {
		return fmt.Errorf("failed to get crypto key version: %w", err)
	}
	fmt.Fprintf(w, "Current state of crypto key version %q: %s\n", result.Name, result.State)
	return nil
}

Java

To run this code, first set up a Java development environment and install the Cloud KMS Java SDK.

import com.google.cloud.kms.v1.CryptoKeyVersion;
import com.google.cloud.kms.v1.CryptoKeyVersionName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import java.io.IOException;

public class CheckStateImportedKey {

  public void checkStateImportedKey() 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 cryptoKeyId = "my-crypto-key";
    String cryptoKeyVersionId = "1";
    checkStateImportedKey(projectId, locationId, keyRingId, cryptoKeyId, cryptoKeyVersionId);
  }

  // Check the state of an imported key in Cloud KMS.
  public void checkStateImportedKey(
      String projectId,
      String locationId,
      String keyRingId,
      String cryptoKeyId,
      String cryptoKeyVersionId)
      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 version name from its path components.
      CryptoKeyVersionName versionName =
          CryptoKeyVersionName.of(
              projectId, locationId, keyRingId, cryptoKeyId, cryptoKeyVersionId);

      // Retrieve the state of an existing version.
      CryptoKeyVersion version = client.getCryptoKeyVersion(versionName);
      System.out.printf(
          "Current state of crypto key version %s: %s%n", version.getName(), version.getState());
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the 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 cryptoKeyId = 'my-imported-key';
// const cryptoKeyVersionId = '1';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the key version name
const keyVersionName = client.cryptoKeyVersionPath(
  projectId,
  locationId,
  keyRingId,
  cryptoKeyId,
  cryptoKeyVersionId
);

async function checkStateCryptoKeyVersion() {
  const [keyVersion] = await client.getCryptoKeyVersion({
    name: keyVersionName,
  });

  console.log(
    `Current state of key version ${keyVersion.name}: ${keyVersion.state}`
  );
  return keyVersion;
}

return checkStateCryptoKeyVersion();

Python

To run this code, first set up a Python development environment and install the Cloud KMS Python SDK.

from google.cloud import kms


def check_state_imported_key(
    project_id: str, location_id: str, key_ring_id: str, import_job_id: str
) -> None:
    """
    Check the state of an import job in Cloud KMS.

    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').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified import_job string.
    import_job_name = client.import_job_path(
        project_id, location_id, key_ring_id, import_job_id
    )

    # Retrieve the state from an existing import job.
    import_job = client.get_import_job(name=import_job_name)

    print(f"Current state of import job {import_job.name}: {import_job.state}")

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

Call the ImportJob.get method and check the state field. If state is PENDING_GENERATION, the import job is still being created. Periodically recheck the state until it is ACTIVE.

After the initial key version is imported, the key's status changes to Active. For symmetric keys, you must set the imported key version as the primary version before you can use the key.

Symmetric keys: Set the primary version

This step is required when importing symmetric keys, and is not relevant for asymmetric keys. An asymmetric key does not have a primary version. You must use the Google Cloud CLI to set the primary version.

gcloud kms keys set-primary-version KEY_NAME\
    --location=LOCATION\
    --keyring=KEY_RING\
    --version=KEY_VERSION

Re-import a previously destroyed key

Cloud Key Management Service supports key re-import, which allows you to restore a previously imported key version in DESTROYED or IMPORT_FAILED state to ENABLED state by providing the original key material. If no original key material has ever been imported due to initial import failure, any key material may be supplied.

Restrictions

  • Only previously imported CryptoKeyVersions can be re-imported.
  • Re-imported key material must match the original key material exactly if the version was previously successfully imported.
  • CryptoKeyVersions destroyed prior to the release of this feature can't be re-imported. The reimport_eligible field of the CryptoKeyVersion is true if the version is eligible for re-import and false if it isn't.

Software and Cloud HSM keys can be re-imported, but external keys can't be re-imported.

Re-importing a destroyed key

Create an ImportJob for re-import by following the steps in Create the import job. You may use either an existing ImportJob or a new ImportJob as long as the protection level matches the original protection level.

Console

  1. Go to the Key Management page in the Google Cloud console.

    Go to the Key Management page

  2. Click the name of the key ring that contains the key whose key version you will re-import.

  3. Click the key whose key version you want to re-import.

  4. Click the three dots next to the key version you want to re-import.

  5. Select Re-import key version

  6. Select your import job from the Select import job dropdown.

  7. In the Upload the wrapped key selector, select the key that you have already wrapped. This key must match the original key material.

  8. Click Re-Import.

gcloud

To use Cloud KMS on the command line, first Install or upgrade to the latest version of Google Cloud CLI.

  1. Re-import the key version using the original key material.

    gcloud kms keys versions import \
    --location LOCATION \
    --keyring KEY_RING \
    --key KEY_NAME \
    --version KEY_VERSION \
    --algorithm ALGORITHM \
    --import-job IMPORT_JOB \
    --target-key-file PATH_TO_KEY \
    

API

These examples use curl as an HTTP client to demonstrate using the API. For more information about access control, see Accessing the Cloud KMS API.

  1. In the request body of the cryptoKeyVersions.import method, set the cryptoKeyVersion field to the key version name of the version being imported. This must be a child of the crypto key.

  2. In the request body, set the algorithm field to the algorithm of the key being imported. This value must match the algorithm of the original key version. The algorithm field is of type CryptoKeyVersionAlgorithm.

  3. In the request body, set the wrappedKeyMaterial field to the key material that you that you have already wrapped.

  4. Call the cryptoKeyVersions.import method. The cryptoKeyVersions.import response is of type CryptoKeyVersion. When a key is successfully imported, its state is ENABLED and you can use it in Cloud KMS.

What's next