UtteraUttera

Verificar un informe

Cada informe en PDF que emitimos va firmado criptográficamente. Cualquiera —tú, tu cliente, la otra parte de una negociación— puede comprobar que un informe salió de nosotros y que nadie lo ha tocado por el camino, sin pedirnos permiso y sin tener cuenta.

Qué es y qué no es. Es una firma criptográfica de autenticidad con Ed25519. No es una firma electrónica cualificada en el sentido del reglamento eIDAS: prueba que el documento salió de nuestro sistema y que no ha cambiado, no equivale a un certificado de un prestador cualificado. Lo decimos aquí y lo dice el propio informe.

Por qué son dos firmas

Cada informe lleva dos, y cada una responde a una pregunta distinta:

FirmaSobre quéQué responde
de contenidolo que el informe dice: resumen, transcripción, nombre del cliente, fecha y consumo«¿este texto salió de Uttera?» — sigue valiendo aunque el PDF se haya reimprimido, recortado o vuelto a guardar
de contenedorlos bytes del fichero PDF«¿este fichero es exactamente el que se emitió?» — detecta un solo byte cambiado

La de contenido va impresa dentro del informe, al pie de cada página, en forma de huella corta. La de contenedor no puede ir dentro —firmar algo que luego se modifica es imposible— así que viaja suelta: la devuelve la API junto al PDF. Si vas a necesitarla, guárdala al lado del fichero.

La clave pública

La publicamos en tres sitios, y los tres dan lo mismo:

https://uttera.ai/.well-known/uttera-firma.pub     el PEM, a secas
https://uttera.ai/.well-known/uttera-firma.json    todas las claves, con sus fechas
https://api.uttera.ai/v1/reports/public-key        la que está firmando ahora

La cadena de confianza es la misma que usan DKIM o los conjuntos de claves JWKS: el certificado TLS de uttera.ai acredita que el dominio es nuestro, y ese dominio publica la clave. No hace falta que te fíes de nosotros por teléfono.

Comprobarlo desde la línea de órdenes

El endpoint es público y no lleva clave de API:

POST https://api.uttera.ai/v1/reports/verify

Comprobar el fichero (firma de contenedor). Necesitas el PDF y la firma que vino con él en report.container_signature:

curl -s -X POST https://api.uttera.ai/v1/reports/verify \
  -H "Content-Type: application/json" \
  -d "{\"modo\":\"contenedor\",
       \"pdf_b64\":\"$(base64 -w0 informe.pdf)\",
       \"firma_b64\":\"LA_FIRMA_DE_CONTENEDOR\"}"

{"valid": true, "mode": "contenedor", "key_fingerprint": "56ac333b…"}

Comprobar el contenido. Necesitas la respuesta del análisis tal cual te la devolvimos, más report.content_signature y la fecha de report.generated_unix — el sello unix, que es el valor que se firmó; generated_at es la fecha escrita, para leer. El sello va impreso en el propio informe, junto al número:

curl -s -X POST https://api.uttera.ai/v1/reports/verify \
  -H "Content-Type: application/json" \
  -d '{"modo":"contenido",
       "datos": { …la respuesta de /v1/summarize… },
       "cliente":"Meridiano Asesores, S.L.",
       "titulo":"Acta de la reunión",
       "generado":1789639533,
       "firma_b64":"LA_FIRMA_DE_CONTENIDO"}'

No guardamos nada para esto. Verificar es una operación de clave pública sobre lo que nos mandas: no consultamos ningún registro. Por eso funciona con un informe de hace años, y por eso no podemos decirte cuántos informes hemos emitido ni buscarte uno que hayas perdido.

Rotación de claves

Cada clave se usa doce meses, y se cambia antes si hay cualquier sospecha. Las claves retiradas se quedan publicadas para siempre: un informe firmado hoy tiene que poder verificarse dentro de diez años.

Por eso cada informe lleva impresa, además de su firma, la huella de la clave que lo firmó. El verificador sabe cuál usar sin tener que probarlas todas.

Si alguna vez tuviéramos que retirar una clave por compromiso, lo diríamos aquí con la fecha. Y diríamos también lo incómodo: los informes firmados con ella dejan de probar nada, porque quien tuviera la clave podría haber firmado documentos con fecha anterior.