Rotate an encryption key

Rotate an encryption key.

Documentation pages that include this code sample

To view the code sample used in context, see the following documentation:

Code sample

C++

For more information, see the Cloud Storage C++ API reference documentation.

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& object_name, std::string const& old_key_base64,
   std::string const& new_key_base64) {
  StatusOr<gcs::ObjectMetadata> object_metadata =
      client.RewriteObjectBlocking(
          bucket_name, object_name, bucket_name, object_name,
          gcs::SourceEncryptionKey::FromBase64Key(old_key_base64),
          gcs::EncryptionKey::FromBase64Key(new_key_base64));

  if (!object_metadata) {
    throw std::runtime_error(object_metadata.status().message());
  }

  std::cout << "Rotated key on object " << object_metadata->name()
            << " in bucket " << object_metadata->bucket()
            << "\nFull Metadata: " << *object_metadata << "\n";
}

Go

For more information, see the Cloud Storage Go API reference documentation.

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/storage"
)

// rotateEncryptionKey encrypts an object with the newKey.
func rotateEncryptionKey(w io.Writer, bucket, object string, key, newKey []byte) error {
	// bucket := "bucket-name"
	// object := "object-name"
	// key := []byte("encryption-key")
	// newKey := []byte("new-encryption-key")
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %v", err)
	}
	defer client.Close()

	obj := client.Bucket(bucket).Object(object)

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	// obj is encrypted with key, we are encrypting it with the newKey.
	_, err = obj.Key(newKey).CopierFrom(obj.Key(key)).Run(ctx)
	if err != nil {
		return fmt.Errorf("Key(%q).CopierFrom(%q).Run: %v", newKey, key, err)
	}
	fmt.Fprintf(w, "Key rotation complete for blob %v.\n", object)
	return nil
}

Java

For more information, see the Cloud Storage Java API reference documentation.

import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class RotateObjectEncryptionKey {
  public static void rotateObjectEncryptionKey(
      String projectId,
      String bucketName,
      String objectName,
      String oldEncryptionKey,
      String newEncryptionKey) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    // The ID of your GCS object
    // String objectName = "your-object-name";

    // The Base64 encoded AES-256 encryption key originally used to encrypt the object. See the
    // documentation
    // on Customer-Supplied Encryption keys for more info:
    // https://cloud.google.com/storage/docs/encryption/using-customer-supplied-keys
    // String oldEncryptionKey = "TIbv/fjexq+VmtXzAlc63J4z5kFmWJ6NdAPQulQBT7g="

    // The new encryption key to use
    // String newEncryptionKey = "0mMWhFvQOdS4AmxRpo8SJxXn5MjFhbz7DkKBUdUIef8="

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    BlobId blobId = BlobId.of(bucketName, objectName);
    // You can't change an object's encryption key directly, the only way is to overwrite the object
    Storage.CopyRequest request =
        Storage.CopyRequest.newBuilder()
            .setSource(blobId)
            .setSourceOptions(Storage.BlobSourceOption.decryptionKey(oldEncryptionKey))
            .setTarget(blobId, Storage.BlobTargetOption.encryptionKey(newEncryptionKey))
            .build();
    storage.copy(request);

    System.out.println(
        "Rotated encryption key for object " + objectName + "in bucket " + bucketName);
  }
}

Node.js

For more information, see the Cloud Storage Node.js API reference documentation.

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

// The ID of your GCS file
// const fileName = 'your-file-name';

// The Base64 encoded AES-256 encryption key originally used to encrypt the
// object. See the documentation on Customer-Supplied Encryption keys for
// more info:
// https://cloud.google.com/storage/docs/encryption/using-customer-supplied-keys
// The Base64 encoded AES-256 encryption key originally used to encrypt the
// const oldKey = 'TIbv/fjexq+VmtXzAlc63J4z5kFmWJ6NdAPQulQBT7g=';

// The new encryption key to use
// const newKey = '0mMWhFvQOdS4AmxRpo8SJxXn5MjFhbz7DkKBUdUIef8=';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function rotateEncryptionKey() {
  await storage
    .bucket(bucketName)
    .file(fileName, {
      encryptionKey: Buffer.from(oldKey, 'base64'),
    })
    .rotateEncryptionKey({
      encryptionKey: Buffer.from(newKey, 'base64'),
    });

  console.log('Encryption key rotated successfully');
}

rotateEncryptionKey().catch(console.error);

PHP

For more information, see the Cloud Storage PHP API reference documentation.

use Google\Cloud\Storage\StorageClient;

/**
 * Change the encryption key used to store an existing object.
 *
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of your Google Cloud object.
 * @param string $base64EncryptionKey the base64 encoded encryption key.
 * @param string $newBase64EncryptionKey the new base64 encoded encryption key.
 *
 * @return void
 */
function rotate_encryption_key(
    $bucketName,
    $objectName,
    $base64EncryptionKey,
    $newBase64EncryptionKey
) {
    $storage = new StorageClient();
    $object = $storage->bucket($bucketName)->object($objectName);

    $rewrittenObject = $object->rewrite($bucketName, [
        'encryptionKey' => $base64EncryptionKey,
        'destinationEncryptionKey' => $newBase64EncryptionKey,
    ]);

    printf('Rotated encryption key for object gs://%s/%s' . PHP_EOL,
        $bucketName, $objectName);
}

Python

For more information, see the Cloud Storage Python API reference documentation.

import base64

from google.cloud import storage


def rotate_encryption_key(
    bucket_name, blob_name, base64_encryption_key, base64_new_encryption_key
):
    """Performs a key rotation by re-writing an encrypted blob with a new
    encryption key."""
    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    current_encryption_key = base64.b64decode(base64_encryption_key)
    new_encryption_key = base64.b64decode(base64_new_encryption_key)

    # Both source_blob and destination_blob refer to the same storage object,
    # but destination_blob has the new encryption key.
    source_blob = bucket.blob(
        blob_name, encryption_key=current_encryption_key
    )
    destination_blob = bucket.blob(
        blob_name, encryption_key=new_encryption_key
    )

    token = None

    while True:
        token, bytes_rewritten, total_bytes = destination_blob.rewrite(
            source_blob, token=token
        )
        if token is None:
            break

    print("Key rotation complete for Blob {}".format(blob_name))

Ruby

For more information, see the Cloud Storage Ruby API reference documentation.

def rotate_encryption_key bucket_name:, file_name:, current_encryption_key:, new_encryption_key:
  # The ID of your GCS bucket
  # bucket_name = "your-unique-bucket-name"

  # The ID of your GCS object
  # file_name = "your-file-name"

  # The Base64 encoded AES-256 encryption key originally used to encrypt the object.
  # See the documentation on Customer-Supplied Encryption keys for more info:
  # https://cloud.google.com/storage/docs/encryption/using-customer-supplied-keys
  # current_encryption_key = "TIbv/fjexq+VmtXzAlc63J4z5kFmWJ6NdAPQulQBT7g="

  # The new encryption key to use
  # new_encryption_key = "0mMWhFvQOdS4AmxRpo8SJxXn5MjFhbz7DkKBUdUIef8="

  require "google/cloud/storage"

  storage = Google::Cloud::Storage.new
  bucket  = storage.bucket bucket_name
  file    = bucket.file file_name, encryption_key: current_encryption_key

  file.rotate encryption_key:     current_encryption_key,
              new_encryption_key: new_encryption_key

  puts "The encryption key for #{file.name} in #{bucket.name} was rotated."
end

What's next

To search and filter code samples for other Google Cloud products, see the Google Cloud sample browser