Convalida del certificato revocato utilizzando i tempi passati

2

Sto lavorando all'implementazione XAdES per Java, in quanto tale ho bisogno di un'implementazione crittografica per poter verificare i certificati in passato.

Purtroppo ho problemi a verificare i certificati revocati. La situazione è la seguente:

(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

Il provider di crittografia di Sun ( X509CRLSelector ) non può utilizzare CRL da "future", quindi la convalida mediante CRL è stata pubblicata 1 ora fa quando la data di verifica è 12 ore in caso di esito negativo. Questo comportamento è completamente sbagliato per il mio caso di utilizzo in quanto la legge polacca richiede un periodo di grazia di 1 ora tra la data e l'ora della firma e la pubblicazione CRL prima che il documento possa essere completamente convalidato.

Quando utilizzi il provider di crittografia di Bouncy Castle, il problema di X509CRLSelector è corretto , ma quando provo per convalidare il certificato revocato mi viene allegata la traccia dello stack.

Comprendo la convalida dei certificati con revoca errata (e l'errore BC è un comportamento corretto) o il comportamento di CertPathBuilder è sbagliato?

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

Il tempo di convalida per questo stacktrace era Thu 18 ottobre 02:46:07 CEST 2012

    
posta Hubert Kario 18.10.2012 - 15:09
fonte

2 risposte

2

Ho letto lo standard e mi sembra che il BC non lo stia implementando correttamente.

RFC 5280, sezione 6.1.3, articolo (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.

In questa situazione, al momento il certificato è non revocato, in futuro sarà revocato in una certa data.

L'implementazione dovrebbe considerare il certificato come revocato prima della sua revoca data in cui è presente l'estensione della data di validità (RFC 5280, sezione 5.3.2).

Ad esempio, se una CA rilascia CRL una volta alla settimana, e alcuni sistemi lo saranno dismesso a metà di questo periodo, quindi non è in violazione di RFC mettere la sua revoca data in futuro. Direi che questo è previsto comportamento da parte di una CA quando i sistemi automatici che dipendono dal download di questa CA. CRL solo una volta alla settimana. Tale uso non è in violazione di RFC, come solo si aspetta che la data di revoca sia successiva al tempo di pubblicazione del precedente CRL. Ma tale caso d'uso non è supportato da BC.

Inoltre, questo è il comportamento da cui dipende la RFC 3161. Come indicato nella sezione 4 di 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. 

Quindi un'implementazione non dovrebbe trattare un motivo di revoca non specificato come molto situazione grave, sulla linea di keyCompromise. Non mi aspetto che BC verifichi se un certificato in fase di verifica è un certificato TSA e il trattamento è altrettanto valido dopo il suo non AfterDate quando è presente il CRL appropriato, ma penso di poterlo fare si aspetta che BC consideri il certificato come valido prima il loro decodificatore quando io fornito CRL pubblicato prima della fine del certificato.

    
risposta data 20.10.2012 - 18:25
fonte
1

Ti consiglio di trasferirlo a SO, poiché è correlato al codice: potrebbe esserci una soluzione alternativa; ma sembra che il problema sia più correlato alla convalida di un certificato revocato dopo la pubblicazione di un nuovo CRL che contiene quel certificato. Non sono al 100% sul tuo scenario, quindi correggi le mie ipotesi se necessario. Ricorda inoltre che è necessario essere in grado di convalidare l'intero percorso in base all'implementazione e potrebbe essere necessario rimuovere qualsiasi CRL o CRLDP emesso dopo il certificato iniziale.

Una spiegazione del problema del percorso CA è disponibile su SO: link

C'è anche una buona discussione su praticamente il tuo problema esatto che è venuto fuori un paio di volte nei forum BC. Non conosco la versione di BC che stai utilizzando, ma dai un'occhiata al punto di discussione qui (rimuovendo efficacemente il CRL che è stato rilasciato in futuro)

link

La sezione pertinente:

BC's path validation implementation doesn't compare the passed time to Now. The client isn't protected against glitches in the CA's systems, and the library doesn't perform sanity checking of its inputs -- and because the output of the validator is a boolean, the library also doesn't return what rule it failed on or why.

Un altro thread simile è qui: link

Effettivamente: dovresti essere in grado di ottenere il vecchio CRL (in cui la cert era ancora valida) affinché BC possa tornare come valido.

    
risposta data 19.10.2012 - 21:50
fonte