Column-Level AES-256-GCM Encryption & Blind Indexing
The GERCIA Platform enforces field-level cryptographic protection for sensitive personal identifiable information (PII) and protected health information (PHI). Even in the event of an adversary obtaining raw physical access to PostgreSQL data files (/data/db), storage snapshots, or database dumps, sensitive health and identity records remain computationally unreadable.
1. Regulatory Compliance & Threat Model
Section titled “1. Regulatory Compliance & Threat Model”Brazilian regulatory frameworks mandate strict defense-in-depth measures for patient health data:
- LGPD (Lei 13.709/2018, Art. 46): Requires security, technical, and administrative measures capable of safeguarding personal data from unauthorized access or accidental/unlawful destruction.
- CFM Resolution 1.821/2007 (Electronic Health Records): Mandates cryptographic integrity and confidentiality for medical history, clinical diagnoses, and electronic prescriptions.
Protected Attributes:
Section titled “Protected Attributes:”- Civil Tax Identifiers: Patient CPF, guardian CPF, prescriber CPF, employee CPF.
- Health Card Identifiers: Cartão Nacional de Saúde (CNS) 15-digit identifiers.
- Sensitive Medical History: Document attachments, clinical notes, patient allergies, and prescription dosages.
2. Cryptographic Architecture: AES-256-GCM
Section titled “2. Cryptographic Architecture: AES-256-GCM”Data is encrypted using AES-256-GCM (Advanced Encryption Standard in Galois/Counter Mode), an authenticated encryption with associated data (AEAD) algorithm:
flowchart LR
subgraph ENCRYPT ["Encryption Pipeline (C# -> PostgreSQL)"]
PLAINTEXT["Plaintext Value<br>(e.g. '123.456.789-00')"]
NONCE["Cryptographic Nonce<br>(96-bit Unique IV)"]
KEY["Tenant AES-256 Key<br>(HKDF Derived)"]
AAD["Associated Data<br>(TenantId + EntityId)"]
PLAINTEXT & NONCE & KEY & AAD --> GCM["AES-256-GCM Engine"]
GCM --> CIPHER["Base64 Payload:<br>[Nonce (12B) | Tag (16B) | Ciphertext]"]
end
Cryptographic Parameters:
Section titled “Cryptographic Parameters:”- Cipher Algorithm:
AES-256-GCM(System.Security.Cryptography.AesGcm). - Key Length: 256 bits (32 bytes).
- Nonce / IV: 96 bits (12 bytes), cryptographically random per encryption operation via
RandomNumberGenerator.GetBytes(12). Nonces are never reused under the same key. - Authentication Tag: 128 bits (16 bytes). Verifies ciphertext integrity before decryption; any bit tampering results in an immediate cryptographic exception.
- Associated Data (AAD):
TenantIdconcatenated withEntityIdis bound into the authentication tag calculation, preventing cross-tenant or cross-entity ciphertext relocation attacks.
3. Tenant-Isolated Key Derivation (HKDF)
Section titled “3. Tenant-Isolated Key Derivation (HKDF)”GERCIA avoids a single global database encryption key. A breach of one tenant’s derived key cannot compromise any other tenant’s data.
Keys are derived using HKDF (HMAC-based Key Derivation Function, RFC 5869) via SHA-256:
TenantKey = HKDF-Expand(PRK = MasterKey, Info = TenantId, Length = 32)flowchart TD
GSM["Google Secret Manager<br>(GERCIA_APP_ENCRYPTION_KEY)"] --> HKDF["HKDF-SHA256 Derivation Engine"]
TENANT["Current TenantId (UUIDv7)"] --> HKDF
HKDF --> DERIVED["Unique 256-Bit Tenant Key<br>(Cached in Memory / 15-Min TTL)"]
- Root Key Custody: The master key is stored in Google Secret Manager (
GERCIA_APP_ENCRYPTION_KEY) and loaded into host memory at container bootstrap. - Deterministic Isolation: Each tenant has an isolated cryptographic domain derived mathematically from the master secret and the tenant’s immutable
TenantId.
4. EF Core Transparent Value Converter ([Encrypted])
Section titled “4. EF Core Transparent Value Converter ([Encrypted])”Developers annotate sensitive domain entity properties with the [Encrypted] attribute:
public class Patient : AggregateRoot, IMustHaveTenant{ [Encrypted] public string Cpf { get; private set; } = string.Empty;
[Encrypted] public string CnsNumber { get; private set; } = string.Empty;}During EF Core model initialization (OnModelCreating), an entity configuration convention discovers all [Encrypted] properties and registers an AesGcmValueConverter:
- On Persist (
SaveChanges): Plaintext is serialized to UTF-8, encrypted via AES-256-GCM with the active tenant key, and written to PostgreSQL as Base64 text. - On Materialize (
Query): Base64 payload is unpacked, authenticated, decrypted in memory, and populated onto the C# domain entity.
5. Searchable Encryption: Blind Indexing Pattern
Section titled “5. Searchable Encryption: Blind Indexing Pattern”Because AES-256-GCM produces randomized ciphertext for the same plaintext (due to unique 96-bit nonces), standard SQL equality lookups (WHERE cpf = @input) cannot query the encrypted column directly.
GERCIA implements the Blind Index Pattern to enable high-speed indexed equality searches without exposing plaintext:
flowchart TD
INPUT["Input Search Parameter<br>(e.g. CPF: '12345678900')"] --> NORM["Normalize String<br>(Strip punctuation & whitespace)"]
NORM --> HMAC["HMAC-SHA256 Engine"]
SALT["Blind Index Salt<br>(Secret from GSM)"] --> HMAC
HMAC --> HASH["Deterministic Blind Index Hash<br>(64-character hex string)"]
HASH --> QUERY["SQL Query:<br>SELECT * FROM clinical.patients<br>WHERE cpf_hash = @hash"]
QUERY --> BTREE["PostgreSQL B-Tree Index<br>(idx_patients_cpf_hash)"]
Table Schema Implementation:
Section titled “Table Schema Implementation:”CREATE TABLE clinical.patients ( id uuid NOT NULL, tenant_id uuid NOT NULL, cpf text NOT NULL, -- AES-256-GCM encrypted ciphertext cpf_hash varchar(64) NOT NULL, -- HMAC-SHA256 deterministic blind index full_name varchar(255) NOT NULL, CONSTRAINT pk_patients PRIMARY KEY (id));
-- Fast B-Tree index on the blind hash scoped to the tenantCREATE INDEX idx_patients_tenant_cpf_hash ON clinical.patients (tenant_id, cpf_hash);Security Properties of Blind Indexing:
Section titled “Security Properties of Blind Indexing:”- One-Way Trapdoor: The blind index cannot be reversed to discover the patient’s CPF.
- Frequency Attack Resistance: The HMAC uses a distinct secret salt stored in Google Secret Manager (
BLIND_INDEX_SALT), preventing rainbow table matching. - High Performance: Queries execute standard index seeks in
O(log N)time with zero decryption overhead inside PostgreSQL.