Back to blog
Best PracticesCloud SecurityGCPIdentity & AccessOperations & Compliance

KMS Key Uses Weak Encryption: Detecting and Fixing Weak GCP Cloud KMS Keys

Learn how to detect and remediate GCP Cloud KMS keys using weak algorithms or short key lengths, with CLI, Terraform, and policy-as-code prevention steps.

TL;DR

This check flags Cloud KMS keys that use weaker algorithms or shorter key lengths than your compliance baseline requires. Weak keys undermine data-at-rest protection and can fail audits. Fix it by creating a new key version with a strong algorithm (AES-256 or RSA-3072+) and rotating workloads onto it.

Encryption keys are only as strong as the algorithm and key length behind them. In Google Cloud KMS it is easy to spin up a key without thinking hard about the crypto parameters, and the defaults are not always what your security policy demands. The kms_lowencryption check looks for Cloud KMS keys that fall below a minimum encryption standard, so you can catch them before an auditor or an attacker does.


What this check detects

The KMS Key Uses Weak Encryption check inspects your Cloud KMS key versions and flags any whose algorithm or key size does not meet a recommended minimum. In practice that means looking at the algorithm field on each crypto key version and the protectionLevel of the key.

Common conditions that trigger this check:

  • A symmetric key configured below the AES-256 standard, or relying on a deprecated cipher.
  • An asymmetric RSA key using a 2048-bit modulus where your policy requires RSA-3072 or RSA-4096.
  • An EC signing key using a weaker curve than your baseline allows.
  • Keys whose algorithm has been marked for deprecation or sunset by NIST guidance.

Note: Cloud KMS does not let you create truly broken keys like DES or MD5-based signing. The risk here is subtler: using algorithms or key lengths that are technically supported but too weak for your data classification or regulatory regime. RSA-2048, for example, is still allowed but is being phased toward RSA-3072 as a minimum for long-lived secrets.


Why it matters

A KMS key protects everything that references it: Cloud Storage objects, persistent disks, BigQuery datasets, Secret Manager secrets, and application-level envelope encryption. If the key itself is weak, every downstream resource inherits that weakness.

Real-world risk

  • Harvest now, decrypt later. An attacker who exfiltrates ciphertext today can sit on it until compute or cryptanalytic advances make a weaker key feasible to break. RSA-2048 and shorter keys are the usual targets of this strategy.
  • Compliance failure. FedRAMP, PCI DSS, HIPAA, and many internal data classification policies mandate AES-256 for data at rest and specific minimums for asymmetric keys. A weak key is a finding that can block an audit.
  • Signing weakness. For asymmetric keys used to sign artifacts or tokens, a short modulus or weak curve makes forgery more practical, which can lead to supply chain or authentication bypass.
  • Blast radius. Because one key often encrypts many resources, a single weak key can quietly lower the security posture of an entire data domain.

Warning: You cannot change the algorithm of an existing key or key version in place. Cloud KMS treats the algorithm as immutable per version. Fixing a weak key always means creating something new and migrating, so plan for a short data re-encryption window rather than a quick toggle.


How to fix it

The remediation path depends on whether the key is symmetric (encryption) or asymmetric (signing/encryption). The general approach is the same: create a stronger key or key version, point your workloads at it, and re-encrypt existing data.

1. Inspect the offending key

gcloud kms keys describe my-key \
  --location=us-central1 \
  --keyring=my-keyring \
  --format="yaml(name,purpose,versionTemplate)"

The versionTemplate.algorithm tells you what new versions will use, and versionTemplate.protectionLevel shows whether it is SOFTWARE, HSM, or EXTERNAL.

2. Update the version template to a strong algorithm

For symmetric keys, update the template so future versions use Google's default symmetric algorithm, which is AES-256-GCM:

gcloud kms keys update my-key \
  --location=us-central1 \
  --keyring=my-keyring \
  --default-algorithm=google-symmetric-encryption

For an asymmetric encryption key that needs a stronger modulus, the algorithm is fixed per key, so create a new key with the right parameters:

gcloud kms keys create my-key-rsa4096 \
  --location=us-central1 \
  --keyring=my-keyring \
  --purpose=asymmetric-encryption \
  --default-algorithm=rsa-decrypt-oaep-4096-sha512 \
  --protection-level=hsm

For signing keys, prefer a strong curve or a 3072-bit-plus modulus:

gcloud kms keys create my-signing-key \
  --location=us-central1 \
  --keyring=my-keyring \
  --purpose=asymmetric-signing \
  --default-algorithm=ec-sign-p384-sha384 \
  --protection-level=hsm

3. Create a new version and rotate to it (symmetric keys)

gcloud kms keys versions create \
  --location=us-central1 \
  --keyring=my-keyring \
  --key=my-key \
  --primary

Marking the new version as primary makes all new encrypt operations use it. Existing ciphertext still references the old version, so you must re-encrypt.

4. Re-encrypt existing data

Re-encryption is resource-specific. For Cloud Storage objects, rewrite the object so it picks up the new key version:

gcloud storage objects update gs://my-bucket/my-object \
  --encryption-key=projects/PROJECT/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key

Danger: Do not destroy or disable the old key version until you have confirmed every resource has been re-encrypted with the new version. Disabling a version that still protects live ciphertext makes that data permanently undecryptable. Verify first, then schedule destruction with the default 24-hour to 30-day recovery window in place.

5. Disable the weak version once migration is complete

gcloud kms keys versions disable WEAK_VERSION_NUMBER \
  --location=us-central1 \
  --keyring=my-keyring \
  --key=my-key

Tip: Disable before you destroy. A disabled version can be re-enabled instantly if you discover a resource you missed, while a destroyed version is gone for good. Keep the weak version disabled for a full audit cycle before scheduling destruction.


Fixing it with Terraform

If you manage KMS as code, set the algorithm and protection level explicitly so weak defaults never slip through:

resource "google_kms_key_ring" "main" {
  name     = "my-keyring"
  location = "us-central1"
}

resource "google_kms_crypto_key" "encryption" {
  name            = "my-key"
  key_ring        = google_kms_key_ring.main.id
  rotation_period = "7776000s" # 90 days

  version_template {
    algorithm        = "GOOGLE_SYMMETRIC_ENCRYPTION"
    protection_level = "HSM"
  }

  lifecycle {
    prevent_destroy = true
  }
}

resource "google_kms_crypto_key" "signing" {
  name     = "my-signing-key"
  key_ring = google_kms_key_ring.main.id
  purpose  = "ASYMMETRIC_SIGN"

  version_template {
    algorithm        = "EC_SIGN_P384_SHA384"
    protection_level = "HSM"
  }
}

Pinning the algorithm in code means every reviewer sees the crypto parameters in the diff, and drift back to a weak setting becomes a visible change rather than a silent click in the console.


How to prevent it from happening again

Manual review does not scale. Push the standard into the pipeline so weak keys cannot be merged or deployed.

Org Policy constraints

Use the Cloud KMS org policy constraints to restrict which algorithms and protection levels are allowed across the organization:

# Restrict allowed protection levels to HSM and EXTERNAL only
gcloud resource-manager org-policies allow \
  constraints/gcp.restrictCmekCryptoKeyProjects \
  under:organizations/ORG_ID

Pair this with a custom organization policy that enforces approved algorithms, so a developer who tries to create an RSA-2048 key in a regulated folder is blocked at create time.

Policy-as-code in CI

For Terraform, add an OPA or Conftest rule that rejects plans containing weak algorithms:

package kms

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "google_kms_crypto_key"
  algo := resource.change.after.version_template[_].algorithm
  weak := {"RSA_DECRYPT_OAEP_2048_SHA256", "RSA_SIGN_PSS_2048_SHA256"}
  weak[algo]
  msg := sprintf("KMS key %s uses weak algorithm %s", [resource.address, algo])
}

Tip: Run Lensix on a schedule against your live projects in addition to gating at CI. Policy-as-code catches what is in your IaC, but keys created by hand, by another team, or by a managed service will only surface in a runtime scan of the actual environment.


Best practices

  • Standardize on AES-256 for symmetric encryption. Google's default symmetric algorithm meets this, so leave it in place rather than experimenting.
  • Use RSA-3072 or higher, or P-384 curves, for asymmetric keys that protect long-lived data or sign trusted artifacts.
  • Prefer HSM protection level for production keys handling sensitive data. The cost difference is small relative to the assurance gain.
  • Enable automatic rotation on symmetric keys, typically every 90 days, so a single compromised version has a bounded lifetime.
  • Document a key classification scheme. Map data sensitivity tiers to required algorithms and protection levels, then enforce that mapping with org policy.
  • Never reuse one key across unrelated data domains. Separate keys limit blast radius and make rotation and revocation surgical instead of disruptive.
  • Audit key access regularly. Weak algorithms are one half of the problem; overly broad IAM on the key is the other. Review roles/cloudkms.cryptoKeyEncrypterDecrypter bindings alongside this check.

Weak encryption on a KMS key is the kind of finding that looks minor until the day it is not. Set strong defaults in code, enforce them with org policy, and let a continuous scan catch the keys that slip through human hands. The fix is straightforward, and doing it now is far cheaper than re-encrypting an entire data estate under audit pressure later.