Google Cloud KMS encryption provider
Google Cloud KMS provider implementing crypto.EncryptionProvider. Master keys live in Google's Hardware Security Modules. Every encrypt and decrypt call goes through the Cloud KMS API.
Overview
GCP KMS is structurally the same model as AWS KMS. The master key cannot leave the HSM, Cloud Audit Logs records every operation, and IAM gates access. The provider is a drop-in EncryptionProvider. You write NewProvider plus two piko.With options, and Piko handles the rest. It satisfies the full port (Encrypt, Decrypt, GenerateDataKey, GetKeyInfo, HealthCheck, EncryptStream, DecryptStream), so it works everywhere the crypto service runs with no adapter glue.
The differences from AWS are operational. Cloud KMS keys live inside key rings, scoped to a location. A location can be global, regional (for example us-central1, europe-west1), or multi-regional (us, eu, asia). A multi-regional key ring replicates as one logical key with consistent IAM and audit semantics across regions. For the full location model, see Cloud KMS locations.
The provider supports direct encryption (small payloads, one KMS call per operation), envelope encryption through GenerateDataKey, and streaming encryption for large objects. GCP KMS has no native data-key API, so the provider emulates envelope encryption. It generates a random DEK locally and wraps it with one Encrypt call to KMS. EncryptStream and DecryptStream issue exactly one KMS call per stream, then run local AES-256-GCM at constant memory of about 64 KB regardless of file size. Large uploads stay cheap, and you write no envelope code yourself.
The crypto service layer wraps every provider in a circuit breaker. Five consecutive failures open it for 30 seconds, so a KMS outage fails fast instead of stalling the caller.
Authentication uses Google's Application Default Credentials by default, workload identity on GKE, the attached service account on GCE/Cloud Run, or gcloud auth application-default login for local development. Pass extra option.ClientOption values (for example an explicit credentials file) as variadic arguments after the config when ADC is not enough. All public methods are safe for concurrent use.
The provider is pure Go and ships as its own module (piko.sh/piko/wdk/crypto/crypto_provider_gcp_kms), pulling in the cloud.google.com/go/kms gRPC stack. It needs no build tag or CGO, so it runs in interpreted dev mode as well as compiled builds.
Requirements
- A GCP project with the Cloud KMS API enabled.
- A key ring and key created beforehand at the chosen location.
- An identity (service account or user) with
roles/cloudkms.cryptoKeyEncrypterDecrypteron the key, or the granularcloudkms.cryptoKeyVersions.useToEncryptandcloudkms.cryptoKeyVersions.useToDecryptpermissions. - Authentication via Application Default Credentials, or explicit
option.ClientOptionvalues passed toNewProvider. - Network egress to
cloudkms.googleapis.com.
Configuration
import (
"context"
"piko.sh/piko/wdk/crypto/crypto_provider_gcp_kms"
)
provider, err := crypto_provider_gcp_kms.NewProvider(ctx, crypto_provider_gcp_kms.Config{
ProjectID: "my-gcp-project", // required
Location: "europe-west1", // required; "global", region, or multi-region
KeyRing: "myapp-prod", // required
KeyName: "primary", // required
})
if err != nil {
return err
}
Config.Validate() rejects missing required fields. Pass option.ClientOption values (from google.golang.org/api/option) as variadic arguments after the config to override credentials, endpoints, or HTTP transports.
NewProvider makes a live GetCryptoKey call to KMS at construction time. Wiring this provider into piko.New blocks on KMS reachability. It fails at startup if the key does not exist, the principal lacks permission, or the network drops egress to cloudkms.googleapis.com. This surfaces a misconfigured key as a boot error, not as a first-request failure.
Bootstrap
server := piko.New(
piko.WithCryptoProvider("gcp_kms", provider),
piko.WithDefaultCryptoProvider("gcp_kms"),
)
When this provider runs alongside the storage service, the container registers the crypto stream transformer against the storage pipeline for you. The pipeline then encrypts uploads at rest with no manual RegisterTransformer call.
Tradeoffs
Like all KMS providers, every direct encrypt and decrypt call is a billable network round-trip with audit overhead. For high-volume workloads, use envelope encryption. GenerateDataKey produces a random DEK locally and wraps it with a single KMS Encrypt call. Encrypt the bulk data locally with the plaintext DEK, and store the wrapped DEK alongside the ciphertext. The Piko crypto service supports this pattern without extra configuration. The provider returns each generated data key in secure memory and zeroes the plaintext after use, so it handles key hygiene for you. Reach for envelope encryption before you reach for more KMS quota.
See also
Other crypto providers:
- AWS KMS, equivalent HSM-backed model on AWS.
- Local AES-GCM, in-process AES-256-GCM with a local key file. Trades the audit trail and per-op latency of KMS for zero per-op cost.
Storage transformer (the typical consumer):
- Crypto transformer, wraps the storage pipeline so this provider encrypts uploads at rest.
Framework docs:
- How to encrypt and decrypt data, wiring the crypto service end-to-end.
- Crypto API reference, every type and method on the crypto service.
External:
- Cloud KMS documentation, authoritative reference.
- Cloud KMS locations, global, regional, and multi-region semantics.
- Cloud KMS pricing, read this before high-volume rollouts.