Tema
EVD-CRYPTO-DATA — Evidencia de Cifrado y Protección de Datos
| Campo | Valor |
|---|---|
| ID | EVD-CRYPTO-DATA |
| Versión | 1.0 |
| Fecha | 2026-04-03 |
| Clasificación | Interno — Confidencial |
| Propietario | CISO / Equipo de Desarrollo |
| Política de referencia | POL-004 Estándares de Cifrado |
| PCI DSS v4.0 | Requisitos 3, 4 |
| Preguntas ControlCase | Q26, Q29, Q1034 |
Q26 — Descubrimiento de Datos de Tarjeta (PAN, Track, CVV, PIN)
Alcance del CDE
Solo dos microservicios dentro del Cardholder Data Environment (CDE) tienen contacto con PANs:
| Servicio | Función | Subnet | Node Pool |
|---|---|---|---|
card-vault-service (puerto 3003) | Cifrado/descifrado de PANs mediante envelope encryption AES-256-GCM | 10.100.10.0/24 (CDE) | cde-pool (Taint pci-scope=true) |
tokenization-service (puerto 3002) | Recibe PAN, genera token irreversible, almacena dato cifrado en vault | 10.100.10.0/24 (CDE) | cde-pool (Taint pci-scope=true) |
Ningun otro servicio del monorepo (payments-api, orchestration-service, email-service, etc.) recibe, almacena ni procesa PANs. Estos servicios trabajan exclusivamente con tokens (tok_pan_*).
Cifrado en Reposo
Tokenization Service — AES-256-GCM directo
El servicio cifra el dato sensible antes de almacenarlo en la tabla payments_vault.tokenized_data:
typescript
// backend/apps/tokenization-service/src/tokenization.service.ts
private encrypt(data: string): { encrypted: string; iv: string; authTag: string } {
const iv = crypto.randomBytes(12); // 96-bit IV
const cipher = crypto.createCipheriv('aes-256-gcm', this.encryptionKey, iv);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return { encrypted, iv: iv.toString('hex'), authTag: authTag.toString('hex') };
}- Algoritmo: AES-256-GCM (cifrado autenticado)
- IV: 12 bytes aleatorios por registro (CSPRNG
crypto.randomBytes) - Auth Tag: 16 bytes (integridad garantizada)
- Clave: 32 bytes desde
VAULT_ENCRYPTION_KEYviaConfigService
Card Vault Service — Envelope Encryption (DEK + KEK)
El vault implementa un esquema de envelope encryption donde cada registro tiene su propia DEK:
typescript
// backend/apps/card-vault-service/src/crypto/envelope/envelope-crypto.service.ts
async encrypt(plaintext: string): Promise<EncryptedEnvelope> {
const dek = randomBytes(32); // DEK unica por registro
const iv = randomBytes(12); // IV unico por registro
const cipher = createCipheriv('aes-256-gcm', dek, iv);
// ...encrypt...
const wrapped = await this.kek.wrapDek(dek); // KEK wraps DEK
return { ciphertextB64: payload, dekCiphertextB64: wrapped.dekCiphertextB64, kekKeyId: wrapped.kekKeyId };
}Esquema de Base de Datos
sql
-- payments_vault.tokenized_data
CREATE TABLE payments_vault.tokenized_data (
token VARCHAR(100) PRIMARY KEY,
encrypted_data BYTEA NOT NULL, -- PAN cifrado AES-256-GCM
hmac_hash BYTEA NOT NULL, -- HMAC-SHA256 de integridad
data_type VARCHAR(50) NOT NULL,
merchant_id UUID NOT NULL,
key_version INTEGER DEFAULT 1, -- Versionado de claves
created_at TIMESTAMPTZ DEFAULT NOW(),
expires_at TIMESTAMPTZ
);
-- RLS: acceso solo por merchant autenticado
ALTER TABLE payments_vault.tokenized_data ENABLE ROW LEVEL SECURITY;
CREATE POLICY vault_access_policy ON payments_vault.tokenized_data
FOR ALL TO vault_user
USING (merchant_id::text = current_setting('app.current_merchant_id', true));Redaccion Automatica de PAN en Logs (@fintrix/logging)
El paquete @fintrix/logging implementa masking automatico a nivel de string y objeto:
Patrones de redaccion (regex):
| Dato | Patron | Reemplazo |
|---|---|---|
| PAN | /\b\d{13,19}\b/g | [REDACTED-PAN] |
| Password | /password["\s:=]+... | password=[REDACTED] |
| Authorization | /authorization["\s:=]+... | authorization=[REDACTED] |
| API Key | /api[_-]?key["\s:=]+... | api_key=[REDACTED] |
| Token | /token["\s:=]+... | token=[REDACTED] |
Claves sensibles redactadas en objetos:
password, token, secret, apiKey, api_key, authorization, pan, cardNumber, card_number, cvv, cvc, ssn, socialSecurityNumber
typescript
// backend/packages/logging/src/logger.service.ts
private redactSensitiveData(value: string): string {
let redacted = value;
redacted = redacted.replace(SENSITIVE_PATTERNS.PAN, '[REDACTED-PAN]');
redacted = redacted.replace(SENSITIVE_PATTERNS.PASSWORD, 'password=[REDACTED]');
redacted = redacted.replace(SENSITIVE_PATTERNS.AUTH_HEADER, 'authorization=[REDACTED]');
redacted = redacted.replace(SENSITIVE_PATTERNS.API_KEY, 'api_key=[REDACTED]');
redacted = redacted.replace(SENSITIVE_PATTERNS.TOKEN, 'token=[REDACTED]');
return redacted;
}Resultado: ningun PAN, CVV, password o clave de API aparece en texto claro en los logs de la aplicacion.
Datos Sensibles de Autenticacion (SAD)
| Dato SAD | Estado | Evidencia |
|---|---|---|
| CVV/CVC | No almacenado. DTOs validan y rechazan almacenamiento post-autorizacion | tokenization-service procesa solo para transmision inmediata al procesador |
| Track completo (Track 1/2) | No procesado ni almacenado | No existe campo en ningun DTO ni tabla de base de datos |
| PIN / PIN block | No procesado ni almacenado | Fintrixs no procesa transacciones con PIN |
| PAN completo en logs | Redactado automaticamente | @fintrix/logging aplica SENSITIVE_PATTERNS.PAN a toda salida |
Escaneo de Descubrimiento de Datos de Tarjeta
| Aspecto | Estado |
|---|---|
| Herramienta | ControlCase Card Data Discovery Tool (CDAT) |
| Ticket | #684997 — pendiente de ejecucion por QSA |
| Alcance del escaneo | Bases de datos (vault_db, payments_db, auth_db), logs almacenados, backups, archivos temporales |
| Frecuencia objetivo | Trimestral |
| Escaneo interno previo | Scripts personalizados (grep -rP '\b\d{13,19}\b') ejecutados sobre logs y codigo fuente — sin hallazgos de PAN en claro |
Referencias
- Flujo de tokenizacion: TOKENIZATION_FLOW
- Politica de cifrado: POL-004
- Definicion de scope: Scope Definition
Q29 — Cifrado de Datos en Transito
Inventario de Conexiones TLS
Protocolos y Cipher Suites por Conexion
| Conexion | Protocolo | Version Min | Cipher Suites | Certificado |
|---|---|---|---|---|
| Cliente → LB (publico) | TLS | 1.3 | TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256 | Let's Encrypt DV (auto-renovacion 60 dias via cert-manager) |
| LB → Kong Gateway | TLS | 1.2 | TLS_AES_256_GCM_SHA384 | CA interna K8s |
| Kong → Microservicios CDE | mTLS | 1.2 | TLS_AES_256_GCM_SHA384 | CA interna K8s (cert-manager) |
| Servicios → PostgreSQL | TLS | 1.2 | TLS_AES_256_GCM_SHA384 | DigitalOcean Managed CA |
| Servicios → Kafka | TLS + SASL_SSL | 1.2 | TLS_AES_256_GCM_SHA384 | Confluent Cloud CA |
| VPN administrativa | WireGuard (Noise) | IKpsk2 | ChaCha20-Poly1305, BLAKE2s | Pre-shared keys |
PostgreSQL — Conexion TLS Obligatoria
Todas las conexiones a PostgreSQL usan sslmode=require:
postgresql://<user>:<pass>@<host>:25060/<db>?sslmode=requireDigitalOcean Managed PostgreSQL fuerza TLS en todas las conexiones y no permite conexiones sin cifrar.
Kafka — TLS + SASL
yaml
# Configuracion Kafka en cada servicio (via @fintrix/event-bus)
security.protocol: SASL_SSL
sasl.mechanism: PLAIN # Confluent Cloud
ssl.enabled.protocols: TLSv1.2,TLSv1.3Kong Gateway — HTTPS Enforced
Kong API Gateway esta configurado para:
- Rechazar tráfico HTTP (solo HTTPS en puerto 443)
- Aplicar mTLS para comunicacion interna al CDE
- Validar cadena de certificados completa
Referencia: backend/infra/kong/kong.yaml
Inventario de Certificados TLS
| Dominio/Servicio | Emisor | Tipo | Vigencia | Auto-renovacion |
|---|---|---|---|---|
*.fintrixs.com | Let's Encrypt | DV | 90 dias (renovacion cada 60) | cert-manager |
| mTLS interno (Kong ↔ CDE) | CA interna K8s | Interno | 1 ano | cert-manager |
| Managed PostgreSQL | DigitalOcean CA | Managed | Gestionado por DO | Si |
| Kafka (Confluent Cloud) | Confluent CA | Managed | Gestionado por Confluent | Si |
Protocolos Prohibidos
| Protocolo | Razon de Prohibicion |
|---|---|
| SSL 2.0, 3.0 | Vulnerabilidades POODLE, BEAST |
| TLS 1.0 | Deprecated por NIST SP 800-52 Rev 2 |
| TLS 1.1 | Deprecated por NIST SP 800-52 Rev 2 |
| RC4 | Bias estadistico conocido |
Ejemplo de Verificacion de TLS en Transito
bash
# Verificar cipher suite del endpoint publico
$ openssl s_client -connect api.fintrixs.com:443 -tls1_3 2>/dev/null | grep -E 'Protocol|Cipher'
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
# Verificar que TLS 1.0 esta rechazado
$ openssl s_client -connect api.fintrixs.com:443 -tls1 2>&1 | grep -i error
error: ... handshake failureQ1034 — Gestion de Cipher Suites Criptograficas
Inventario Completo de Cifrados en Uso
Cifrado en Transito
| Contexto | Protocolo | Cipher Suites Aceptadas |
|---|---|---|
| Trafico publico (API) | TLS 1.3 | TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256 |
| Trafico publico (fallback) | TLS 1.2 | ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES128-GCM-SHA256 |
| Comunicacion interna CDE | mTLS 1.2+ | TLS_AES_256_GCM_SHA384 |
| PostgreSQL | TLS 1.2+ | TLS_AES_256_GCM_SHA384 |
| Kafka | SASL_SSL TLS 1.2+ | TLS_AES_256_GCM_SHA384 |
Cifrado en Reposo
| Dato | Algoritmo | Key Size | Modo | Ubicacion |
|---|---|---|---|---|
| PAN (tokenization-service) | AES | 256 bits | GCM (autenticado) | payments_vault.tokenized_data |
| PAN (card-vault-service) | AES | 256 bits | GCM (envelope: DEK + KEK) | vault_db.encrypted_cards |
| Integridad de PAN | HMAC | 256 bits | SHA-256 | Columna hmac_hash |
| PAN fingerprint | HMAC | 256 bits | SHA-256 | Columna panFingerprint |
| Disco de PostgreSQL (DO) | AES | 256 bits | XTS | Gestionado por DigitalOcean |
| Backups de DB | AES | 256 bits | CBC | DigitalOcean Spaces cifrado |
Firmas Digitales y Hashing
| Uso | Algoritmo | Key Size | Implementacion |
|---|---|---|---|
| JWT Tokens (auth-service) | RSA | 2048 bits | RS256 via @nestjs/jwt |
| Webhook signatures | HMAC | 256 bits | SHA-256 |
| Password hashing | bcrypt | cost factor 12 | bcryptjs |
| Certificados TLS | RSA / ECDSA | 2048 / 256 bits | Let's Encrypt, CA interna |
Algoritmos y Protocolos Prohibidos
| Algoritmo/Protocolo | Razon | Referencia |
|---|---|---|
| SSL 2.0, 3.0 | POODLE, BEAST | NIST SP 800-52 Rev 2 |
| TLS 1.0, 1.1 | Deprecated | NIST SP 800-52 Rev 2 |
| DES, 3DES | Key size insuficiente | NIST SP 800-131A |
| RC4 | Bias estadistico conocido | RFC 7465 |
| MD5 | Colisiones demostradas | NIST |
| SHA-1 | Colisiones demostradas (SHAttered) | NIST |
| RSA < 2048 bits | Key size insuficiente | NIST SP 800-57 |
| CBC sin HMAC | Vulnerable a padding oracle | PCI DSS v4.0 |
Ciclo de Vida de Claves Criptograficas
Calendario de Rotacion de Claves
| Tipo de Clave | Frecuencia | Metodo | Responsable |
|---|---|---|---|
| Master Encryption Key (KEK) | Anual | Manual con dual control | CISO + DevOps Lead |
| Data Encryption Keys (DEK) | Por registro (card-vault) | Automatico (CSPRNG) | Sistema |
| VAULT_ENCRYPTION_KEY | Trimestral | Rotacion manual con re-cifrado | DevOps |
| HMAC Keys | Mensual | CronJob automatizado | Sistema |
| JWT Signing Keys (RSA) | Semanal | Automatico | auth-service |
| TLS Certificates (publicos) | Cada 60 dias | cert-manager (auto) | Sistema |
| TLS Certificates (internos) | Anual | cert-manager | Sistema |
| Database passwords | Trimestral | Semi-automatico | DevOps |
Custodia de Claves (Dual Control)
- La Master Encryption Key (KEK) requiere dual control: dos personas distintas, cada una con una parte de la clave
- Ninguna persona individual tiene acceso a la clave completa
- Los custodios firman un reconocimiento de responsabilidad
- Referencia: POL-004, seccion 4.3
Monitoreo de Viabilidad Criptografica
Fuentes Monitoreadas
| Fuente | Frecuencia de Revision | Responsable |
|---|---|---|
| NIST Special Publications (SP 800-57, SP 800-131A) | Trimestral | CISO |
| ENISA Algorithms Report | Trimestral | Equipo de Desarrollo |
| RFC/IETF deprecation notices | Continuo (suscripcion) | DevOps |
| PCI SSC Bulletin Board | Mensual | CISO |
| CERT/CC Advisories | Continuo (suscripcion) | DevOps |
| CVE Database (NVD) | Continuo (automatizado) | Sistema de alertas |
Estrategia de Migracion para Cipher Suites Deprecated
| Severidad | Accion | Plazo |
|---|---|---|
| Critica (explotacion activa) | Migracion de emergencia | 24-72 horas |
| Alta (vulnerabilidad demostrada) | Plan de migracion urgente | 30 dias |
| Media (deprecation anunciado) | Plan de migracion planificado | 6 meses |
| Baja (recomendacion de transicion) | Inclusion en roadmap | 12 meses |
Procedimiento de Migracion Criptografica
- Evaluacion de impacto (sistemas afectados, volumen de datos)
- Seleccion de algoritmo de reemplazo (aprobado por NIST)
- Pruebas en entorno de desarrollo/staging
- Migracion gradual con soporte dual temporal (version N y N+1)
- Verificacion de compatibilidad con procesadores de pago
- Remocion del algoritmo deprecated
- Actualizacion de POL-004 y este documento de evidencia
Resumen de Controles y Estado
| Control | PCI DSS Req | Estado | Evidencia |
|---|---|---|---|
| Cifrado de PAN en reposo (AES-256-GCM) | 3.4.1 | Implementado | tokenization-service, card-vault-service |
| Envelope encryption (DEK + KEK) | 3.5.1 | Implementado | card-vault-service/crypto/ |
| No almacenamiento de SAD post-auth | 3.3 | Implementado | Sin campos CVV/PIN en schema |
| Redaccion de PAN en logs | 3.4 | Implementado | @fintrix/logging |
| TLS 1.2+ en todas las conexiones | 4.2.1 | Implementado | LB, Kong, PostgreSQL, Kafka |
| Inventario de cipher suites | 4.2.1 | Documentado | POL-004, este documento |
| Protocolos deprecated bloqueados | 4.2.1 | Implementado | SSL/TLS 1.0/1.1 deshabilitados |
| Rotacion de claves programada | 3.6.1 | Implementado | Calendario definido |
| Dual control de KEK | 3.6.1 | Implementado | Procedimiento documentado |
| Escaneo de descubrimiento de PAN | 3.4 | Pendiente QSA | Ticket #684997 (CDAT) |
| Monitoreo de viabilidad criptografica | 4.2.1 | Activo | Suscripciones NIST/CERT |
Historial de Revisiones
| Version | Fecha | Autor | Cambios |
|---|---|---|---|
| 1.0 | 2026-04-03 | Equipo de Desarrollo / Seguridad | Documento inicial de evidencia |
Aprobacion
| Rol | Nombre | Firma | Fecha |
|---|---|---|---|
| CISO / Oficial de Seguridad | _________________ | _________________ | //____ |
| Gerencia Ejecutiva | _________________ | _________________ | //____ |
