Overview
Pixop encrypts sensitive application data at rest to protect it from unauthorized access to the underlying database. Encryption is applied at the application layer and ensures that sensitive values are stored only in encrypted form while remaining transparently usable by the application at runtime.
The encryption system provides confidentiality and cryptographic integrity of encrypted values using modern, industry-standard cryptographic primitives.
Technologies Used
AES (Advanced Encryption Standard)
- Symmetric encryption algorithm
- Operated in GCM (Galois/Counter Mode) for authenticated encryption
- Key size: 256 bits
- Provides confidentiality and authenticity of encrypted values
Argon2
- Memory-hard key derivation function
- Used to derive encryption keys from a master secret
- Configuration:
- Memory: 64 MB
- Parallelism: 2 threads
- Iterations: 4
- Provides resistance against brute-force and GPU-based attacks
HMAC-SHA512
- Used as a pseudorandom function (PRF) for deriving context-specific salts
- Ensures strong key separation between different encryption contexts
SecureRandom
- Generates cryptographically secure random initialization vectors (IVs)
Base64 Encoding
- Encodes encrypted binary data for safe storage in string-based database fields
Key Concepts
Encryption Contexts
Each encrypted value belongs to an encryption context (e.g. user data, job parameters, integration data).
A unique encryption key is derived per context, ensuring that compromise of one context does not affect others.
Key Generation
Encryption keys are derived using the following process:
- A master secret is combined with a context-specific salt
- The salt is derived using HMAC-SHA512
- Argon2 derives a 256-bit AES key from the master secret and salt
This design ensures:
- Strong separation between encryption contexts
- No direct reuse of encryption keys
- Safe long-term storage of encrypted data
Encryption
- AES-GCM encrypts plaintext using:
- A derived context-specific key
- A randomly generated IV (nonce)
- Additional authenticated data (AAD)
- AES-GCM produces authenticated ciphertext that includes an authentication tag
Encrypted Value Format
Encrypted values are stored as:
<key-version>:Base64( IV || Ciphertext || AuthenticationTag )
Example:
1-2025-12-01:QkFTRTY0RU5DT0RFRF9EQVRB
Where:
- key-version identifies which encryption key must be used for decryption
- IV length: 12 bytes
- Authentication tag length: 16 bytes
- Ciphertext length: variable
The key version prefix allows multiple encryption keys to coexist during key rotation and ensures that data encrypted with historical keys remains decryptable.
Decryption
- The key version prefix is parsed to determine which encryption key to use
- Decryption uses the derived key and IV
- AES-GCM verifies the authentication tag during decryption
- Any modification of encrypted data results in decryption failure
Persistence Integration
Encryption and decryption are integrated into the persistence layer using JPA entity lifecycle callbacks:
- Encryption occurs before data is written to the database
- Decryption occurs after data is loaded from the database
As a result:
- Encrypted values are never stored in plaintext
- Application code operates on decrypted values transparently
Configuration
The encryption system requires two master secrets:
Master Secret Salt
- Base64-encoded
- Used as input to HMAC-SHA512
- Length: 64 bytes
Master Secret for Argon2
- Base64-encoded
- Used as the primary secret for key derivation
- Length: at least 64 bytes
Both secrets are stored securely in AWS Secrets Manager.
Key Rotation and Re-Encryption
General Principles
Master secrets are regularly rotated and long-lived data re-encrypted.
Rotating encryption secrets does not automatically re-encrypt existing data.
Because encryption is applied during persistence operations, encrypted values must be explicitly re-written in order to be re-encrypted using newly derived keys.
Old master secrets must remain available until all required data has been migrated.
Long-Lived Sensitive Data
Certain data is considered long-lived and security-critical and is actively re-encrypted during key rotation.
Examples include:
- Cloud provider access credentials
- Secrets used for signing webhooks
During rotation:
- Existing records are loaded
- Encrypted fields are decrypted using the key identified by their key version
- Values are re-encrypted using newly derived keys
- Updated values are persisted back to the database
Short-Lived and Operational Data
Some encrypted data is considered operational or short-lived, such as:
- Transient job parameters
- Historical execution metadata
This data is not explicitly re-encrypted during key rotation.
Rationale:
- The data is expected to be short-lived or of limited operational value
- Re-encrypting large volumes of historical metadata adds operational complexity
- Such records are subject to periodic cleanup and eventual deletion
Until deletion occurs, this data may remain encrypted using historical keys.
Those keys are retained according to the system’s key retention policy.
Security Guarantees and Limitations
Guarantees
- Sensitive values are stored only in encrypted form at rest
- AES-GCM provides confidentiality and cryptographic integrity
- Context-specific keys limit the blast radius of key compromise
- Key versioning enables safe coexistence of multiple encryption keys
Non-Goals
This encryption system does not protect against:
- Compromise of the running application
- Malicious administrators with legitimate access
- Unauthorized use of valid application credentials
Summary
The Pixop encryption system provides robust, modern encryption for sensitive data at rest, with explicit handling of key rotation and re-encryption based on data sensitivity and lifecycle.
Encryption contexts, explicit key versioning, and controlled re-encryption ensure that long-lived secrets are migrated during rotation while operational data can be retired naturally through cleanup processes.
