open-eid / digidoc4j

DigiDoc for Java. Javadoc:
http://open-eid.github.io/digidoc4j
GNU Lesser General Public License v2.1
72 stars 40 forks source link

Adding Certificates programatically for non EU members #111

Closed SananMS closed 1 year ago

SananMS commented 2 years ago

I am trying to resolve my problem regarding the OCSP request failure. I was wondering how I can trust my certificates and add them in order to get a successful OCSP request. I have OCSP and CERTS in .yaml file of digidocj.

SananMS commented 2 years ago

Additionally, is it mandatory for a new TSL or it is possible without it, as well?

naare commented 2 years ago

You can take a look at the unit tests for examples: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java#L105

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java#L712

If you want more precise control over parameters use this method: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/TSLCertificateSource.java#L54

Keep in mind that you need to trust all the certificate chains used in the signing process (signer, timestamp and OCSP chain).

SananMS commented 2 years ago

When it comes to List in the examples it gets it directly after adding the certificate to the source; however, in the case addCertificate() method I need to have such a list beforehand. How can retrieve this list, specifically for addCertificate() method?

SananMS commented 2 years ago

You can take a look at the unit tests for examples:

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java#L105

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java#L712

If you want more precise control over parameters use this method:

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/TSLCertificateSource.java#L54

Keep in mind that you need to trust all the certificate chains used in the signing process (signer, timestamp and OCSP chain).

I tried the examples; however I get such error

Exception in thread "main" Failed to construct OCSP request
    at org.digidoc4j.impl.SKOnlineOCSPSource.buildRequest(SKOnlineOCSPSource.java:166)
    at org.digidoc4j.impl.SKOnlineOCSPSource.queryOCSPToken(SKOnlineOCSPSource.java:135)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getRevocationToken(SKOnlineOCSPSource.java:94)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getRevocationToken(SKOnlineOCSPSource.java:65)
    at eu.europa.esig.dss.validation.RevocationDataLoadingStrategy.checkOCSP(RevocationDataLoadingStrategy.java:159)
    at eu.europa.esig.dss.validation.OCSPFirstRevocationDataLoadingStrategy.getRevocationToken(OCSPFirstRevocationDataLoadingStrategy.java:41)
    at eu.europa.esig.dss.validation.SignatureValidationContext.getRevocationToken(SignatureValidationContext.java:783)
    at eu.europa.esig.dss.validation.SignatureValidationContext.getRevocationData(SignatureValidationContext.java:726)
    at eu.europa.esig.dss.validation.SignatureValidationContext.validate(SignatureValidationContext.java:661)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.validateContext(SignedDocumentValidator.java:626)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.getValidationData(SignedDocumentValidator.java:506)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.getValidationData(SignedDocumentValidator.java:495)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineLT.extendSignatures(XAdESLevelBaselineLT.java:92)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineT.extendSignatures(XAdESLevelBaselineT.java:144)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineT.extendSignatures(XAdESLevelBaselineT.java:81)
    at eu.europa.esig.dss.xades.signature.XAdESService.signDocument(XAdESService.java:148)
    at eu.europa.esig.dss.xades.signature.XAdESService.signDocument(XAdESService.java:169)
    at org.digidoc4j.impl.asic.xades.XadesSigningDssFacade.signDocument(XadesSigningDssFacade.java:121)
    at org.digidoc4j.impl.asic.AsicSignatureFinalizer.finalizeSignature(AsicSignatureFinalizer.java:86)
    at org.digidoc4j.DataToSign.finalize(DataToSign.java:93)
    at org.example.DigidocTest.main(DigidocTest.java:551)
Caused by: eu.europa.esig.dss.model.DSSException: Unable to instantiate KeyStoreSignatureTokenConnection
    at eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection.<init>(KeyStoreSignatureTokenConnection.java:105)
    at eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection.<init>(KeyStoreSignatureTokenConnection.java:81)
    at eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection.<init>(KeyStoreSignatureTokenConnection.java:69)
    at eu.europa.esig.dss.token.Pkcs12SignatureToken.<init>(Pkcs12SignatureToken.java:85)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getOCSPAccessCertificatePrivateKey(SKOnlineOCSPSource.java:279)
    at org.digidoc4j.impl.SKOnlineOCSPSource.buildRequest(SKOnlineOCSPSource.java:158)
    ... 20 more
Caused by: java.io.IOException: toDerInputStream rejects tag type 45
    at java.base/sun.security.util.DerValue.toDerInputStream(DerValue.java:886)
    at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1974)
    at java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:222)
    at java.base/java.security.KeyStore.load(KeyStore.java:1479)
    at eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection.<init>(KeyStoreSignatureTokenConnection.java:103)
    ... 25 more
SananMS commented 2 years ago

I was able to overcome this issue by creating a .jks file from the ocsp certificate and then creating a .p12 file from the .jks file. However, now I get the following error:

Exception in thread "main" Failed to construct OCSP request
    at org.digidoc4j.impl.SKOnlineOCSPSource.buildRequest(SKOnlineOCSPSource.java:166)
    at org.digidoc4j.impl.SKOnlineOCSPSource.queryOCSPToken(SKOnlineOCSPSource.java:135)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getRevocationToken(SKOnlineOCSPSource.java:94)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getRevocationToken(SKOnlineOCSPSource.java:65)
    at eu.europa.esig.dss.validation.RevocationDataLoadingStrategy.checkOCSP(RevocationDataLoadingStrategy.java:159)
    at eu.europa.esig.dss.validation.OCSPFirstRevocationDataLoadingStrategy.getRevocationToken(OCSPFirstRevocationDataLoadingStrategy.java:41)
    at eu.europa.esig.dss.validation.SignatureValidationContext.getRevocationToken(SignatureValidationContext.java:783)
    at eu.europa.esig.dss.validation.SignatureValidationContext.getRevocationData(SignatureValidationContext.java:726)
    at eu.europa.esig.dss.validation.SignatureValidationContext.validate(SignatureValidationContext.java:661)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.validateContext(SignedDocumentValidator.java:626)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.getValidationData(SignedDocumentValidator.java:506)
    at eu.europa.esig.dss.validation.SignedDocumentValidator.getValidationData(SignedDocumentValidator.java:495)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineLT.extendSignatures(XAdESLevelBaselineLT.java:92)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineT.extendSignatures(XAdESLevelBaselineT.java:144)
    at eu.europa.esig.dss.xades.signature.XAdESLevelBaselineT.extendSignatures(XAdESLevelBaselineT.java:81)
    at eu.europa.esig.dss.xades.signature.XAdESService.signDocument(XAdESService.java:148)
    at eu.europa.esig.dss.xades.signature.XAdESService.signDocument(XAdESService.java:169)
    at org.digidoc4j.impl.asic.xades.XadesSigningDssFacade.signDocument(XadesSigningDssFacade.java:121)
    at org.digidoc4j.impl.asic.AsicSignatureFinalizer.finalizeSignature(AsicSignatureFinalizer.java:86)
    at org.digidoc4j.DataToSign.finalize(DataToSign.java:93)
    at org.example.DigidocTest.main(DigidocTest.java:555)
Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:372)
    at java.base/java.util.ArrayList.get(ArrayList.java:459)
    at org.digidoc4j.impl.SKOnlineOCSPSource.getOCSPAccessCertificatePrivateKey(SKOnlineOCSPSource.java:280)
    at org.digidoc4j.impl.SKOnlineOCSPSource.buildRequest(SKOnlineOCSPSource.java:158)
    ... 20 more
rsarendus commented 2 years ago

When it comes to List in the examples it gets it directly after adding the certificate to the source; however, in the case addCertificate() method I need to have such a list beforehand. How can retrieve this list, specifically for addCertificate() method?

In some cases, addTSLCertificate(X509Certificate) might be enough for adding new certificates into the trusted list: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/TSLCertificateSource.java#L18-L42

But addCertificate(CertificateToken, List<TrustProperties>) is useful in case the trust properties generated by Digidoc4j automatically for the certificate, are not suitable for your use case: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/TSLCertificateSource.java#L54

In that case, the list of TrustProperties must be created by yourself. One example of how to create TrustProperties can be seen here: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TSLCertificateSourceImpl.java#L81-L108

rsarendus commented 2 years ago

I was able to overcome this issue by creating a .jks file from the ocsp certificate and then creating a .p12 file from the .jks file. However, now I get the following error:

Indeed, only PKCS12 keystores are supported for signing OCSP requests.

According to the stack trace that you provided, your keystore does not seem to contain any private keys. In your comment you mention that you created the keystore from the OCSP certificate. But this keystore is for signing OCSP requests, which means that it must contain a key-pair - a pair of a private key and its corresponding certificate.

SananMS commented 2 years ago

I was able to overcome this issue by creating a .jks file from the ocsp certificate and then creating a .p12 file from the .jks file. However, now I get the following error:

Indeed, only PKCS12 keystores are supported for signing OCSP requests.

According to the stack trace that you provided, your keystore does not seem to contain any private keys. In your comment you mention that you created the keystore from the OCSP certificate. But this keystore is for signing OCSP requests, which means that it must contain a key-pair - a pair of a private key and its corresponding certificate.

I am using EJBCA for Certification Authority and Validation Authority and it is configured in such a way that those private keys are stored in HSM. Is there any way I can handle this situation?

rsarendus commented 2 years ago

The current default OCSPSource used in Digidoc4j supports only keystore-based OCSP request signing keys: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/impl/SKOnlineOCSPSource.java#L161

and only from PKCS12 keystores: https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/impl/SKOnlineOCSPSource.java#L277-L279

Unfortunately there currently seems to be no way to configure Digidoc4j to use custom OCSPSources either.

SananMS commented 2 years ago

The current default OCSPSource used in Digidoc4j supports only keystore-based OCSP request signing keys:

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/impl/SKOnlineOCSPSource.java#L161

and only from PKCS12 keystores:

https://github.com/open-eid/digidoc4j/blob/7f37926d19356fe5379b5baca6ad0206c8d2c0ce/digidoc4j/src/main/java/org/digidoc4j/impl/SKOnlineOCSPSource.java#L277-L279

Unfortunately there currently seems to be no way to configure Digidoc4j to use custom OCSPSources either.

I have been trying to find a way to make this work; however, there seems to be no hope. Also from your suggestion, it means that currently there is no way to handle this situation, am I right?

rsarendus commented 2 years ago

Apologies for the delayed answer. Unfortunately, I can't think of any easy way either to make this work, aside from forking the project yourself.