Firmar y verificar la evidencia
🟡 Parcial — Firma ECDSA-P256+DSSE+in-toto hecha; backend enchufable (local + Scaleway KMS); anclaje de identidad keyless (Sigstore) pendiente.
Toda salida del motor sei — el bundle de evidencia, el reconstruct del ciclo ISO 23894, el Anexo IV y los informes de conformidad — queda firmada antes de escribirse a disco. La firma es un requisito explícito del EU AI Act: el Anexo IV §2(g) exige que los registros de evaluación estén “fechados y firmados”. La integridad criptográfica hace que cualquier modificación posterior sea detectable.
Esquema de firma: ECDSA-P256 (RFC 6979) + DSSE + in-toto
Sección titulada «Esquema de firma: ECDSA-P256 (RFC 6979) + DSSE + in-toto»Cada artefacto .sei/* lleva un fichero hermano .sig que contiene un sobre DSSE (Dead Simple Signing Envelope) con un Statement in-toto firmado con ECDSA sobre la curva NIST P-256 (SHA-256). Las firmas son deterministas (RFC 6979): la misma clave sobre el mismo contenido produce siempre el mismo valor.
El flujo de firma es:
- El artefacto JSON se serializa en forma canónica JCS (RFC 8785) — bytes estables e idempotentes con independencia del orden de claves.
- Se construye un Statement in-toto cuyo
subjectes el digest SHA-256 del JSON canónico. Esto vincula la firma al contenido exacto del artefacto. - El Statement se convierte en el
payloaddel sobre DSSE. El sobre aplica el esquema Pre-Authentication Encoding (PAE) antes de firmar. - Se firma con el crate
p256(RustCrypto). La firma se almacena en formato crudor‖s(64 bytes) codificado en base64 dentro del sobre. - El sobre serializado se escribe en
<artefacto>.sig.
El keyid del sobre es hex(SHA-256(pubkey SEC1 sin comprimir, 65 B)): identifica la clave pública (0x04 ‖ X ‖ Y) sin transportarla entera y permite anclar la verificación a la clave esperada.
bundle.json ← evidencia del ciclo (gate, controles, risk analysis…)bundle.json.sig ← sobre DSSE · Statement in-toto · firmado ECDSA-P256Lo mismo aplica a reconstruct.json y conformance/<slug>.json.
Backend de firma enchufable
Sección titulada «Backend de firma enchufable»El firmante es enchufable vía la variable de entorno SEI_SIGNING_BACKEND:
local(por defecto) — clave ECDSA-P256 local. El escalar privado se lee deSEI_SIGNING_KEY(32 bytes en hex, 64 caracteres); si no está configurado, se usa un escalar de desarrollo fijo y conocido que solo aporta integridad/tamper-evidence, no no-repudio.scaleway-kms— la firma se delega al Scaleway Key Manager (algoritmoEC-P256-SHA256); la clave privada nunca sale del KMS. La pubkey verificadora se obtiene del KMS en formato SEC1 sin comprimir (65 B).
sei pubkey imprime la pubkey verificadora del firmante configurado (SEC1 sin comprimir, hex de 130 caracteres). El cliente la exporta y la registra en la nube por conexión (ScmConnection.signerPubkey), de modo que la nube verifica cada evidencia contra la clave esperada de ESA conexión.
Verificar con sei verify
Sección titulada «Verificar con sei verify»sei verify lee .sei/bundle.json y .sei/bundle.json.sig y comprueba cuatro condiciones en cadena:
- El sobre es un JSON DSSE válido con
payloadType: "application/vnd.in-toto+json". - El
keyiddel sobre coincide conhex(SHA-256(pubkey SEC1))de la clave configurada en el entorno (misma clave que firmó). - La firma ECDSA-P256 (raw
r‖s) sobre el PAE es válida. - El
subject.sha256del Statement in-toto coincide con el digest del bundle dado.
Si todas pasan, el comando imprime sei verify: firma VÁLIDA y devuelve exit 0. Si cualquier condición falla, devuelve exit 1 con un mensaje descriptivo.
sei verify --repo /ruta/al/proyectoSalida esperada tras un sei run correcto:
sei verify: firma VÁLIDAsei verify es el verificador autoritativo. La nube (plano cloud) implementa la misma lógica en TypeScript con @noble/curves (P-256) y verifica por conexión contra la signerPubkey registrada para esa ScmConnection, de forma fail-loud: si la conexión no tiene pubkey configurada, la nube no verifica en silencio sino que falla. Aun así, el resultado definitivo siempre es el del binario sei; la verificación en la nube es de conveniencia y DEBE coincidir.
Qué protege la firma
Sección titulada «Qué protege la firma»| Escenario | ¿Detectado por sei verify? |
|---|---|
Bundle modificado a mano tras sei run | Sí — digest SHA-256 del subject no coincide |
.sig reemplazado por otro válido de otro bundle | Sí — el subject apunta al bundle original |
| Firma forjada con clave diferente | Sí — keyid no coincide con la clave configurada |
| Firma válida sobre contenido íntegro | No es un problema — resultado: VÁLIDA |
La firma no cubre la integridad del historial git: sei reconstruct —que replaya los commits del bundle— es el mecanismo para verificar el linaje temporal.
Estado actual y líneas futuras
Sección titulada «Estado actual y líneas futuras»El anclaje de identidad keyless (Sigstore / Fulcio / Rekor) está pendiente. Este mecanismo asociaría la clave pública a una identidad OIDC verificada (p. ej. una cuenta de CI/CD) y depositaría el log de transparencia en Rekor, lo que eliminaría la dependencia de que el verificador conozca la clave pública de antemano.
La guarda de la crate refleja este estado: el módulo seigarrena-sign nombra explícitamente “ancla de identidad keyless pendiente” en su documentación interna.
Para más detalle sobre los artefactos .sei/* y su estructura de sobre, consulta Referencia: artefactos .sei/*.
Para el contexto sobre incompletitudes actuales del motor, consulta Estado e incompletitudes.
Referencias
Sección titulada «Referencias»- Artefactos
.sei/*— estructura del sobreSeiArtifact<T>, JSON Schema v1 - Estado e incompletitudes — huecos actuales del motor y líneas futuras
- Referencia CLI
sei— documentación completa desei verifyy otros subcomandos