| Metadato | Valor |
|---|---|
| Versión / Version | 1 |
| Estado / Status | Normativo — vigente; contraste con ACM-ECCG v2.0 a la fecha de redacción |
| URI / URI | https://docs.docuten.com/earchiving/crypto-policy/v1 |
| Dónde se cita / Where it is cited | docs/governance/mets-profile.md §3.2 y docs/governance/mets-profile.xml (DOCUTEN-EARK-CRYPTO-01); fila GOV-03-10 de docs/governance/cen-ts-18170-matrix.md; restricción «Criptografía» de CLAUDE.md |
| Decisiones / Decisions | D-09, D-10, D-11 (06.9-CONTEXT.md) · PRE-05 |
| Fecha / Date | 2026-11-10 |
La URI es un identificador estable, no una URL que deba resolverse. Su publicación en esa dirección la gestiona DevOps (PRE-07), y ningún consumidor debe depender de que resuelva para validar un paquete.
The URI is a stable identifier, not a URL that must be dereferenced. Publishing it at that address is handled by DevOps (PRE-07); no consumer may depend on it resolving in order to validate a package.
Este documento es la fuente única de la política criptográfica de Docuten eArchiving. Los documentos que la citan remiten aquí y no duplican su texto.
This document is the single source of the Docuten eArchiving cryptographic policy. The documents that cite it point here and do not duplicate its text.
La política cubre todo uso con valor probatorio: fixity, firma, sellado, cadenas de hash del audit log y cualquier valor que se incorpore a evidencia sellada. Es la redacción más amplia de las que convivían en el repositorio («para fixity» frente a «todo uso con valor probatorio») y es la que rige (D-09).
The policy covers every use with evidentiary value: fixity, signing, sealing, audit-log hash chains and any value that is incorporated into sealed evidence. This is the broadest of the wordings that coexisted in the repository ("for fixity" versus "every use with evidentiary value") and it is the one that governs (D-09).
En síntesis: SHA-256 es el algoritmo por defecto y SHA-512 es opcional; SHA-384 está prohibido para fixity (divergencia declarada en §4). Los algoritmos prohibidos con valor probatorio están en la tabla de §3, y la única excepción, cerrada, se publica aparte en §5.
In short: SHA-256 is the default algorithm and SHA-512 is optional; SHA-384 is forbidden for fixity (a divergence declared in §4). The algorithms forbidden for evidentiary use are in the table in §3, and the single, closed exception is published separately in §5.
La referencia es ECCG Agreed Cryptographic Mechanisms (ACM-ECCG), versión 2.0 (abril de 2025), publicada como versión aplicable en la página de ENISA el 6 de mayo de 2025: https://certification.enisa.europa.eu/publications/eucc-guidelines-cryptography_en. Las clasificaciones de este documento se han leído en el texto primario de esa versión. La leyenda es la del propio ACM: R = recomendado; L = legacy, con validez por defecto L[2031+] (§1.1); L[aaaa] = legacy aceptable hasta el año indicado.
The reference is ECCG Agreed Cryptographic Mechanisms (ACM-ECCG), version 2.0 (April 2025), published as the applicable version on the ENISA page on 6 May 2025: https://certification.enisa.europa.eu/publications/eucc-guidelines-cryptography_en. The classifications in this document were read in the primary text of that version. The legend is ACM's own: R = recommended; L = legacy, default validity L[2031+] (§1.1); L[yyyy] = legacy acceptable until the stated year.
Existe un borrador v3 de ACM-ECCG en revisión pública desde el 2 de junio de 2026. A 2026-11-10 no hay versión final. Cuando la haya, la adaptación será una versión nueva de esta política, no una edición de esta.
A draft v3 of ACM-ECCG has been under public review since 2 June 2026. As of 2026-11-10 there is no final version. When there is one, adopting it will be a new version of this policy, not an edit of this one.
El anexo del Reglamento de Ejecución (UE) 2025/2532 designa ACM-ECCG como referencia para la evaluación de los algoritmos criptográficos y su uso, sin fijar versión ni fecha. Por eso este documento cita la versión vigente a su fecha (v2.0), y esa elección queda registrada como decisión (D-10). ETSI TS 119 312 sigue siendo una referencia general útil sobre suites criptográficas para firmas electrónicas, pero ese anexo no la cita: la referencia normativa de esta política es ACM-ECCG.
The annex to Commission Implementing Regulation (EU) 2025/2532 designates ACM-ECCG as the reference for the evaluation of cryptographic algorithms and their use, without fixing a version or a date. This document therefore cites the version in force at its date (v2.0), and that choice is recorded as a decision (D-10). ETSI TS 119 312 remains a useful general reference on cryptographic suites for electronic signatures, but that annex does not cite it: the normative reference of this policy is ACM-ECCG.
Cada fila contrasta un mecanismo en uso en el código de producción (*/src/main) con su clasificación
en ACM-ECCG v2.0. La columna «Dónde» usa anclas simbólicas (clase o método), nunca referencias a
fichero y línea, para que no caduquen con cada edición (D-53).
Each row contrasts a mechanism used in production code (*/src/main) with its classification in
ACM-ECCG v2.0. The "Dónde" (where) column uses symbolic anchors (class or method), never file-and-line
references, so they do not go stale with every edit (D-53). Columns: mechanism, use, where (symbolic
anchor), ACM v2.0 classification, Docuten position, note.
| Mecanismo | Uso | Dónde (ancla simbólica) | Clasificación ACM v2.0 | Posición de Docuten | Nota |
|---|---|---|---|---|---|
| SHA-256 | Fixity de ficheros, árbol Merkle, cadena de hash del audit log, imprint del sello de tiempo, derivación determinista de identificadores de eventos PREMIS | PackageGenerator (MessageDigest.getInstance("SHA-256")), RepresentationMetsAssembler (setCHECKSUMTYPE("SHA-256")), MerkleTree, HashChain, SealEnvelope.IMPRINT_DIGEST_ALGORITHM, DeterministicPremisEventId |
R (§2.3, familia SHA-2) | Alineada; algoritmo por defecto | Note 4-QuantumThreat de ACM: donde se exija resistencia frente a ataques cuánticos, se recomienda no usar hashes de salida inferior a 384 bits. Esta política no declara ese requisito |
| SHA-512 | Fixity opcional; imprint de 64 bytes en la petición de sello de tiempo | TsaPortImpl (32 bytes → SHA-256, 64 bytes → SHA-512; cualquier otra longitud se rechaza), TsaPortAdapter (solo admite SHA256 y SHA512), FixityCheckTasklet.ALLOWED_ALGORITHMS |
R (§2.3, familia SHA-2) | Alineada; opcional | Único algoritmo alternativo admitido junto a SHA-256 |
| SHA-384 | Prohibido para fixity | Javadoc y conjunto ALLOWED_ALGORITHMS de FixityCheckTasklet; validación de longitud del digest en CatalogIndexAdapter |
R (§2.3, familia SHA-2) | Posición más estricta que ACM-ECCG: prohibido para fixity aunque ACM lo clasifica R. Motivo: un único algoritmo de referencia y validación determinista, no riesgo criptográfico (D-11.1) | Divergencia intencional declarada en §4 |
| MD5 y SHA-1 | Prohibidos en todo uso con valor probatorio | TsaTokenImprint (un token cuyo imprint no es SHA-256 da NOT_SHA256, nunca coincidencia); FixityCheckTasklet.ALLOWED_ALGORITHMS |
Fuera de los mecanismos acordados por ACM v2.0: SHA-1 no es una función hash acordada y solo HMAC-SHA-1 se admite como L[2030] (§2.3, §3.3); MD5 no figura | Prohibidos | Docuten no usa HMAC-SHA-1. La única excepción, cerrada y sin valor de integridad, no es una fila de esta tabla: se publica aparte en §5 |
| Firma del sello cualificado (QTSP) | Sello electrónico cualificado sobre la evidencia, firmado por el QTSP con RSA PKCS#1 v1.5 sobre SHA-256 | DocutenQtspCallAdapter (mecanismo RSASHA256), DocutenQtspClient (SignatureAlgorithm.RSA_SHA256) |
PKCS#1 v1.5: L (§5.2, Note 48-PKCSFormatCheck); RSA-PSS: R (§5.2); primitiva RSA n ≥ 3000: R, n ≥ 1900: L[2025], ya expirado (§4.1, Note 30-LegacyRSA) | Acordado como legacy (L), condicionado a n ≥ 3000 en el certificado del QTSP, no verificable desde el repo. Mecanismo delegado al QTSP, regido por eIDAS | Divergencia declarada en §4. ACM-ECCG se publica en las guías de criptografía EUCC de ENISA (página citada en §2); el texto de ACM v2.0 no contiene una declaración sobre su aplicación a prestadores cualificados, y esta política no presume ninguna exención |
| Token de sello de tiempo RFC 3161 | Sello de tiempo cualificado del QTSP sobre el imprint | TsaPortImpl (getTimeStampResponse), AnchoredTimestampValidator (DigestAlgorithm.SHA256) |
Hash del imprint: R (§2.3). La firma del token es la del TSA del QTSP: mismo régimen que la fila anterior | Imprint alineado; firma delegada al QTSP | El tamaño de la clave del TSA tampoco es verificable desde el repo |
| AES-256-GCM | Cifrado cliente de todo blob (staging y AIP) antes de enviarlo a Azure, con una CEK por blob | EnvelopeEncryptionService (EncryptionVersion.V2_1, nunca el constructor CBC), AzureBlobAdapter (putStaging, putAip) |
AES k = 256: R (§2.1); GCM: R (§3.5), con Note 23-GMAC-GCMOptions (IV de 96 bits, construcción determinista, etiqueta de 128 bits) | Alineada en algoritmo y modo. La construcción del IV la hace el SDK de Azure (cifrado cliente v2.1) y no está verificada contra la Note 23 | La CEK es de un solo uso por blob y se envuelve con la KEK del tenant (filas siguientes) |
| RSA-OAEP-256 (wrap de la KEK, producción) | Envoltura de la CEK y del secreto del webhook con la KEK por tenant de Azure Key Vault | StorageProperties#keyWrapAlgorithm (por defecto RSA-OAEP-256), clave earchiving.storage.key-wrap-algorithm de application.yml, EnvelopeEncryptionService; KekWebhookSecretVault (usa el algoritmo configurado, no fija uno propio) |
OAEP: R (§5.1), condicionado a la primitiva RSA n ≥ 3000: R (§4.1); n ≥ 1900 era L[2025], expirado el 31-12-2025 | Tamaño de la clave fijado en el aprovisionamiento de Key Vault, fuera del repo; a verificar con az keyvault key show |
Divergencia potencial declarada en §4. El tamaño no se afirma aquí: lo que figura en el código es un supuesto de diseño, no una medida. Fila de verificación en docs/ops/immutable-env-checklist.md |
| A256KW (wrap de la KEK, solo desarrollo) | Envoltura de la CEK con una KEK AES-256 local por tenant | LocalKekProvider (activo solo con kek-provider=local; aborta el arranque con un perfil prod), ConfigurationCoherenceGuard (aborta kek-provider=local en pre) |
AES-Keywrap: R (§3.6) | Solo desarrollo; bloqueado en pre y prod | No interviene en ninguna evidencia de producción |
| HMAC-SHA-256 (webhook) | Firma de las notificaciones webhook enviadas al suscriptor | WebhookSigner (HMAC_ALGORITHM, SECRET_BYTES = 32 de SecureRandom); KekWebhookSecretVault (custodia del secreto envuelto) |
HMAC con k ≥ 125: R (§3.3); Note 19-QuantumThreat recomienda claves de al menos 192 bits donde se exija resistencia cuántica | Cumple: el secreto son 32 bytes de SecureRandom (256 bits de entropía) y la clave HMAC son los 64 bytes ASCII de su codificación hexadecimal (D-17 de 06.6) |
Verificado en WebhookSigner: la longitud del secreto se valida y nunca entra en el mensaje firmado |
| JWT RS256 | Verificación de los tokens de acceso OIDC emitidos por Keycloak | SecurityConfig (jwsAlgorithm(SignatureAlgorithm.RS256)) |
RSA PKCS#1 v1.5: L (§5.2), condicionado a n ≥ 3000 (§4.1) | Acordado como legacy (L). El tamaño de la clave del realm se fija en Keycloak, fuera del repo; a verificar | No figuraba en la lista inicial de D-10; se añade porque está en src/main (hallazgo C6) |
| TLS y mTLS | Transporte: API pública detrás del ingress, mTLS de cliente m2m en el borde, conexión a PostgreSQL | DatabaseConnectionGuard (REQUIRED_SSL_PARAMETER, sslmode=verify-full en pre y prod), application-prod.yml (server.ssl), ClientCertificateValidator (el ingress NGINX valida la cadena) |
TLS 1.3: R; TLS 1.2: L; suites TLS 1.2 ECDHE con GCM: L (§6.1) | Hecho declarado: el repo no fija versión ni suites; las deciden el JDK y el ingress de Azure. Posición: TLS 1.3 preferido, 1.2 con ECDHE-GCM admitido (ACM: L) | Divergencia declarada en §4 (D-11.3) |
Esta política no oculta dónde se separa de ACM-ECCG v2.0 ni dónde su cumplimiento depende de algo que no se puede comprobar desde el repositorio. Cada divergencia lleva su porqué (D-11).
This policy does not hide where it departs from ACM-ECCG v2.0, nor where its compliance depends on something that cannot be checked from the repository. Each divergence carries its reason (D-11).
ACM v2.0 clasifica SHA-384 como R (§2.3). Docuten lo prohíbe para fixity: es una posición más estricta que ACM-ECCG, no una alineación. El motivo no es un riesgo criptográfico, sino operativo: un único algoritmo de referencia (SHA-256, con SHA-512 como única alternativa) hace que la validación de un paquete sea determinista y que dos validadores no puedan discrepar por el algoritmo elegido.
ACM v2.0 classifies SHA-384 as R (§2.3). Docuten forbids it for fixity: this is a position stricter than ACM-ECCG, not an alignment. The reason is operational, not cryptographic risk: a single reference algorithm (SHA-256, with SHA-512 as the only alternative) makes package validation deterministic, so that two validators cannot disagree because of the chosen algorithm.
El QTSP firma el sello cualificado con RSA PKCS#1 v1.5 sobre SHA-256. ACM v2.0 acuerda ese esquema como legacy (L) y clasifica RSA-PSS como R (§5.2); la primitiva RSA exige n ≥ 3000 para R, y el rango n ≥ 1900 fue L[2025], ya expirado el 31-12-2025 (§4.1, Note 30-LegacyRSA). El tamaño de la clave del certificado del QTSP no es verificable desde el repositorio. El mecanismo está delegado al QTSP y lo rige eIDAS. Esta redacción corrige la premisa inicial de que ACM v2.0 no acordaba PKCS#1 v1.5 (hallazgo C1 de la investigación de la fase).
The QTSP signs the qualified seal with RSA PKCS#1 v1.5 over SHA-256. ACM v2.0 agrees that scheme as legacy (L) and classifies RSA-PSS as R (§5.2); the RSA primitive requires n ≥ 3000 for R, and the n ≥ 1900 range was L[2025], expired on 31-12-2025 (§4.1, Note 30-LegacyRSA). The key size of the QTSP certificate cannot be verified from the repository. The mechanism is delegated to the QTSP and governed by eIDAS. This wording corrects the initial premise that ACM v2.0 did not agree PKCS#1 v1.5 (finding C1 of the phase research).
El repositorio no fija versión de TLS ni suites criptográficas: las deciden el JDK y el ingress de Azure. Se declara como hecho. La posición de Docuten es TLS 1.3 preferido (ACM: R) y TLS 1.2 con suites ECDHE-GCM admitido (ACM: L).
The repository does not fix the TLS version or cipher suites: they are decided by the JDK and the Azure ingress. This is declared as a fact. Docuten's position is TLS 1.3 preferred (ACM: R) and TLS 1.2 with ECDHE-GCM suites admitted (ACM: L).
Tres tamaños de clave RSA se fijan fuera del repositorio y quedan a verificar: la KEK por tenant
de Azure Key Vault (RSA-OAEP-256), la clave de firma del realm de Keycloak (JWT RS256) y la del
certificado del QTSP. ACM v2.0 pide n ≥ 3000 para R (§4.1); n ≥ 1900 era L[2025] y expiró el
31-12-2025. Para la KEK, la evidencia es la salida de az keyvault key show y la verificación tiene
su fila en docs/ops/immutable-env-checklist.md (KEK RSA ≥ 3072 aprovisionada antes del primer
sellado). Esta política no afirma ningún tamaño como hecho: si la verificación diera un tamaño
inferior a 3000 bits, sería una divergencia real y se corregiría en el aprovisionamiento.
Three RSA key sizes are set outside the repository and remain to be verified: the per-tenant
Azure Key Vault KEK (RSA-OAEP-256), the Keycloak realm signing key (JWT RS256) and the QTSP
certificate key. ACM v2.0 requires n ≥ 3000 for R (§4.1); n ≥ 1900 was L[2025] and expired on
31-12-2025. For the KEK, the evidence is the output of az keyvault key show, and the check has its
row in docs/ops/immutable-env-checklist.md (RSA KEK ≥ 3072 provisioned before the first seal). This
policy asserts no size as a fact: should the check return a size below 3000 bits, that would be a real
divergence and would be corrected at provisioning.
Esta nota no es una fila de la tabla de §3 ni un mecanismo «permitido»: documenta la única excepción a la prohibición de MD5, que es cerrada (D-11.4).
This note is not a row of the table in §3, nor a "permitted" mechanism: it documents the single exception to the MD5 prohibition, which is closed (D-11.4).
UUID.nameUUIDFromBytes (UUID v3, que usa MD5 internamente) se emplea solo como derivación
determinista de nombres de blob y del aipId dentro del contenedor del tenant. Anclas:
AipBlobResolver, AipBlobResolverImpl (nombre del blob del sello), SagaStep y
CatalogIndexTasklet. Es un patrón vigente desde la fase 02.6, del que dependen los aipId ya
persistidos, y por eso no es reversible sin dejar huérfanos los AIP existentes. No aporta ni sustituye
garantía de integridad alguna: esa la dan el sello cualificado y las cadenas SHA-256. Su entrada es un
UUID aleatorio no adivinable (con un prefijo o sufijo fijo cuando deriva un nombre secundario).
Cualquier uso nuevo de MD5 o SHA-1 fuera de esta excepción sigue prohibido sin matices.
UUID.nameUUIDFromBytes (UUID v3, which uses MD5 internally) is used only as a deterministic
derivation of blob names and of the aipId within the tenant container. Anchors: AipBlobResolver,
AipBlobResolverImpl (seal blob name), SagaStep and CatalogIndexTasklet. The pattern has been in
force since phase 02.6 and the already persisted aipId values depend on it, so it cannot be reversed
without orphaning existing AIPs. It provides no integrity guarantee and replaces none: that is
provided by the qualified seal and the SHA-256 chains. Its input is an unguessable random UUID (with a
fixed prefix or suffix when it derives a secondary name). Any new use of MD5 or SHA-1 outside this
exception remains forbidden without qualification.
DeterministicPremisEventId evita a propósito reutilizar este patrón: deriva los identificadores de
eventos PREMIS con SHA-256.
DeterministicPremisEventId deliberately avoids reusing this pattern: it derives PREMIS event
identifiers with SHA-256.
Un cambio de esta política es una versión nueva (v2, con su propia URI), nunca una edición del
texto que cita la evidencia ya emitida. La adopción de una versión final de
ACM-ECCG v3 se hará mediante crypto-policy/v2.
A change to this policy is a new version (v2, with its own URI), never an edit of the text cited
by evidence already issued. Adopting a final version of ACM-ECCG v3 will be done through
crypto-policy/v2.
Este documento no contiene claves, secretos ni material criptográfico: solo nombres de algoritmos, tamaños y anclas simbólicas.
This document contains no keys, secrets or cryptographic material: only algorithm names, sizes and symbolic anchors.