> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Encryption Keys

> Manage encryption keys

# Overview

Encryption keys let you encrypt sensitive fields in logs and sessions before they reach Formal's servers. You decrypt them on demand from your browser.

Encrypted fields are stored as JWE (JSON Web Encryption) instead of plaintext. Refer to the [log configuration documentation](/docs/guides/core-concepts/connectors/logs#logs-configuration) to learn which fields can be encrypted.

# Configuration via Terraform

Encryption keys are managed through the `formal_encryption_key` resource. AWS KMS and GCP KMS are supported, both using an asymmetric RSA key. The encrypting client (Connector or Desktop App) holds only the public key and needs no cloud credentials, so only the decryptor can recover the plaintext.

<Tabs>
  <Tab title="AWS KMS">
    ```hcl theme={null}
    provider "aws" {
      region = "us-east-1"
    }

    resource "aws_kms_key" "formal_logs_key" {
      description              = "Asymmetric key for Formal log encryption"
      customer_master_key_spec = "RSA_4096"
      key_usage                = "ENCRYPT_DECRYPT"
    }

    data "aws_kms_public_key" "formal_logs_key" {
      key_id = aws_kms_key.formal_logs_key.id
    }

    resource "formal_encryption_key" "logs_key" {
      key_provider   = "aws-kms"
      key_id         = aws_kms_key.formal_logs_key.arn
      public_key_pem = data.aws_kms_public_key.formal_logs_key.public_key_pem
      # Optional: an HTTPS endpoint the browser calls to decrypt individual fields.
      # decryptor_uri = "<HTTPS endpoint to perform decryption>"
    }
    ```

    The region is derived from the key ARN, so pass the full ARN in `key_id`.
  </Tab>

  <Tab title="GCP KMS">
    ```hcl theme={null}
    provider "google" {
      project = "my-project"
    }

    resource "google_kms_key_ring" "formal" {
      name     = "formal-logs"
      location = "us-east1"
    }

    resource "google_kms_crypto_key" "formal_logs_key" {
      name     = "formal-logs-key"
      key_ring = google_kms_key_ring.formal.id
      purpose  = "ASYMMETRIC_DECRYPT"

      version_template {
        algorithm = "RSA_DECRYPT_OAEP_4096_SHA256"
      }
    }

    data "google_kms_crypto_key_version" "formal_logs_key" {
      crypto_key = google_kms_crypto_key.formal_logs_key.id
    }

    resource "formal_encryption_key" "logs_key" {
      key_provider   = "gcp-kms"
      key_id         = data.google_kms_crypto_key_version.formal_logs_key.name
      public_key_pem = data.google_kms_crypto_key_version.formal_logs_key.public_key[0].pem
      # Optional: an HTTPS endpoint the browser calls to decrypt individual fields.
      # decryptor_uri = "<HTTPS endpoint to perform decryption>"
    }
    ```

    For GCP, pass the crypto key version resource name (`projects/.../cryptoKeyVersions/N`) in `key_id`.
  </Tab>
</Tabs>

<Note>
  Symmetric and deterministic algorithms (`aes_random`, `aes_deterministic`) are deprecated and can no longer be registered. Encryption keys use asymmetric RSA (`rsaes_oaep_sha256`), which both the Connector and Desktop App can use without cloud credentials.
</Note>

# The Decryptor

Formal cannot decrypt these fields. When you set a `decryptor_uri`, the client-side JavaScript of the Formal Console calls it when a user decrypts a field. The endpoint must support CORS and accept POST requests with the encrypted payload in the body. Use [this decryptor reference implementation](https://github.com/formalco/decryptor).

<Warning>
  There is no authentication mechanism between the Formal Console and the decryptor. Deploy it behind a VPN or in a private network to restrict access.
</Warning>
