Skybridge engineering

Encrypting customer AI keys with AES-256-GCM: design questions beyond the cipher

A technical guide to authenticated encryption, key separation, nonce safety, migration, rotation and runtime access for BYOK secrets.

The cipher sits inside a key lifecycle
01EncryptFresh nonce and authenticated data
02OperateScoped runtime decryption
03RotateVersioned migration and recovery

AES-256-GCM can protect an AI API key at rest and detect ciphertext tampering. The cipher choice does not settle where the encryption key lives, how nonces remain unique, which process can decrypt, how old records migrate or how keys rotate without downtime.

The complete design is a small key-management system. Treat the storage format, runtime boundary, migration and evidence as parts of the security control.

Use authenticated encryption for the stored value

Galois/Counter Mode combines encryption with an authentication tag. During decryption, the application verifies that the ciphertext and any associated data have not been altered. NIST specifies GCM in Special Publication 800-38D.

For each stored secret, keep a version, nonce or initialization vector, authentication tag and ciphertext. A textual envelope can look like:

enc:v1:<nonce>:<tag>:<ciphertext>

The prefix is not decoration. It lets the reader choose the correct parser and key policy. A future format can use v2 without guessing from byte length.

Make nonce uniqueness a system invariant

GCM security depends on avoiding reuse of the same key and nonce pair. Generate a fresh 96-bit nonce for every encryption operation using a cryptographically secure random generator. Never derive it from a tenant ID, timestamp or row counter unless the complete construction has been reviewed for uniqueness across processes and restores.

Store the nonce beside the ciphertext; it does not need to be secret. Rotation and migration code must generate a new nonce whenever it re-encrypts a value.

Test this behavior statistically during development and structurally in code review. The most valuable review question is whether any call site can accept a caller-supplied or reused nonce.

Keep the data key away from the database

Application-level encryption protects against a database dump only when the decryption key is stored in another control plane. Do not place it in the same table, migration or backup as the encrypted API keys.

A straightforward deployment uses a 32-byte key supplied through the runtime's secret manager. Stronger deployments can use envelope encryption: a data-encryption key protects values, while a cloud key-management service protects that data key and controls decrypt operations.

The process that needs to call the AI provider may decrypt in memory. Browser clients, analytics jobs and list endpoints should receive only a status such as hasKey, never plaintext or ciphertext that encourages accidental handling.

Bind context with associated data

GCM can authenticate additional data without encrypting it. Associated authenticated data can bind a ciphertext to its record purpose, tenant and key version. A copied ciphertext will then fail authentication if placed in a different context.

The associated fields must be stable. If an agent identifier can change, using it directly may make a legitimate rename break decryption. Choose immutable identifiers and a documented serialization format.

Design failure behavior before migration

An encrypted value can fail to decrypt because the key is wrong, the envelope is corrupted or the version is unsupported. The application must not include the key, ciphertext or detailed cryptographic internals in the error.

List endpoints should remain available without exposing the secret. An action that requires the key should fail closed with a reason an operator can investigate. Alerting should distinguish missing key material from one corrupt row.

Skybridge's encryption module uses a versioned AES-256-GCM envelope with a fresh nonce per value. Server-side row helpers decrypt only on paths that require the key, while public application responses expose key presence. Deployment acceptance verifies that encryption material exists before claiming the storage path is active.

Migrate plaintext without a flag day

Legacy records need an explicit migration path. One practical sequence is:

  1. ship a reader that accepts legacy plaintext and the new envelope;
  2. encrypt every new or updated value;
  3. run an idempotent migration against development;
  4. verify record counts and decryptability without printing values;
  5. migrate production through a controlled release; and
  6. remove plaintext compatibility after the accepted transition period.

The migration should skip already encrypted records and support safe restart. Record counts by state are useful; logging values is forbidden.

A degraded mode that silently writes plaintext creates false assurance. If temporary compatibility is unavoidable, emit an operator-visible failure state and block production acceptance until key material and migration are verified.

Plan rotation into version one

Rotation needs both a key identifier and a re-encryption process. Keep the old decryption key available while rows move to the new version. New writes use the active key immediately; reads identify the version and can optionally re-encrypt after successful decryption.

Rotation should support four events: scheduled change, suspected key exposure, cryptographic-policy change and infrastructure migration. Test rollback while both key versions exist. A backup restored after rotation must still have an authorized path to its historical key or a documented reason it cannot be decrypted.

Audit key operations without recording keys

Record who set, replaced or cleared a provider key, which workspace or agent was affected and when the operation occurred. Record encryption version and migration outcome. Never log request bodies, secret prefixes or partial keys as identifiers.

Monitor failed decryptions, missing runtime key material and unexpected legacy values. These are control-health signals, not ordinary user errors.

Test the whole secret lifecycle

The acceptance suite should cover round-trip encryption, different ciphertext for identical plaintext, tamper detection, wrong-key failure, unsupported version, legacy migration, rotation, missing-key startup and secret-free error output.

Then inspect the application boundary. Confirm that list APIs, browser payloads, traces and backups do not reveal the key. Cryptography protects the database value; system design protects every place the value could otherwise escape.

Use the production-incapable development environment guide to separate secret material across environments and the architecture runtime audit to keep the key path documented.

Continue reading: What a production-incapable development environment really means.