Validación de certificados revocados usando tiempos pasados

2

Estoy trabajando en la implementación de XAdES para Java, por lo que necesito una implementación criptográfica para poder verificar los certificados en el pasado.

Lamentablemente tengo problemas para verificar los certificados revocados. La situación se ve así:

(time)
↑
| ← in 1d:    CA and user certificate notAfter date
|
| ← *now*:      user certificate validation using time from time stamp (12h ago)
| 
| ← 1h ago:   CRL publishing
|
| ← 6h ago:   user certificate revocation (reason: unknown)
| 
| ← 12h ago:  signature creation and time stamping
|
| ← 1 day ago:
|             CA notBefore Date
|             user notBefore Date

El proveedor de servicios criptográficos de Sun ( X509CRLSelector ) no puede usar CRL de "futuro", por lo que la validación con CRL se publicó hace 1 h cuando la fecha de verificación es 12 h en el pasado. Este comportamiento es completamente incorrecto para mi caso de uso, ya que la ley polaca requiere un período de gracia de 1 hora entre el sello de tiempo de firma y la publicación de CRL antes de que el documento pueda validarse por completo.

Al usar el proveedor criptográfico Bouncy Castle, el problema X509CRLSelector es corregido , pero cuando lo intento Para validar el certificado revocado, obtengo un seguimiento de pila adjunto.

¿Entiendo que la validación de certificado con la revocación es incorrecta (y que el error de BC es el comportamiento correcto) o es incorrecto este comportamiento de CertPathBuilder?

xades4j.providers.CannotBuildCertificationPathException: Certification path could not be validated.
    at xades4j.providers.impl.PKIXCertificateValidationProvider.validateWithParams(PKIXCertificateValidationProvider.java:272)
    at xades4j.providers.impl.PKIXCertificateValidationProvider.validate(PKIXCertificateValidationProvider.java:235)
    at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:175)
    at xades4j.verification.AgedTimeStampTest.verifySignature(AgedTimeStampTest.java:339)
    at xades4j.verification.AgedTimeStampTest.testT_3v(AgedTimeStampTest.java:287)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
    at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.security.cert.CertPathBuilderException: Certification path could not be validated.
    at org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi.engineBuild(PKIXCertPathBuilderSpi.java:112)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at xades4j.providers.impl.PKIXCertificateValidationProvider.validateWithParams(PKIXCertificateValidationProvider.java:268)
    ... 28 more
Caused by: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Certificate revocation after Thu Oct 18 08:46:09 CEST 2012, reason: unspecified
    at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(RFC3280CertPathUtilities.java:1516)
    at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:274)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:250)
    at org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi.build(PKIXCertPathBuilderSpi.java:195)
    at org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi.engineBuild(PKIXCertPathBuilderSpi.java:105)
    ... 30 more
Caused by: org.bouncycastle.jce.provider.AnnotatedException: Certificate revocation after Thu Oct 18 08:46:09 CEST 2012, reason: unspecified
    at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.checkCRLs(RFC3280CertPathUtilities.java:2013)
    at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(RFC3280CertPathUtilities.java:1506)
    ... 34 more

El tiempo de validación para este seguimiento de pila fue Thu Oct 18 02:46:07 CEST 2012

    
pregunta Hubert Kario 18.10.2012 - 15:09
fuente

2 respuestas

2

He leído el estándar y me parece que BC no lo está implementando correctamente.

El RFC 5280, sección 6.1.3, elemento (a):

         (3)  At the current time, the certificate is not revoked.  This 
              may be determined by obtaining the appropriate CRL 
              (Section 6.3), by status information, or by out-of-band 
              mechanisms.

En esta situación, en el momento actual no se revoca, se se revocará en una fecha específica en el futuro.

La implementación debe tratar el certificado como revocado antes de su revocación fecha en que está presente la extensión de fecha de invalidez (RFC 5280, sección 5.3.2).

Por ejemplo, si una CA emite CRL una vez por semana, y algún sistema será dado de baja a mediados de este período, entonces no está en violación de RFC Para poner su fecha de revocación en el futuro. Yo diría que esto se espera comportamiento de una CA cuando los sistemas automatizados que dependen de esta CA descargan CRL sólo una vez por semana. Tal uso no es una violación de RFC, ya que solo espera que la fecha de revocación sea posterior al tiempo de publicación de CRL. Pero tal caso de uso no es compatible con BC.

Además, este es el comportamiento del que depende RFC 3161. Como se indica en la sección 4 de RFC 3161:

   1. When a TSA shall not be used anymore, but the TSA private key has 
      not been compromised, the authority's certificate SHALL be 
      revoked.  When the reasonCode extension relative to the revoked 
      certificate from the TSA is present in the CRL entry extensions, 
      it SHALL be set either to unspecified (0), affiliationChanged (3), 
      superseded (4) or cessationOfOperation (5).  In that case, at any 
      future time, the tokens signed with the corresponding key will be 
      considered as invalid, but tokens generated before the revocation 
      time will remain valid.  When the reasonCode extension relative to 
      the revoked certificate from the TSA is not present in the CRL 
      entry extensions, then all the tokens that have been signed with 
      the corresponding key SHALL be considered as invalid.  For that 
      reason, it is recommended to use the reasonCode extension. 

Por lo tanto, una implementación no debe tratar el motivo de revocación no especificado como una muy Grave situación, en la línea de KeyCompromise. No espero que BC compruebe si un certificado que se está verificando es un certificado TSA y se trata como válido incluso después de su notAfterDate cuando el CRL apropiado está presente, pero creo que puedo esperar que BC trate el certificado como válido antes de su fecha de revocación cuando proporcionado CRL publicado antes del fin de validez del certificado.

    
respondido por el Hubert Kario 20.10.2012 - 18:25
fuente
1

Yo recomendaría trasladar esto a SO, ya que está relacionado con el código; puede haber una solución alternativa; pero parece que el problema está más relacionado con la validación de un certificado revocado después de la publicación de una nueva CRL que contiene ese certificado. No estoy al 100% en su escenario, así que corrija mis suposiciones si es necesario. También recuerde que debe poder validar la ruta completa según su implementación, y es posible que deba eliminar cualquier CRL o CRLDP que se haya emitido después del certificado inicial.

Una explicación del problema de la ruta de CA está disponible en SO aquí: enlace

También hay una buena discusión sobre prácticamente tu problema exacto que ha surgido un par de veces en los foros de BC. No sé la versión de BC que está utilizando, pero eche un vistazo al punto de discusión aquí (eliminando efectivamente la CRL que se emitió en el futuro)

enlace

La sección pertinente:

  

La implementación de validación de ruta de BC no compara el tiempo pasado con Ahora. El cliente no está protegido contra fallos en los sistemas de la AC, y la biblioteca no realiza una comprobación de validez de sus entradas, y como la salida del validador es un booleano, la biblioteca tampoco devuelve la regla en la que falló. o por qué.

Otro hilo similar está aquí: enlace

Efectivamente: necesitarías poder obtener la CRL antigua (donde el certificado todavía era válido) para que BC pueda regresar como válida.

    
respondido por el iivel 19.10.2012 - 21:50
fuente