← Índice de Demos
FHE em Ação · Encrypted Query
Demo 07 · RWE Pull
Demonstração Factual

O Balcão que Não Lembra.

Pharma global pergunta. Farmácia responde. Sem ninguém ver pacientes individuais.

O Cenário

Pharma quer saber: quantos pacientes diabéticos iniciaram metformina nos últimos 90 dias e abandonaram em 30? A farmácia tem a base; pharma envia query cifrada.

O Problema

O modelo IQVIA atual depende de "anonimização" que cada vez mais é considerada legalmente frágil. FHE oferece garantia matemática.

A Garantia

Pharma decifra apenas a contagem agregada. Nunca vê pacientes individuais. Farmácia nunca vê a query (a query também é cifrada). Tudo verificável.

Passo 01 · Setup

Definir os parâmetros.

Antes de cifrar a base de pacientes, escolhemos os parâmetros BGV. Cada um é um trade-off entre segurança, velocidade e capacidade de cálculo.

Parâmetros · BGV

params := bgv.NewParametersFromLiteral({
  LogN: 13,  // N = 8192
  LogQ: [55,45,45],
  PlaintextModulus: 65537,
})
8 192Slots/ciphertext
EXATOTipo de esquema

O que cada termo significa

BGV (esquema "exato") — Opera sobre números inteiros. Sem ruído de aproximação. Resultado é bit-a-bit idêntico ao plaintext. Ideal para contagens, queries SQL e lógica booleana — exatamente o que esta demo de RWE precisa.

8 192 slots — Cada ciphertext é um vetor de 8 192 valores empacotados. 1 ciphertext cabe 8 192 pacientes simultaneamente. Operação única processa todos. Em produção real, milhões via batching.

Profundidade multiplicativa 2 — Quantas multiplicações encadeadas o ciphertext suporta. A query desta demo precisa de 2 (AND triplo entre 3 flags binárias) → profundidade 2 basta.

~128 bits de segurança — Padrão da indústria. Quebrar a chave exigiria ~2128 operações.

Base RLWE — Ring Learning With Errors. O mesmo problema matemático sobre o qual NIST padronizou criptografia pós-quântica (ML-KEM, ML-DSA).

Passo 02 · Chaves

Pharma cria, farmácia recebe.

Diferente de outros casos, aqui a chave secreta pertence à PHARMA (quem faz a query). A farmácia só recebe a chave pública para poder cifrar dados sob ela. Inversão de papéis comum em RWE pull.

Quem tem o quê

Pharma — gera o par (sk, pk). Mantém sk consigo. Apenas pharma poderá decifrar a resposta final.

Farmácia — recebe pk + rlk + galois keys. Pode cifrar dados e processar queries, mas NÃO PODE decifrar nada (nem mesmo sua própria base depois de cifrada).

~10 msGeração total

Por que essa inversão

Pharma define a pergunta — Em RWE pull, pharma é quem precisa da resposta. Ela escolhe a query, precisa entender o resultado, e decide o que fazer com ele. Faz sentido que ela detenha a chave.

Farmácia perde flexibilidade — Mas ganha proteção: não pode ser obrigada a decifrar a base sob ordem judicial, nem por funcionário desonesto, nem por invasor. Tecnicamente impossível.

Modelo simétrico vs assimétrico — Para cruzamento entre operadora e hospital (caso simétrico), usaríamos threshold com chaves divididas. Para query pharma → farmácia (assimétrico), o modelo "pharma detém a chave" funciona melhor.

Passo 03 · Base

Cifrar a base.

A farmácia cifra UMA VEZ os 3 vetores característicos (diabético, iniciou metformina, abandonou). Qualquer query futura reusa esses ciphertexts.

Base de Pacientes

1 000Pacientes
3Flags por paciente

Distribuição realista: ~30% diabéticos, ~12% iniciaram metformina, ~3% abandonaram em 30d.

Cifragem

9 msCifragem total (3 vetores)
384 KBPor vetor cifrado
Passo 04 · Query

A pharma pergunta.

Pharma define a pergunta de RWE como uma fórmula booleana SQL-like sobre as flags. Sob FHE, a tradução é direta: AND vira multiplicação, contagem vira InnerSum.

A query em SQL tradicional

SELECT count(*)
FROM pacientes
WHERE diabetico = 1
  AND iniciou_metformina = 1
  AND abandonou_30d = 1

Esta é a query que pharma quer executar. Em SQL tradicional, exigiria acesso direto à base da farmácia em claro.

A mesma query sob FHE

// AND triplo = multiplicação
ctAnd := evaluator.Mul(
  ctDiab, ctMet,
)
ctAnd := evaluator.Mul(
  ctAnd, ctAban,
)

// COUNT = InnerSum dos slots
ctCount := evaluator.InnerSum(ctAnd)

Mesma semântica, sintaxe diferente. A multiplicação de ciphertexts binários é exatamente AND lógico. A soma dos slots é exatamente COUNT.

Passo 05 · Computação

Query roda sobre a base cifrada.

A farmácia executa a query inteira sobre os ciphertexts. Cada operação é matemática pura — sem nenhum ponto onde o dado é decifrado. Tempo total: 47 ms.

O que a operação significa

2 multiplicações cifradas — Para um AND triplo entre 3 flags binárias, precisamos encadear 2 multiplicações: ct₁·ct₂, depois (ct₁·ct₂)·ct₃. Cada multiplicação consome 1 nível de profundidade. Por isso configuramos LogQ com 2 níveis multiplicativos no Passo 01.

log₂(N) rotações Galois — Para somar todos os 1 000 slots ativos via InnerSum, são necessárias ~10 rotações em estilo árvore binária. Cada rotação é uma operação Galois cifrada usando as Galois keys do passo 2.

47 ms total — Tempo real medido. Comparado a query SQL tradicional (~ms), é 50× mais lento. Comparado ao tempo de uma reunião de comitê para autorizar acesso a dado clínico em modelo tradicional (semanas), é 10⁹ × mais rápido.

0 bytes decifrados — A farmácia não decifra nada. Não pode. Não tem chave. O resultado fica como ciphertext até chegar à pharma.

O que a farmácia possui agora

2Multiplicações cifradas
~10Rotações Galois
47 msTempo total
0Bytes decifrados

Um único ciphertext: ct_resposta. Codifica a contagem. A farmácia também não pode decifrar — só a pharma tem a chave secreta.

Passo 06 · Resposta

Pharma decifra.

A pharma recebe ct_resposta. Decifra com sua chave secreta. Descobre apenas a contagem.

Resposta da query
33
pacientes diabéticos que iniciaram metformina e abandonaram em 30 dias
Passo 07 · Prova

Validação matemática.

BGV é esquema exato — sem ruído de aproximação como CKKS.

FHE vs Plaintext

MétricaFHEPlaintext
Contagem3333
DiferençaEXATA — 0 erro

Por que é Exato

BGV opera sobre inteiros módulo um primo (65537). Para contagens dentro do domínio, o resultado FHE é bit-a-bit idêntico ao plaintext.

Passo 08 · Adversarial

Pharma desonesta.

O que pharma pode tentar para inferir indivíduos da contagem agregada?

Ataques

  • 1 — Inferir indivíduo da contagemUma única contagem não é injetiva. Para isolar um indivíduo, pharma precisaria fazer queries específicas — bloqueado por política de mínimos por query (ex: nunca reportar contagem < 10).
  • 2 — Ler bytes cifradosPseudoaleatórios. Nada recuperável.
  • 3 — Brute force2^3000 combinações de flags. Inviável.

Defesa em camadas

Privacidade diferencial pode ser adicionada à contagem (ruído gaussiano calibrado), garantindo que mesmo com queries adaptativas pharma não consegue isolar indivíduo.

Passo 09 · Síntese

O que aconteceu.

Em menos de 100 ms, pharma obteve um insight regulatório-grade sem nunca ver pacientes individuais.

O Fluxo

  1. Farmácia cifrou sua base de 1000 pacientes uma única vez
  2. Pharma definiu uma query SQL-like sobre 3 flags
  3. Farmácia executou a query inteira sob cifra
  4. Pharma decifrou apenas a contagem agregada

Números Reais

9 msCifragem da base
47 msQuery
384 KBPor ciphertext
EXATAPrecisão
4 eBooks usam esta primitivaFarmácias, Labs, Farma e Bancos (M&A due diligence).
Simplificação didática · janelas temporaisEsta demo usa flags binárias simples. Queries reais de RWE incluem janelas temporais: "nos últimos 90 dias", "em pacientes ≥ 65 anos", "após evento X". Janelas temporais exigem codificação adicional: cada data vira vetor binário de "mês/ano" e a query usa AND/OR entre vetores. A primitiva FHE permanece idêntica; só a representação de entrada fica mais rica. Para contagens exatas BGV é o esquema correto; para agregações estatísticas com janelas CKKS é mais eficiente.