Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
siimsuu1 committed Feb 2, 2021
2 parents ddb89ac + ac6b98d commit df4a84d
Show file tree
Hide file tree
Showing 21 changed files with 196 additions and 39 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/digidoc4j-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Digidoc4j CI with Maven

on:
push:
branches:
- main
- develop

jobs:
digidoc4j_build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-18.04]
java: [ 8, 11, 15 ]
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Build with Maven
env:
TZ: Europe/Helsinki
run: mvn clean verify -q -"Dgpg.skip"
32 changes: 32 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
DigiDoc4J Java library release notes
------------------------------------

Release 4.1.0
------------------
Summary of the major changes since 4.1.0-RC.1
------------------------------------------
* Added PolicyImplied policy support - now defaults to standard validation procedure
* Added validity verification of timestamp and OCSP certificate when creating signatures
* Fixed OCSP revocation validation
* Upgrade of TSL TLS truststore

Known issues
------------
* We have noticed a decrease in performance with the introduction of properly accessing AIA certificate resources
* Opening a container that contains signatures, triggers TSL loading (TSL lazy loading does not work as expected)
* While upgrading from versions older than 2.1.1 be sure that your integration :
- doesn't use Xalan or XercesImpl dependencies
- uses a patched Java version (JDK8 or higher)
Xalan and XercesImpl were used to patch XML vulnerabilities in older java versions. They should be discarded with higher versions because they override default Java XML security.
If it is not possible to remove Xalan, then you can set your system property to override TransformerFactory : System.setProperty("javax.xml.transform.TransformerFactory","com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");


Release 4.1.0-RC.1
------------------
Summary of the major changes since 4.0.3
Expand All @@ -16,6 +37,17 @@ Summary of the major changes since 4.0.3
* New default test OCSP responder - TEST of SK OCSP RESPONDER 2020
* Changed TSLCertificateSource interface

Known issues
------------
* We have noticed a decrease in performance with the introduction of properly accessing AIA certificate resources
* Opening a container that contains signatures, triggers TSL loading (TSL lazy loading does not work as expected)
* While upgrading from versions older than 2.1.1 be sure that your integration :
- doesn't use Xalan or XercesImpl dependencies
- uses a patched Java version (JDK8 or higher)
Xalan and XercesImpl were used to patch XML vulnerabilities in older java versions. They should be discarded with higher versions because they override default Java XML security.
If it is not possible to remove Xalan, then you can set your system property to override TransformerFactory : System.setProperty("javax.xml.transform.TransformerFactory","com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");


Release 4.0.3
------------------
Bug fixes
Expand Down
4 changes: 2 additions & 2 deletions ddoc4j/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<groupId>org.digidoc4j</groupId>
<artifactId>ddoc4j</artifactId>
<packaging>jar</packaging>
<version>4.1.0-RC.1</version>
<version>4.1.0</version>

<name>DDoc4J</name>
<description>DDoc4J is Java Library for validating DDOC documents. It's not recommended to use it directly but rather through DigiDoc4J's API.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<artifactId>digidoc4j-parent</artifactId>
<groupId>org.digidoc4j</groupId>
<version>4.1.0-RC.1</version>
<version>4.1.0</version>
</parent>

<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion ddoc4j/src/main/resources/certs/EECCRCA.crt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGVonfig
BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
Expand Down
8 changes: 4 additions & 4 deletions digidoc4j/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>org.digidoc4j</groupId>
<artifactId>digidoc4j</artifactId>
<packaging>jar</packaging>
<version>4.1.0-RC.1</version>
<version>4.1.0</version>

<name>DigiDoc4j</name>
<description>DigiDoc4j is a Java library for digitally signing documents and creating digital signature containers
Expand All @@ -18,14 +18,14 @@
<parent>
<artifactId>digidoc4j-parent</artifactId>
<groupId>org.digidoc4j</groupId>
<version>4.1.0-RC.1</version>
<version>4.1.0</version>
</parent>

<properties>
<logback-classic.version>1.2.3</logback-classic.version>
<junit.version>4.13.1</junit.version>
<dss.groupId>org.digidoc4j.dss</dss.groupId>
<dss.version>5.7.d4j.1</dss.version>
<dss.version>5.7.d4j.2</dss.version>
<dss.util.build>${project.build.directory}/build/util</dss.util.build>
<dss.util.lib>${project.build.directory}/library/util</dss.util.lib>
<dss.zip.lib>${project.build.directory}/library/zip</dss.zip.lib>
Expand All @@ -43,7 +43,7 @@
<dependency>
<artifactId>ddoc4j</artifactId>
<groupId>org.digidoc4j</groupId>
<version>4.1.0-RC.1</version>
<version>4.1.0</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.io.IOException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Date;

/**
* Created by Janar Rahumeel (CGI Estonia)
Expand Down Expand Up @@ -97,7 +98,8 @@ public Extension createNonce(X509Certificate certificate) {
}

@Override
protected void verifyOcspResponderCertificate(CertificateToken token) {
protected void verifyOcspResponderCertificate(CertificateToken token, Date producedAt) {
verifyValidityDate(token, producedAt);
TSLCertificateSource certificateSource = getConfiguration().getTSL();

if (!certificateSource.isTrusted(token)
Expand Down
21 changes: 16 additions & 5 deletions digidoc4j/src/main/java/org/digidoc4j/impl/SKOnlineOCSPSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
Expand Down Expand Up @@ -211,12 +212,12 @@ private void verifyOCSPResponse(BasicOCSPResp response) throws IOException {
} else {
continue;
}
verifyOcspResponderCertificate(token);
verifyOcspResponderCertificate(token, response.getProducedAt());
verifyOCSPResponseSignature(token, response);
}
if(!hasOcspResponderCert) {
if (!hasOcspResponderCert) {
throw CertificateValidationException.of(CertificateValidationStatus.TECHNICAL,
"None of the OCSP response certificates does have 'OCSPSigning' extended key usage");
"None of the OCSP response certificates does have 'OCSPSigning' extended key usage");
}
} else {
if (!this.configuration.isTest()) {
Expand All @@ -230,11 +231,12 @@ protected boolean isOcspResponderCertificate(CertificateToken token) {
return token.getCertificate().getExtendedKeyUsage() != null && token.getCertificate().getExtendedKeyUsage().contains(OID_OCSP_SIGNING);
} catch (CertificateParsingException e) {
throw CertificateValidationException.of(CertificateValidationStatus.TECHNICAL,
String.format("Error on verifying 'OCSPSigning' extended key usage for OCSP response certificate <%s>", token.getDSSIdAsString()), e);
String.format("Error on verifying 'OCSPSigning' extended key usage for OCSP response certificate <%s>", token.getDSSIdAsString()), e);
}
}

protected void verifyOcspResponderCertificate(CertificateToken token) {
protected void verifyOcspResponderCertificate(CertificateToken token, Date producedAt) {
verifyValidityDate(token, producedAt);
if (!configuration.getTSL().isTrusted(token)) {
throw CertificateValidationException.of(CertificateValidationStatus.UNTRUSTED,
String.format("OCSP response certificate <%s> match is not found in TSL", token.getDSSIdAsString()));
Expand All @@ -250,6 +252,15 @@ protected void verifyOcspResponderCertificate(CertificateToken token) {
}
}

protected void verifyValidityDate(CertificateToken token, Date producedAt) {
X509Certificate x509Certificate = token.getCertificate();
if (x509Certificate.getNotAfter().before(producedAt)
|| x509Certificate.getNotBefore().after(producedAt)) {
throw CertificateValidationException.of(CertificateValidationStatus.UNTRUSTED,
String.format("OCSP response certificate <%s> is expired or not yet valid", token.getDSSIdAsString()));
}
}

private void verifyOCSPResponseSignature(CertificateToken token, BasicOCSPResp ocspResponse) {
boolean signatureValid;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.digidoc4j.SignatureParameters;
import org.digidoc4j.SignatureProfile;
import org.digidoc4j.X509Cert;
import org.digidoc4j.exceptions.CertificateValidationException;
import org.digidoc4j.exceptions.ContainerWithoutFilesException;
import org.digidoc4j.exceptions.DigiDoc4JException;
import org.digidoc4j.exceptions.OCSPRequestFailedException;
Expand Down Expand Up @@ -108,6 +109,7 @@ public Signature createSignature(DSSDocument signedDocument) {
signature = signatureOpener.open(signatureWrapper);
}
validateOcspResponse(signature.getOrigin());
validateTimestampResponse(signature.getOrigin());
LOGGER.info("Signing asic successfully completed");
return signature;
}
Expand Down Expand Up @@ -136,10 +138,10 @@ private void populateParametersForFinalizingSignature(byte[] signatureValueBytes

private void setOcspSource(byte[] signatureValueBytes) {
SKOnlineOCSPSource ocspSource = (SKOnlineOCSPSource) OCSPSourceBuilder.anOcspSource().
withSignatureProfile(this.signatureParameters.getSignatureProfile()).
withSignatureValue(signatureValueBytes).
withConfiguration(configuration).
build();
withSignatureProfile(this.signatureParameters.getSignatureProfile()).
withSignatureValue(signatureValueBytes).
withConfiguration(configuration).
build();
this.facade.setOcspSource(ocspSource);
}

Expand Down Expand Up @@ -167,6 +169,16 @@ private void validateOcspResponse(XadesSignature xadesSignature) {
}
}

private void validateTimestampResponse(XadesSignature signature) {
if (signature.getTimeStampCreationTime() == null) {
return;
}
if (!signature.getTimeStampTokenCertificate().isValid(signature.getTimeStampCreationTime())) {
throw CertificateValidationException.of(CertificateValidationException.CertificateValidationStatus.UNTRUSTED,
"Timestamp response certificate is expired or not yet valid");
}
}

private boolean isBaselineSignatureProfile() {
return signatureParameters.getSignatureProfile() != null
&& (SignatureProfile.B_BES == signatureParameters.getSignatureProfile()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.digidoc4j.utils.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
Expand All @@ -38,7 +40,8 @@
public class OcspNonceValidator {

private static final Logger logger = LoggerFactory.getLogger(OcspNonceValidator.class);

private static final List<String> ALL_TM_POLICIES = Arrays.asList("1.3.6.1.4.1.10015.1000.2.10.10", "1.3.6.1.4.1.10015.1000.3.1.1",
"1.3.6.1.4.1.10015.1000.3.2.1", "1.3.6.1.4.1.10015.1000.3.2.3");
private XAdESSignature signature;
private BasicOCSPResp ocspResponse;

Expand All @@ -61,6 +64,10 @@ public boolean isValid() {
if (signature.getPolicyId() == null) {
return true;
}
String policyIdentifier = Helper.getIdentifier(signature.getPolicyId().getIdentifier());
if (!ALL_TM_POLICIES.contains(policyIdentifier)) {
return true;
}
if (ocspResponse == null) {
logger.debug("OCSP response was not found in signature: " + signature.getId());
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,18 +138,28 @@ private void addPolicyValidationErrors() {
LOGGER.debug("Extracting policy validation errors");
XAdESSignature dssSignature = this.getDssSignature();
SignaturePolicy policy = dssSignature.getPolicyId();
if (policy != null && dssSignature.getSignatureTimestamps().isEmpty()) {
if (policy == null) {
return;
}
addPolicyImpliedWarning();
if (dssSignature.getSignatureTimestamps().isEmpty()) {
String policyIdentifier = Helper.getIdentifier(policy.getIdentifier());
if (!StringUtils.equals(XadesSignatureValidator.TM_POLICY, policyIdentifier)) {
this.addValidationError(new WrongPolicyIdentifierException(String.format("Wrong policy identifier: %s", policyIdentifier)));
} else {
this.addPolicyIdentifierQualifierValidationErrors();
}
} else if (policy != null && !dssSignature.getSignatureTimestamps().isEmpty()) {
} else if (!dssSignature.getSignatureTimestamps().isEmpty()) {
LOGGER.debug("Signature profile is not LT_TM, but has defined policy");
}
}

private void addPolicyImpliedWarning() {
if (isSignaturePolicyImpliedElementPresented()) {
this.addValidationWarning(new WrongPolicyIdentifierException("Signature created with implied policy, additional conditions may apply!"));
}
}

private void addPolicyUriValidationErrors() {
LOGGER.debug("Extracting policy URL validation errors");
SignaturePolicy policy = this.getDssSignature().getPolicyId();
Expand Down
2 changes: 1 addition & 1 deletion digidoc4j/src/main/resources/conf/constraint.xml
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
<Recognition Level="FAIL"/>
<Signature Level="FAIL"/>
<NotExpired Level="FAIL"/>
<RevocationDataAvailable Level="INFORM"/>
<RevocationDataAvailable Level="FAIL"/>
<RevocationDataNextUpdatePresent Level="WARN"/>
<RevocationDataFreshness Level="FAIL"/>
<NotRevoked Level="FAIL"/>
Expand Down
2 changes: 1 addition & 1 deletion digidoc4j/src/main/resources/conf/test_constraint.xml
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
<Recognition Level="FAIL"/>
<Signature Level="FAIL"/>
<NotExpired Level="FAIL"/>
<RevocationDataAvailable Level="INFORM"/>
<RevocationDataAvailable Level="FAIL"/>
<RevocationDataNextUpdatePresent Level="WARN"/>
<RevocationDataFreshness Level="FAIL"/>
<NotRevoked Level="FAIL"/>
Expand Down
Binary file modified digidoc4j/src/main/resources/ssl/tsl_truststore.p12
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public void TSLIsLoadedAfterSettingNewTSLLocation() {
BDocContainer container = (BDocContainer) ContainerBuilder.aContainer(BDOC_CONTAINER_TYPE)
.withConfiguration(this.configuration).build();
container.getConfiguration().getTSL();
Assert.assertEquals(13, container.getConfiguration().getTSL().getCertificates().size());
Assert.assertEquals(14, container.getConfiguration().getTSL().getCertificates().size());
try {
int tenSeconds = 10000;
String tslHost = "10.0.25.57";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
package org.digidoc4j;

import org.digidoc4j.test.TestAssert;
import org.junit.Ignore;
import org.junit.Test;

public class LibraryInteroperabilityTest extends AbstractTest {

@Test
@Ignore("DD4J-672")
public void verifySignatureWithDigiDoc4j_BC_unsafe_integer_by_default() {
Container container = ContainerBuilder.aContainer().
fromExistingFile("src/test/resources/prodFiles/valid-containers/InvestorToomas.bdoc").
Expand Down
Loading

0 comments on commit df4a84d

Please sign in to comment.