Skip to content

Cryptography Reference

Grizzly encrypts asset data with AES-256-GCM and wraps the resulting symmetric keys using RSA-4096 before storing them. Asset metadata integrity is protected through a separate AES-256-GCM signing scheme. This document covers the specific algorithms, key material, IV construction, and binary formats in enough detail to evaluate them, audit them, or present them to a security reviewer.

Algorithms at a Glance

Purpose Algorithm Key Size Notes
Data encryption AES-256-GCM 256-bit 128-bit auth tag
Key wrapping RSA-4096 4096-bit PKCS1 public, PKCS8 private
Asset signing AES-256-GCM 256-bit Binds a SHA-256 content hash
Content hashing SHA-256 Used during asset signing only

AES-256-GCM

All asset data is encrypted using AES-256-GCM with a 32-byte key and a 128-bit authentication tag. GCM provides authenticated encryption, which means the ciphertext carries an integrity check that the decryption process must verify before returning any plaintext. If the authentication tag does not match, decryption fails rather than silently producing corrupted output. The authentication tag (16 bytes) is appended to the end of the ciphertext and stripped during decryption.

IV Construction

Each encryption operation uses a 96-bit (12-byte) nonce composed of two parts: a 72-bit (9-byte) cryptographically random prefix and a 24-bit (3-byte) incrementing counter. The random prefix is generated when a Key is first created. The counter starts at zero and increments with each encrypt call on that Key.

This construction follows NIST SP 800-38D guidance for deterministic IV generation. The 24-bit counter supports up to 16,777,216 unique nonces per prefix before exhaustion, but Key rotation limits the number of operations per Key to a configurable ceiling that sits well below that number in practice.

Key Rotation

Each Key on a KeyRing has a maxEncryptCount setting that controls how many encrypt operations it will serve before the KeyRing automatically rotates to a new Key. The platform default is 50,000 operations. NIST recommends rotating AES-256-GCM keys before 64 GB of data has been encrypted under a single key, so organizations encrypting large payloads should tune maxEncryptCount downward to stay within that boundary.

After a Key rotates, it is never used for new encryption but remains in the system so that previously encrypted data can still be decrypted. The platform tracks which Key was used for each encrypt operation, so decryption always resolves to the correct Key regardless of how many rotations have occurred on the KeyRing.

Key Wrapping: RSA-4096

Every AES-256 key generated by the platform is immediately encrypted using the RSA-4096 public key associated with its KeyRing before it is stored. Grizzly never persists a raw symmetric key. To decrypt any asset, the caller presents the private key, which the platform uses to unwrap the symmetric key and complete the decryption.

Public keys are stored in PEM PKCS1 format. Private keys default to PEM PKCS8 format and can optionally be encrypted at rest using a symmetric cipher and passphrase, which adds a second layer of protection if the key file is exposed. Organizations generating their own key pairs outside of Grizzly's tooling can produce compatible keys with OpenSSL:

openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -out public.pem

Organizations that manage their own RSA key pairs can destroy the private key to render all data encrypted under a given KeyRing permanently unrecoverable, which is useful for time-limited datasets, expired partner contracts, or regulatory data destruction requirements.

Asset Signing

Asset metadata is signed using a dedicated AES-256-GCM signing key that is separate from the data encryption key. When an asset is signed, the platform computes a SHA-256 hash of the serialized asset metadata and encrypts a payload containing that hash into the signature. The signing operation produces three outputs: an encrypted payload, a 12-byte random IV, and a reference identifier for the signing key.

Verification decrypts the payload using the original signing key and IV, then recomputes the SHA-256 hash of the current asset metadata. If the metadata has changed at all since signing, the hashes will not match and verification fails. If the ciphertext itself has been modified, the GCM authentication tag will reject decryption before the hash comparison is even reached.

A valid signature therefore proves two things independently: that the metadata content has not changed since signing (via the SHA-256 hash), and that the signature ciphertext has not been tampered with since it was produced (via the GCM auth tag).

Encrypted Output: The Header

When the platform encrypts data, it prepends a binary header to the ciphertext. The header carries the information needed to look up the correct Key for decryption and can embed the IV, a signed asset, or an asset ID as typed blocks.

Header layout (Version 1):

Field Size Description
Version 1 byte Header version (currently 1)
Length 2 bytes Total header length, max 64 KB
Hash 14 bytes 6 bytes KeyRing ID + 8 bytes Key ID
Blocks variable Zero or more typed data blocks

Each block contains a 1-byte type identifier, a 2-byte length field (max 64 KB of data per block), and the block payload. Three block types are defined:

Type Value Contents
IV 1 The packed nonce (random prefix + counter) used during encryption
Asset 2 The signed asset payload
AssetId 3 The asset identifier string

The 14-byte hash is returned as a standalone value in encrypt responses. Either the full header or the hash can be passed to the decrypt endpoint; the platform uses whichever is provided to resolve the KeyRing and Key, then decrypts accordingly.

Platform Capacity

The hash field in the header allocates 6 bytes to the KeyRing ID and 8 bytes to the Key ID. Those sizes set the theoretical upper bounds on scale:

  • KeyRings: up to 281,474,976,710,656 (2^48), which is roughly 892,551 new KeyRings per minute sustained over 10 years.
  • Keys per KeyRing: up to approximately 1.89 × 10^19 (2^64), which is roughly 974,904,028 new Keys per second sustained over 10 years.

These limits are inherent to the binary format and are not configurable.

Security Properties

AES-256-GCM with a 32-byte key provides 256-bit symmetric security against brute force. The GCM authentication tag detects any modification to ciphertext before decryption produces output, so a successful decryption is proof the data has not been altered in transit or at rest. RSA-4096 key wrapping means raw symmetric keys are never stored in plaintext and can only be recovered by whoever holds the corresponding private key. Each KeyRing uses a separate RSA key pair, so a key pair compromise is bounded to that KeyRing's data and does not affect others. Key rotation limits the volume of data exposed under any single symmetric key, and rotated keys are retained for decryption of existing data but are never reused for new encryption.