Auditoría forense · remediación · 11 de septiembre de 2026
Auditoría
El dictamen, el sello, los documentos y el recuento. Una sola puerta.
Sello
El código del comprobante. El libro dice si está.
Resultados
La suma. Sin nombres.
Documentos
El trámite, en corto.
Privacidad
Qué queda y qué no.
Dictamen
Lo que el código sostiene, y lo que un operador honesto todavía debe declarar. No es un certificado. Es leer lo que corre.
Dictamen actualizado
El operador de la base ya no cruza el voto
- Integridad del acto (pública). Sostenida. Un voto por identidad, padrón por correo único, nulo del secreto del votante, sello Blake2-256 + híbrido P-256/ML-DSA-65 anclado a las claves de la institución (derivadas del secreto de despliegue, no del org_key en Postgres).
- Secreto frente a quien tiene la base. Sostenido para el administrador institucional. Recibos indexados por una clave del votante envuelta en AES-256-GCM. Nulo no derivable desde org_key. El camino Merkle y el índice de hoja no se persisten. Quien solo vuelca Postgres no une correo con opción.
- Cadena y oráculo. Libro append-only (disparadores que rechazan UPDATE/DELETE). Hora del DON obligatoria: sin feed vigente la ventana no abre. Claves del DON ligadas al secreto de despliegue y a una semilla por institución, no a la constante pública anterior.
Amenaza frente a control
Enlace o Excel copiable
CerradoControl. OTP de seis dígitos al correo del padrón. Pedido no enumerativo. /i/:token redirige a Votante.
Estado. generateInvites, getInvite y voteByInvite rechazan. El padrón ya no descarga credenciales.
Doble voto / no padronado
SostenidoControl. election_roster + nulo por secreto del votante + recibo único. Merkle de compromisos.
Estado. OTP y sesión de miembro comparten nulo. Invite retirado. Bien.
Operador lee quién votó qué
CerradoControl. Cédula ElGamal en el cliente. Recuento homomórfico: se abre la suma, nunca el voto suelto. Recibo con clave del votante. Sin leaf_index ni merkle_path.
Estado. Quien tiene el secreto de despliegue sigue en el TCB y podría desviar el descifrado. El código solo descifra agregados. Guardianes umbral, después.
Tally alterado
CerradoControl. Hash encadenado Blake2-256, sello híbrido, verificar sello, disparadores append-only.
Estado. Un SQL UPDATE sobre ballots o chain_blocks aborta. No hay consenso BFT de varios nodos.
Ventana falseada
CerradoControl. Oráculo de hora (OCR 3/5) con claves por institución.
Estado. Sin feed vigente o con feed de más de dos minutos, el voto no entra. Ya no se omite el chequeo.
Computación cuántica
CerradoControl. Sello híbrido both-must-verify, claves pinneadas a la institución.
Estado. Las claves se derivan del secreto de despliegue, no del org_key volcado. Un HSM físico sigue siendo el siguiente escalón.
IA / perfilamiento (art. 8 bis)
SostenidoControl. No hay modelo. El voto es un acto, no una inferencia.
Estado. Sostenido. No hay scoring. La EIPD del 15 ter no se dispara.
Suplantación del buzón
ResidualControl. Llave de acceso (WebAuthn) como segundo factor. OTP de seis dígitos como reserva. 10 min, 5 intentos, 5/hora.
Estado. En visores embebidos la llave a menudo no abre: el código de correo sigue siendo un factor sobre el buzón.
Purga / ARSOP Ley 21.719
CerradoControl. Canal del titular en Votante. Purga administrativa cubre padrón, roster, OTP, claves envueltas y bitácora.
Estado. Los sellos y el recuento permanecen, sin titular. Eso es la constancia del acto.
Hallazgos cerrados en el runtime
verifyHybrid compara las claves del sello con el anillo de la institución, derivado del secreto de despliegue. Un par P-256 + ML-DSA-65 ajeno firma el mismo mensaje y falla. verifyProof exige el híbrido: sin él, el desafío Fiat–Shamir no basta.
El nulo sale del secreto del votante, no de org_key + memberId. Ese secreto viaja en la sesión y se guarda envuelto (AES-256-GCM) bajo una huella del correo. El libro no guarda leaf_index ni el camino Merkle. Verificar sello no publica cédula ni nombre.
Los pallets Padrón, Quórum y Oracle existen en Rust. La mesa que vota hoy usa el runtime web, WASM como hasher y disparadores WORM en Postgres. Quien posee el secreto de despliegue sigue siendo TCB: puede desenvolver claves. Quien solo tiene la base, no. Un nodo Substrate en caliente con BFT es el siguiente escalón, no el actual.
Si falta BETTER_AUTH_SECRET en un despliegue con proyecto, el proceso aborta. En vista previa el pimiento es local y no sale a producción. El OTP y el JWT del votante ya no caen a una cadena pública.
El voto se cifra en el dispositivo (ElGamal exponencial). La urna suma cifrados y abre el total. Comprobar cédula ocurre en el cliente y no envía el azar. El comprobante muestra un código QRM, no un hash de 64 caracteres. Se puede cambiar el voto mientras la mesa esté abierta: cuenta el último.
Residual que todavía no se afirma
- El código de correo sigue siendo reserva. La llave de acceso no abre en todos los visores.
- Quien tiene el secreto de despliegue puede desenvolver la clave de urna y el secreto del votante. Eso es TCB de plataforma. El código solo descifra sumas.
- No hay consenso BFT entre varios nodos Substrate en caliente. El WORM es de base, no de red. El nulo ya no es WORM: se actualiza el puntero al sello vigente.
- La membresía se prueba con compromiso + sello institucional, no con Groth16. El camino no se publica.
Quórum es una mesa institucional donde el administrador de la base no reconstruye la cédula. El recuento es público. El titular tiene canal ARSOP. La ciberseguridad jurídica exige seguir diciendo la diferencia: la ley se crea desde el código solo si el código no miente.