diff --git a/.github/workflows/digidoc4j-verify.yml b/.github/workflows/digidoc4j-verify.yml index f15e52119..5ddeed04e 100644 --- a/.github/workflows/digidoc4j-verify.yml +++ b/.github/workflows/digidoc4j-verify.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: os: [ ubuntu-20.04 ] - java: [ 8, 11, 15 ] + java: [ 8, 11, 17 ] steps: - uses: actions/checkout@v2 - name: Set up JDK diff --git a/.mvn/wrapper/dists/apache-maven-3.8.3-bin.zip b/.mvn/wrapper/dists/apache-maven-3.8.5-bin.zip similarity index 72% rename from .mvn/wrapper/dists/apache-maven-3.8.3-bin.zip rename to .mvn/wrapper/dists/apache-maven-3.8.5-bin.zip index a3ed63f30..4217b49ae 100644 Binary files a/.mvn/wrapper/dists/apache-maven-3.8.3-bin.zip and b/.mvn/wrapper/dists/apache-maven-3.8.5-bin.zip differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index fd031704e..e3247f8e8 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip \ No newline at end of file +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip \ No newline at end of file diff --git a/README.md b/README.md index 3c7da78cc..b585d37f2 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ DigiDoc4j is a Java library for digitally signing documents and creating digital * **LT** (Long Term) - Signature with **time-stamp** and **OCSP** (both "regular" and AIA OCSP are supported). * **LTA** (Long Term Archival) - signature format has additional **archival time-stamp** to LT profile. * **.asice** or **.sce** file is in fact a ZIP container with the signed files, the signatures and the protocol control information and can basically be opened by any program that recognizes the ZIP format. -* It is recommended not to use special characters in the data file’s name, i.e. it is suggested to use only the characters that are categorized as “unreserved” according to RFC3986 (http://tools.ietf.org/html/rfc3986). +* It is recommended not to use special characters in the data file’s name, i.e. it is suggested to use only the characters that are categorized as “unreserved” according to RFC3986 (https://datatracker.ietf.org/doc/html/rfc3986). # BDOC (Estonian specific implementation of Associated Signature Container Extended) container format * Has **.bdoc** extension @@ -40,7 +40,7 @@ DigiDoc4j is a Java library for digitally signing documents and creating digital * **LT_TM** (Long Term TimeMark) - signature has **time-mark** ensuring long-term provability of the authenticity of the signature. * It is based on **XAdES baseline LT** signature format. * **.bdoc** file is in fact a ZIP container with the signed files, the signatures and the protocol control information and can basically be opened by any program that recognizes the ZIP format. -* It is recommended not to use special characters in the data file’s name, i.e. it is suggested to use only the characters that are categorized as “unreserved” according to RFC3986 (http://tools.ietf.org/html/rfc3986). +* It is recommended not to use special characters in the data file’s name, i.e. it is suggested to use only the characters that are categorized as “unreserved” according to RFC3986 (https://datatracker.ietf.org/doc/html/rfc3986). # ASiC-S (ASiC-E - Associated Signature Container Simple) container format * Has **.asics** or **.scs** extension @@ -62,17 +62,17 @@ DigiDoc4j is a Java library for digitally signing documents and creating digital * [Examples](https://github.com/open-eid/digidoc4j/wiki/Examples-of-using-it) * [Wiki](https://github.com/open-eid/digidoc4j/wiki) * [Architecture of ID-software](http://open-eid.github.io/) -* [Digital signature formats](https://www.id.ee/en/rubriik/digital-signing/) -* [BDOC 2.1.2 specification](http://id.ee/wp-content/uploads/2020/06/bdoc-spec212-eng.pdf) +* [Digital signature formats](http://www.id.ee/index.php?id=36108) +* [BDOC 2.1.2 specification](https://www.id.ee/wp-content/uploads/2021/06/bdoc-spec212-eng.pdf) * [DDOC specification](https://www.id.ee/wp-content/uploads/2020/08/digidoc_format_1.3.pdf) # Requirements * Java **8** (since version 4.0.0-RC.1) * Internet access to external verification services - * OCSP (Online Certificate Status Protocol) - http://ocsp.sk.ee - * EU TSL (European Commission's Trusted Status List) - https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml - * All the EU member states' TL servers referred in the EU TSL. Note that this list may change. (e.g. https://sr.riik.ee/tsl/estonian-tsl.xml, https://sede.minetur.gob.es/Prestadores/TSL/TSL.xml, https://www.viestintavirasto.fi/attachments/TSL-Ficora.xml etc.) - * TSA (Time Stamping Authority) - http://tsa.sk.ee +* OCSP (Online Certificate Status Protocol) - http://ocsp.sk.ee +* EU TSL (European Commission's Trusted Status List) - https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml +* All the EU member states' TL servers referred in the EU TSL. Note that this list may change. (e.g. https://sr.riik.ee/tsl/estonian-tsl.xml, https://sede.minetur.gob.es/Prestadores/TSL/TSL.xml, https://www.viestintavirasto.fi/attachments/TSL-Ficora.xml etc.) +* TSA (Time Stamping Authority) - http://tsa.sk.ee ## Maven You can use the library as a Maven dependency from the Maven Central (http://mvnrepository.com/artifact/org.digidoc4j/digidoc4j) @@ -81,7 +81,7 @@ You can use the library as a Maven dependency from the Maven Central (http://mvn org.digidoc4j digidoc4j - 4.x.x + 5.x.x ``` diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index edbf7a431..98bb96c3b 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,79 @@ DigiDoc4J Java library release notes ------------------------------------ +Release 5.0.0 +------------------ +Summary of the major changes since 4.3.0 +------------------------------------------ +* DSS version update to 5.9 (sd-dss.5.9.d4j.1), previously used DSS 5.8. Check changes in DSS here: https://github.com/esig/dss/releases +* Pivot LOTL support (https://ec.europa.eu/tools/lotl/pivot-lotl-explanation.html): + - pivot LOTL support is enabled by default for PROD mode + - pivot LOTL support is configurable via Configuration.setLotlPivotSupportEnabled(boolean) and LOTL_PIVOT_SUPPORT_ENABLED configuration parameter +* Improved digest algorithm selection: + - signature digest algorithm and datafile digest algorithm are separately configurable + - for ECC signatures, the default signature digest algorithm depends on the key length +* Changes in handling the encoded datafile names in signatures: + - a '+' sign in an encoded data file name is decoded as '+' instead of a whitespace +* TSL loading default connection and socket timeouts increased to 1 minute +* TSL refresh callbacks. More information can be found here: https://github.com/open-eid/digidoc4j/wiki/Questions-&-Answers#tsl-refresh-callbacks-since-version-500 +* Separate configurability for HTTP and HTTPS proxy user and password +* Refactoring of LOTL configuration API (Configuration class and YAML configuration parameters): + - added setLotlLocation(String) and getLotlLocation() methods, LOTL_LOCATION parameter (deprecated setTslLocation(String), getTslLocation() and TSL_LOCATION) + - added setLotlTruststorePath(String) and getLotlTruststorePath(String) methods, LOTL_TRUSTSTORE_PATH parameter (deprecated setTslKeyStoreLocation(String), getTslKeyStoreLocation() and TSL_KEYSTORE_LOCATION) + - added setLotlTruststorePassword(String) and getLotlTruststorePassword() methods, LOTL_TRUSTSTORE_PASSWORD parameter (deprecated setTslKeyStorePassword(String), getTslKeyStorePassword() and TSL_KEYSTORE_PASSWORD) + - added setLotlTruststoreType(String) and getLotlTruststoreType() methods, LOTL_TRUSTSTORE_TYPE parameter (set the default to "PKCS12" instead of "JKS") +* Removal of old API-s that were deprecated before the version 4.0.0; an inconclusive list of removed public API-s: + - methods removed from Configuration class: + - void enableBigFilesSupport(long) + - boolean isBigFilesSupportEnabled() + - methods removed from Container interface and its implementing classes: + - void addRawSignature(byte[]) + - void addRawSignature(InputStream) + - int countDataFiles() + - int countSignatures() + - void extendTo(SignatureProfile) + - DataFile getDataFile(int) + - DigestAlgorithm getDigestAlgorithm() + - DocumentType getDocumentType() + - Signature getSignature(int) + - String getSignatureProfile() + - String getVersion() + - SignedInfo prepareSigning(X509Certificate) + - void removeDataFile(String) + - void removeSignature(int) + - void save(String) + - void setSignatureParameters(SignatureParameters) + - void setSignatureProfile(SignatureProfile) + - Signature signRaw(byte[]) + - Signature sign(SignatureToken) + - methods removed from Signature interface and its implementing classes: + - String getPolicy() + - Date getProducedAt() + - byte[] getRawSignature() + - URI getSignaturePolicyURI() + - Date getSigningTime() + - List validate() + - DigestDataFile(String, DigestAlgorithm, byte[]) constructor without mimetype + - Signer interface and PKCS12Signer class +* Removal of custom TSL TLS trust-store: + - by default, Java TLS trust-store is used for both PROD and TEST modes + - no custom TSL TLS trust-store is shipped with DigiDoc4J library +* DataFile digest calculation and memory usage improvements: + - reduction of making redundant in-memory copies of the contents of datafiles + - improved calculation and caching of digest values +* Dependencies update + +Known issues +------------ +* We have noticed a slight increase in TSL loading times due to pivot LOTL support +* 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.3.0 ------------------ Summary of the major changes since 4.2.2 diff --git a/ddoc4j/pom.xml b/ddoc4j/pom.xml index e034c293b..d7c9b1879 100644 --- a/ddoc4j/pom.xml +++ b/ddoc4j/pom.xml @@ -3,10 +3,9 @@ 4.0.0 - org.digidoc4j ddoc4j jar - 4.3.0 + 5.0.0 DDoc4J DDoc4J is Java Library for validating DDOC documents. It's not recommended to use it directly but rather through DigiDoc4J's API. @@ -15,7 +14,7 @@ digidoc4j-parent org.digidoc4j - 4.3.0 + 5.0.0 diff --git a/digidoc4j/pom.xml b/digidoc4j/pom.xml index 1a7bc702f..75fda8a2c 100644 --- a/digidoc4j/pom.xml +++ b/digidoc4j/pom.xml @@ -4,10 +4,9 @@ 4.0.0 - org.digidoc4j digidoc4j jar - 4.3.0 + 5.0.0 DigiDoc4j DigiDoc4j is a Java library for digitally signing documents and creating digital signature containers @@ -18,16 +17,16 @@ digidoc4j-parent org.digidoc4j - 4.3.0 + 5.0.0 2.2 - 1.2.7 - 2.13.0 + 1.2.11 + 2.13.3 4.13.2 org.digidoc4j.dss - 5.8.d4j.1 + 5.9.d4j.1 ${project.build.directory}/build/util ${project.build.directory}/library/util ${project.build.directory}/library/zip @@ -45,7 +44,7 @@ ddoc4j org.digidoc4j - 4.3.0 + 5.0.0 @@ -76,11 +75,6 @@ commons-lang3 3.12.0 - - commons-logging - commons-logging - 1.2 - org.apache.commons commons-collections4 @@ -94,7 +88,7 @@ org.apache.santuario xmlsec - 2.1.7 + 2.2.4 org.codehaus.woodstox @@ -105,7 +99,7 @@ org.yaml snakeyaml - 1.29 + 1.30 org.slf4j @@ -208,11 +202,10 @@ - org.apache.pdfbox pdfbox - 2.0.24 + 2.0.26 ${dss.groupId} @@ -243,7 +236,7 @@ org.glassfish.jaxb jaxb-runtime - 2.3.5 + 2.3.6 javax.activation @@ -253,7 +246,7 @@ com.sun.xml.bind jaxb-impl - 2.3.5 + 2.3.6 com.sun.xml.bind @@ -287,7 +280,7 @@ org.mockito mockito-core - 3.12.4 + 4.5.1 test @@ -323,7 +316,7 @@ com.github.tomakehurst wiremock-jre8 - 2.31.0 + 2.33.2 test @@ -359,7 +352,7 @@ org.json json - 20210307 + 20220320 test @@ -521,7 +514,7 @@ org.apache.maven.plugins maven-antrun-plugin - 3.0.0 + 3.1.0 ant-util-zip @@ -613,12 +606,12 @@ org.apache.maven.plugins maven-install-plugin - 2.5.2 + 3.0.0-M1 org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.0.1 sign-artifacts @@ -639,7 +632,7 @@ org.apache.maven.plugins maven-install-plugin - 2.5.2 + 3.0.0-M1 org.apache.maven.plugins @@ -656,12 +649,12 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.2.2 org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.3.0 org.apache.maven.plugins @@ -671,7 +664,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5.3 + 3.0.0-M5 true ${project.version} @@ -700,27 +693,27 @@ org.jvnet.jaxb2.maven2 maven-jaxb2-plugin - 0.14.0 + 0.15.1 org.apache.maven.plugins maven-deploy-plugin - 2.8.2 + 3.0.0-M2 org.apache.maven.plugins maven-antrun-plugin - 3.0.0 + 3.1.0 org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.0.1 org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh diff --git a/digidoc4j/src/main/java/org/digidoc4j/Configuration.java b/digidoc4j/src/main/java/org/digidoc4j/Configuration.java index 125aae044..df2463465 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/Configuration.java +++ b/digidoc4j/src/main/java/org/digidoc4j/Configuration.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -46,6 +46,7 @@ import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.function.BiPredicate; +import java.util.stream.Collectors; import static java.util.Arrays.asList; @@ -105,7 +106,9 @@ *
  • CANONICALIZATION_FACTORY_IMPL: Canonicalization factory implementation.
    * Default value: {@value Constant.DDoc4J#CANONICALIZATION_FACTORY_IMPLEMENTATION}
  • *
  • CONNECTION_TIMEOUT: TSL HTTP Connection timeout (milliseconds).
    - * Default value: 1000
  • + * Default value: 60000 + *
  • SOCKET_TIMEOUT: TSL HTTP Socket timeout (milliseconds).
    + * Default value: 60000
  • *
  • DIGIDOC_FACTORY_IMPL: Factory implementation.
    * Default value: {@value Constant.DDoc4J#FACTORY_IMPLEMENTATION}
  • *
  • DIGIDOC_DF_CACHE_DIR: Temporary directory to use. Default: uses system's default temporary directory
  • @@ -129,20 +132,32 @@ *
  • DIGIDOC_PKCS12_PASSWD: OCSP access certificate password
  • *
  • OCSP_SOURCE: Online Certificate Service Protocol source
  • *
  • SIGN_OCSP_REQUESTS: Should OCSP requests be signed? Allowed values: true, false
  • - *
  • TSL_LOCATION: TSL Location
  • + *
  • TSL_LOCATION: TSL Location - DEPRECATED: use LOTL_LOCATION instead
  • *
  • TSP_SOURCE: Time Stamp Protocol source address
  • *
  • VALIDATION_POLICY: Validation policy source file
  • - *
  • TSL_KEYSTORE_LOCATION: keystore location for tsl signing certificates
  • - *
  • TSL_KEYSTORE_PASSWORD: keystore password for the keystore in TSL_KEYSTORE_LOCATION
  • + *
  • LOTL_LOCATION: LOTL (List of Trusted Lists) location
  • + *
  • LOTL_TRUSTSTORE_PATH: path to the trust-store for LOTL signing certificates
  • + *
  • LOTL_TRUSTSTORE_TYPE: type of trust-store for LOTL signing certificates (default is "PKCS12")
  • + *
  • LOTL_TRUSTSTORE_PASSWORD: password for the truststore in LOTL_TRUSTSTORE_PATH
  • + *
  • LOTL_PIVOT_SUPPORT_ENABLED: whether to enable LOTL pivot support (default is "true" for PROD mode + * and "false" for TEST mode)
  • + *
  • TSL_KEYSTORE_LOCATION: keystore location for tsl signing certificates - DEPRECATED: + * use LOTL_TRUSTSTORE_PATH instead
  • + *
  • TSL_KEYSTORE_PASSWORD: keystore password for the keystore in TSL_KEYSTORE_LOCATION - DEPRECATED: + * use LOTL_TRUSTSTORE_PASSWORD instead
  • *
  • TSL_CACHE_EXPIRATION_TIME: TSL cache expiration time in milliseconds
  • *
  • TRUSTED_TERRITORIES: list of countries and territories to trust and load TSL certificates * (for example, EE, LV, FR)
  • + *
  • REQUIRED_TERRITORIES: list of countries and territories that must be successfully loaded + * into the TSL (for example, EE, LV, FR) - used by the default TSL refresh callback
  • *
  • HTTP_PROXY_HOST: network proxy host name
  • *
  • HTTP_PROXY_PORT: network proxy port
  • *
  • HTTP_PROXY_USER: network proxy user (for basic auth proxy)
  • *
  • HTTP_PROXY_PASSWORD: network proxy password (for basic auth proxy)
  • *
  • HTTPS_PROXY_HOST: https network proxy host name
  • *
  • HTTPS_PROXY_PORT: https network proxy port
  • + *
  • HTTPS_PROXY_USER: https network proxy user (for basic auth proxy)
  • + *
  • HTTPS_PROXY_PASSWORD: https network proxy password (for basic auth proxy)
  • *
  • SSL_KEYSTORE_PATH: SSL KeyStore path
  • *
  • SSL_KEYSTORE_TYPE: SSL KeyStore type (default is "jks")
  • *
  • SSL_KEYSTORE_PASSWORD: SSL KeyStore password (default is an empty string)
  • @@ -180,14 +195,17 @@ public class Configuration implements Serializable { private HashMap> aiaOcspMap = new HashMap<>(); private List trustedTerritories = new ArrayList<>(); + private List requiredTerritories = new ArrayList<>(); private ArrayList inputSourceParseErrors = new ArrayList<>(); private LinkedHashMap configurationFromFile; private String configurationInputSourceName; + private DataLoaderFactory aiaDataLoaderFactory; private DataLoaderFactory ocspDataLoaderFactory; private DataLoaderFactory tspDataLoaderFactory; private DataLoaderFactory tslDataLoaderFactory; - private DataLoaderFactory aiaDataLoaderFactory; + private DSSFileLoaderFactory tslFileLoaderFactory; + private TSLRefreshCallback tslRefreshCallback; /** * Application mode @@ -402,16 +420,14 @@ public Hashtable getDDoc4JConfiguration() { } /** - * Enables big files support. Sets limit in MB when handling files are creating temporary file for streaming in + * Sets limit in MB when handling files are creating temporary file for streaming in * container creation and adding data files. *

    * Used by DigiDoc4J and by DDoc4J. * - * @param maxFileSizeCachedInMB Maximum size in MB. - * @deprecated obnoxious naming. Use {@link Configuration#setMaxFileSizeCachedInMemoryInMB(long)} instead. + * @param maxFileSizeCachedInMB maximum data file size in MB stored in memory. */ - @Deprecated - public void enableBigFilesSupport(long maxFileSizeCachedInMB) { + public void setMaxFileSizeCachedInMemoryInMB(long maxFileSizeCachedInMB) { LOGGER.debug("Set maximum datafile cached to: " + maxFileSizeCachedInMB); String value = Long.toString(maxFileSizeCachedInMB); if (isValidIntegerParameter("DIGIDOC_MAX_DATAFILE_CACHED", value)) { @@ -419,27 +435,6 @@ public void enableBigFilesSupport(long maxFileSizeCachedInMB) { } } - /** - * Sets limit in MB when handling files are creating temporary file for streaming in - * container creation and adding data files. - *

    - * Used by DigiDoc4J and by DDoc4J. - * - * @param maxFileSizeCachedInMB maximum data file size in MB stored in memory. - */ - public void setMaxFileSizeCachedInMemoryInMB(long maxFileSizeCachedInMB) { - enableBigFilesSupport(maxFileSizeCachedInMB); - } - - /** - * @return is big file support enabled - * @deprecated obnoxious naming. Use {@link Configuration#storeDataFilesOnlyInMemory()} instead. - */ - @Deprecated - public boolean isBigFilesSupportEnabled() { - return getMaxDataFileCachedInMB() >= 0; - } - /** * If all the data files should be stored in memory. Default is true (data files are temporarily stored only in * memory). @@ -488,13 +483,32 @@ public long getMaxDataFileCachedInBytes() { } /** - * Get TSL location. + * Set LOTL (List of Trusted Lists) location. + * LOTL can be loaded from file (file://) or from web (http://). If file protocol is used then + * first try is to locate file from this location if file does not exist then it tries to load + * relatively from classpath. + *

    + * Setting new location clears old values + *

    + * Windows wants it in file:DRIVE:/directories/lotl-file.xml format + * + * @param lotlLocation LOTL location to be used + */ + public void setLotlLocation(String lotlLocation) { + setConfigurationParameter(ConfigurationParameter.LotlLocation, lotlLocation); + tslManager.setTsl(null); + } + + /** + * Get LOTL (List of Trusted Lists) location. * * @return url */ - public String getTslLocation() { - String urlString = getConfigurationParameter(ConfigurationParameter.TslLocation); - if (!Protocol.isFileUrl(urlString)) return urlString; + public String getLotlLocation() { + String urlString = getConfigurationParameter(ConfigurationParameter.LotlLocation); + if (!Protocol.isFileUrl(urlString)) { + return urlString; + } try { String filePath = new URL(urlString).getPath(); if (!new File(filePath).exists()) { @@ -505,7 +519,19 @@ public String getTslLocation() { } catch (MalformedURLException e) { LOGGER.warn(e.getMessage()); } - return urlString == null ? "" : urlString; + return (urlString == null) ? "" : urlString; + } + + /** + * Get TSL location. + * + * @return url + * + * @deprecated Use {@link #getLotlLocation()} instead. + */ + @Deprecated + public String getTslLocation() { + return getLotlLocation(); } /** @@ -541,16 +567,59 @@ public TSLCertificateSource getTSL() { * Windows wants it in file:DRIVE:/directories/tsl-file.xml format * * @param tslLocation TSL Location to be used + * + * @deprecated Use {@link #setLotlLocation(String)} instead. */ + @Deprecated public void setTslLocation(String tslLocation) { - this.setConfigurationParameter(ConfigurationParameter.TslLocation, tslLocation); - this.tslManager.setTsl(null); + setLotlLocation(tslLocation); + } + + /** + * Set a file loader factory that manages the creation of custom file loaders for downloading TSL. + * @param tslFileLoaderFactory TSL file loader factory. + */ + public void setTslFileLoaderFactory(DSSFileLoaderFactory tslFileLoaderFactory) { + this.tslFileLoaderFactory = tslFileLoaderFactory; + } + + /** + * Returns the currently set TSL file loader factory or null if no custom file loader factory is set. + * @return TSL file loader factory. + */ + public DSSFileLoaderFactory getTslFileLoaderFactory() { + return tslFileLoaderFactory; + } + + /** + * Sets a callback that validates the state of the TSL after each TSL refresh. + * If no custom callback is configured, a default callback is used for TSL validation. + * @param tslRefreshCallback a callback to validate TSL after a refresh + */ + public void setTslRefreshCallback(TSLRefreshCallback tslRefreshCallback) { + this.tslRefreshCallback = tslRefreshCallback; + } + + /** + * Returns the currently configured TSL refresh callback or {@code null} if no custom callback is configured. + * @return configured TSL refresh callback or {@code null} + */ + public TSLRefreshCallback getTslRefreshCallback() { + return tslRefreshCallback; } /** * Set a data loader factory that manages the creation of custom data loaders for downloading TSL. * @param tslDataLoaderFactory TSL data loader factory. + * + * @deprecated Prefer to use {@link #setTslFileLoaderFactory(DSSFileLoaderFactory)} + * and {@link #getTslFileLoaderFactory()} instead. + * If a custom TSL file loader factory is configured, then a custom TSL data loader factory has no effect. + * If a data loader created by a custom TSL data loader factory does not implement + * {@link eu.europa.esig.dss.spi.client.http.DSSFileLoader}, then it is wrapped into a + * {@link eu.europa.esig.dss.service.http.commons.FileCacheDataLoader}. */ + @Deprecated public void setTslDataLoaderFactory(DataLoaderFactory tslDataLoaderFactory) { this.tslDataLoaderFactory = tslDataLoaderFactory; } @@ -558,7 +627,15 @@ public void setTslDataLoaderFactory(DataLoaderFactory tslDataLoaderFactory) { /** * Returns the currently set TSL data loader factory or null if no custom data loader factory is set. * @return TSL data loader factory. + * + * @deprecated Prefer to use {@link #setTslFileLoaderFactory(DSSFileLoaderFactory)} + * and {@link #getTslFileLoaderFactory()} instead. + * If a custom TSL file loader factory is configured, then a custom TSL data loader factory has no effect. + * If a data loader created by a custom TSL data loader factory does not implement + * {@link eu.europa.esig.dss.spi.client.http.DSSFileLoader}, then it is wrapped into a + * {@link eu.europa.esig.dss.service.http.commons.FileCacheDataLoader}. */ + @Deprecated public DataLoaderFactory getTslDataLoaderFactory() { return tslDataLoaderFactory; } @@ -764,36 +841,121 @@ public boolean isOcspNonceUsed() { * Set the KeyStore Location that holds potential TSL Signing certificates * * @param tslKeyStoreLocation KeyStore location to use + * + * @deprecated Use {@link #setLotlTruststorePath(String)} instead. */ + @Deprecated public void setTslKeyStoreLocation(String tslKeyStoreLocation) { - this.setConfigurationParameter(ConfigurationParameter.TslKeyStoreLocation, tslKeyStoreLocation); + setLotlTruststorePath(tslKeyStoreLocation); } /** * Get the Location to Keystore that holds potential TSL Signing certificates * * @return KeyStore Location + * + * @deprecated Use {@link #getLotlTruststorePath()} instead. */ + @Deprecated public String getTslKeyStoreLocation() { - return this.getConfigurationParameter(ConfigurationParameter.TslKeyStoreLocation); + return getLotlTruststorePath(); } /** * Set the password for Keystore that holds potential TSL Signing certificates * * @param tslKeyStorePassword Keystore password + * + * @deprecated Use {@link #setLotlTruststorePassword(String)} instead. */ + @Deprecated public void setTslKeyStorePassword(String tslKeyStorePassword) { - this.setConfigurationParameter(ConfigurationParameter.TslKeyStorePassword, tslKeyStorePassword); + setLotlTruststorePassword(tslKeyStorePassword); } /** * Get the password for Keystore that holds potential TSL Signing certificates * * @return Tsl Keystore password + * + * @deprecated Use {@link #getLotlTruststorePassword()} instead. */ + @Deprecated public String getTslKeyStorePassword() { - return getConfigurationParameter(ConfigurationParameter.TslKeyStorePassword); + return getLotlTruststorePassword(); + } + + /** + * Set the path to the trust-store that holds potential LOTL signing certificates. + * + * @param lotlTruststorePath LOTL trust-store path to use + */ + public void setLotlTruststorePath(String lotlTruststorePath) { + setConfigurationParameter(ConfigurationParameter.LotlTruststorePath, lotlTruststorePath); + } + + /** + * Get the path to the trust-store that holds potential LOTL signing certificates. + * + * @return LOTL trust-store path + */ + public String getLotlTruststorePath() { + return getConfigurationParameter(ConfigurationParameter.LotlTruststorePath); + } + + /** + * Set the type of the trust-store that holds potential LOTL signing certificates. + * Default is {@code PKCS12}. + * + * @param lotlTruststoreType LOTL trust-store type to use + */ + public void setLotlTruststoreType(String lotlTruststoreType) { + setConfigurationParameter(ConfigurationParameter.LotlTruststoreType, lotlTruststoreType); + } + + /** + * Get the type of the trust-store that holds potential LOTL signing certificates. + * + * @return LOTL trust-store type + */ + public String getLotlTruststoreType() { + return getConfigurationParameter(ConfigurationParameter.LotlTruststoreType); + } + + /** + * Set the password for the trust-store that holds potential LOTL signing certificates. + * + * @param lotlTruststorePassword LOTL trust-store password + */ + public void setLotlTruststorePassword(String lotlTruststorePassword) { + setConfigurationParameter(ConfigurationParameter.LotlTruststorePassword, lotlTruststorePassword); + } + + /** + * Get the password for the trust-store that holds potential LOTL signing certificates. + * + * @return LOTL trust-store password + */ + public String getLotlTruststorePassword() { + return getConfigurationParameter(ConfigurationParameter.LotlTruststorePassword); + } + + /** + * Set whether LOTL pivot support should be enabled + * + * @param lotlPivotSupport whether LOTL pivot support should be enabled + */ + public void setLotlPivotSupportEnabled(boolean lotlPivotSupport) { + this.setConfigurationParameter(ConfigurationParameter.LotlPivotSupportEnabled, String.valueOf(lotlPivotSupport)); + } + + /** + * Get whether LOTL pivot support is enabled + * + * @return whether LOTL pivot support is enabled + */ + public boolean isLotlPivotSupportEnabled() { + return Boolean.parseBoolean(getConfigurationParameter(ConfigurationParameter.LotlPivotSupportEnabled)); } /** @@ -903,7 +1065,16 @@ public void setRevocationAndTimestampDeltaInMinutes(int timeInMinutes) { * @return SignatureProfile. */ public SignatureProfile getSignatureProfile() { - return SignatureProfile.findByProfile(this.getConfigurationParameter(ConfigurationParameter.SignatureProfile)); + return SignatureProfile.findByProfile(getConfigurationParameter(ConfigurationParameter.SignatureProfile)); + } + + /** + * Set signature profile. + * + * @param signatureProfile profile of the signature + */ + public void setSignatureProfile(SignatureProfile signatureProfile) { + this.setConfigurationParameter(ConfigurationParameter.SignatureProfile, signatureProfile.name()); } /** @@ -915,6 +1086,34 @@ public DigestAlgorithm getSignatureDigestAlgorithm() { return DigestAlgorithm.findByAlgorithm(getConfigurationParameter(ConfigurationParameter.SignatureDigestAlgorithm)); } + /** + * Set signature digest algorithm. + * + * @param digestAlgorithm digest algorithm of signature + */ + public void setSignatureDigestAlgorithm(DigestAlgorithm digestAlgorithm) { + this.setConfigurationParameter(ConfigurationParameter.SignatureDigestAlgorithm, digestAlgorithm.name()); + } + + + /** + * Datafile digest algorithm. + * + * @return DigestAlgorithm. + */ + public DigestAlgorithm getDataFileDigestAlgorithm() { + return DigestAlgorithm.findByAlgorithm(getConfigurationParameter(ConfigurationParameter.DataFileDigestAlgorithm)); + } + + /** + * Set datafile digest algorithm. + * + * @param digestAlgorithm digest algorithm of datafile + */ + public void setDataFileDigestAlgorithm(DigestAlgorithm digestAlgorithm) { + this.setConfigurationParameter(ConfigurationParameter.DataFileDigestAlgorithm, digestAlgorithm.name()); + } + /** * @return HTTPS proxy host */ @@ -987,6 +1186,86 @@ public void setHttpsProxyPortFor(ExternalConnectionType connectionType, int http this.setConfigurationParameter(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPort), String.valueOf(httpsProxyPort)); } + /** + * Set HTTPS network proxy user name. + * + * @param httpsProxyUser username. + */ + public void setHttpsProxyUser(String httpsProxyUser) { + this.setConfigurationParameter(ConfigurationParameter.HttpsProxyUser, httpsProxyUser); + } + + /** + * Set HTTPS network proxy user name for specific type of external connections. + * Overrides network proxy user name set via {@link Configuration#setHttpsProxyUser(String)} + * + * @param connectionType type of external connections. + * @param httpsProxyUser username. + */ + public void setHttpsProxyUserFor(ExternalConnectionType connectionType, String httpsProxyUser) { + this.setConfigurationParameter(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyUser), httpsProxyUser); + } + + /** + * Get HTTPS proxy user. + * + * @return HTTPS proxy user. + */ + public String getHttpsProxyUser() { + return this.getConfigurationParameter(ConfigurationParameter.HttpsProxyUser); + } + + /** + * Get HTTPS proxy user for specific type of external connections. + * + * @param connectionType type of external connections. + * @return HTTPS proxy user. + */ + public String getHttpsProxyUserFor(ExternalConnectionType connectionType) { + String proxyUser = this.getConfigurationParameter(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyUser)); + return (proxyUser != null) ? proxyUser : this.getHttpsProxyUser(); + } + + /** + * Set HTTPS network proxy password. + * + * @param httpsProxyPassword password. + */ + public void setHttpsProxyPassword(String httpsProxyPassword) { + this.setConfigurationParameter(ConfigurationParameter.HttpsProxyPassword, httpsProxyPassword); + } + + /** + * Set HTTPS network proxy password for specific type of external connections. + * Overrides network proxy password set via {@link Configuration#setHttpsProxyPassword(String)} + * + * @param connectionType type of external connections. + * @param httpsProxyPassword password. + */ + public void setHttpsProxyPasswordFor(ExternalConnectionType connectionType, String httpsProxyPassword) { + this.setConfigurationParameter(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPassword), httpsProxyPassword); + } + + /** + * Get HTTPS proxy password. + * + * @return HTTPS proxy password. + */ + public String getHttpsProxyPassword() { + return this.getConfigurationParameter(ConfigurationParameter.HttpsProxyPassword); + } + + /** + * Get HTTPS proxy password for specific type of external connections. + * + * @param connectionType type of external connections. + * @return HTTPS proxy password. + */ + public String getHttpsProxyPasswordFor(ExternalConnectionType connectionType) { + String proxyPassword = this.getConfigurationParameter(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPassword)); + return (proxyPassword != null) ? proxyPassword : this.getHttpsProxyPassword(); + } + /** * Get http proxy host. @@ -1606,7 +1885,8 @@ public void setFullReportNeeded(boolean isFullReport) { * @return isFullReport needed boolean value. */ public boolean isFullReportNeeded() { - return Boolean.parseBoolean(this.getConfigurationParameter(ConfigurationParameter.IsFullSimpleReportNeeded)); + String isFullSimpleReportNeeded = getConfigurationParameter(ConfigurationParameter.IsFullSimpleReportNeeded); + return Boolean.parseBoolean(isFullSimpleReportNeeded != null ? isFullSimpleReportNeeded : Constant.Default.FULL_SIMPLE_REPORT); } /** @@ -1647,16 +1927,16 @@ public ExecutorService getThreadExecutor() { } /** - * Set countries and territories (2 letter country codes) whom to trust and accept certificates. + * Set countries and territories (alpha-2 country codes) whom to trust and accept certificates. *

    - * It is possible accept signatures (and certificates) only from particular countries by filtering + * It is possible to accept signatures (and certificates) only from particular countries by filtering * trusted territories. Only the TSL (and certificates) from those countries are then downloaded and * others are skipped. *

    * For example, it is possible to trust signatures only from these three countries: Estonia, Latvia and France, * and skip all other countries: "EE", "LV", "FR". * - * @param trustedTerritories list of 2 letter country codes. + * @param trustedTerritories list of alpha-2 country codes. */ public void setTrustedTerritories(String... trustedTerritories) { this.trustedTerritories = Arrays.asList(trustedTerritories); @@ -1665,12 +1945,40 @@ public void setTrustedTerritories(String... trustedTerritories) { /** * Get trusted territories. * - * @return trusted territories list. + * @return list of trusted territories */ public List getTrustedTerritories() { return trustedTerritories; } + /** + * Set countries and territories (alpha-2 country codes) whose trusted lists must always be successfully + * loaded into the TSL. + *

    + * This list is used by the default TSL refresh callback. + * If the trusted list of any of these territories fails to load, then the TSL refresh is considered + * to have been failed. + * + * @param requiredTerritories list of alpha-2 country codes. + * + * @see #setTslRefreshCallback(TSLRefreshCallback) + * @see #getTslRefreshCallback() + */ + public void setRequiredTerritories(String... requiredTerritories) { + this.requiredTerritories = Arrays.asList(requiredTerritories); + } + + /** + * Get required territories. + * + * @return list of required territories + * + * @see #setRequiredTerritories(String...) + */ + public List getRequiredTerritories() { + return requiredTerritories; + } + /** * Set allowed OCSP responders common names for timemark validation. * For example: "SK OCSP RESPONDER 2011", "ESTEID-SK OCSP RESPONDER", "KLASS3-SK OCSP RESPONDER". @@ -1799,10 +2107,11 @@ private void initDefaultValues() { LOGGER.debug("------------------------ DEFAULTS ------------------------"); this.tslManager = new TslManager(this); this.setConfigurationParameter(ConfigurationParameter.ConnectionTimeoutInMillis, - String.valueOf(Constant.ONE_SECOND_IN_MILLISECONDS)); + String.valueOf(Constant.ONE_MINUTE_IN_MILLISECONDS)); this.setConfigurationParameter(ConfigurationParameter.SocketTimeoutInMillis, - String.valueOf(Constant.ONE_SECOND_IN_MILLISECONDS)); - this.setConfigurationParameter(ConfigurationParameter.TslKeyStorePassword, "digidoc4j-password"); + String.valueOf(Constant.ONE_MINUTE_IN_MILLISECONDS)); + this.setConfigurationParameter(ConfigurationParameter.LotlTruststoreType, "PKCS12"); + this.setConfigurationParameter(ConfigurationParameter.LotlTruststorePassword, "digidoc4j-password"); this.setConfigurationParameter(ConfigurationParameter.RevocationAndTimestampDeltaInMinutes, String.valueOf(Constant.ONE_DAY_IN_MINUTES)); this.setConfigurationParameter(ConfigurationParameter.TslCacheExpirationTimeInMillis, @@ -1810,18 +2119,14 @@ private void initDefaultValues() { this.setConfigurationParameter(ConfigurationParameter.TempFileMaxAgeInMillis, String.valueOf(Constant.ONE_DAY_IN_MILLISECONDS)); this.setConfigurationParameter(ConfigurationParameter.AllowedTimestampAndOCSPResponseDeltaInMinutes, "15"); - this.setConfigurationParameter(ConfigurationParameter.SignatureProfile, Constant.Default.SIGNATURE_PROFILE); - this.setConfigurationParameter(ConfigurationParameter.SignatureDigestAlgorithm, - Constant.Default.SIGNATURE_DIGEST_ALGORITHM); - this.setConfigurationParameter(ConfigurationParameter.IsFullSimpleReportNeeded, - Constant.Default.FULL_SIMPLE_REPORT); this.setConfigurationParameter(ConfigurationParameter.useNonce, "true"); this.setConfigurationParameter(ConfigurationParameter.ZipCompressionRatioCheckThreshold, "1048576"); this.setConfigurationParameter(ConfigurationParameter.MaxAllowedZipCompressionRatio, "100"); if (Mode.TEST.equals(this.mode)) { this.setConfigurationParameter(ConfigurationParameter.TspSource, Constant.Test.TSP_SOURCE); - this.setConfigurationParameter(ConfigurationParameter.TslLocation, Constant.Test.TSL_LOCATION); - this.setConfigurationParameter(ConfigurationParameter.TslKeyStoreLocation, Constant.Test.TSL_KEYSTORE_LOCATION); + this.setConfigurationParameter(ConfigurationParameter.LotlLocation, Constant.Test.LOTL_LOCATION); + this.setConfigurationParameter(ConfigurationParameter.LotlTruststorePath, Constant.Test.LOTL_TRUSTSTORE_PATH); + this.setConfigurationParameter(ConfigurationParameter.LotlPivotSupportEnabled, "false"); this.setConfigurationParameter(ConfigurationParameter.ValidationPolicy, Constant.Test.VALIDATION_POLICY); this.setConfigurationParameter(ConfigurationParameter.OcspSource, Constant.Test.OCSP_SOURCE); this.setConfigurationParameter(ConfigurationParameter.SignOcspRequests, "false"); @@ -1833,14 +2138,15 @@ private void initDefaultValues() { this.loadYamlAiaOCSPs(loadYamlFromResource("defaults/demo_aia_ocsp.yaml"), true); } else { this.setConfigurationParameter(ConfigurationParameter.TspSource, Constant.Production.TSP_SOURCE); - this.setConfigurationParameter(ConfigurationParameter.TslLocation, Constant.Production.TSL_LOCATION); - this.setConfigurationParameter(ConfigurationParameter.TslKeyStoreLocation, - Constant.Production.TSL_KEYSTORE_LOCATION); + this.setConfigurationParameter(ConfigurationParameter.LotlLocation, Constant.Production.LOTL_LOCATION); + this.setConfigurationParameter(ConfigurationParameter.LotlTruststorePath, Constant.Production.LOTL_TRUSTSTORE_PATH); + this.setConfigurationParameter(ConfigurationParameter.LotlPivotSupportEnabled, "true"); this.setConfigurationParameter(ConfigurationParameter.ValidationPolicy, Constant.Production.VALIDATION_POLICY); this.setConfigurationParameter(ConfigurationParameter.OcspSource, Constant.Production.OCSP_SOURCE); this.setConfigurationParameter(ConfigurationParameter.SignOcspRequests, "false"); this.setConfigurationParameter(ConfigurationParameter.PrintValidationReport, "false"); - this.trustedTerritories = Constant.Production.DEFAULT_TRUESTED_TERRITORIES; + this.requiredTerritories = Constant.Production.DEFAULT_REQUIRED_TERRITORIES; + this.trustedTerritories = Constant.Production.DEFAULT_TRUSTED_TERRITORIES; this.setDDoc4JParameter("SIGN_OCSP_REQUESTS", "false"); setDDoc4JParameter("ALLOWED_OCSP_RESPONDERS_FOR_TM", StringUtils.join(Constant.Production.DEFAULT_OCSP_RESPONDERS, ",")); this.setConfigurationParameter(ConfigurationParameter.AllowedOcspRespondersForTM, Constant.Production.DEFAULT_OCSP_RESPONDERS); @@ -1867,7 +2173,8 @@ private void loadInitialConfigurationValues() { this.setDDoc4JDocConfigurationValue("DIGIDOC_OCSP_RESPONDER_URL", this.getOcspSource()); this.setDDoc4JDocConfigurationValue("DIGIDOC_FACTORY_IMPL", Constant.DDoc4J.FACTORY_IMPLEMENTATION); this.setDDoc4JDocConfigurationValue("DIGIDOC_DF_CACHE_DIR", null); - this.setConfigurationParameterFromFile("TSL_LOCATION", ConfigurationParameter.TslLocation); + this.setConfigurationParameterFromFile("TSL_LOCATION", ConfigurationParameter.LotlLocation); + this.setConfigurationParameterFromFile(ConfigurationParameter.LotlLocation); this.setConfigurationParameterFromFile("TSP_SOURCE", ConfigurationParameter.TspSource); this.setConfigurationParameterFromFile("VALIDATION_POLICY", ConfigurationParameter.ValidationPolicy); this.setConfigurationParameterFromFile("OCSP_SOURCE", ConfigurationParameter.OcspSource); @@ -1879,8 +2186,12 @@ private void loadInitialConfigurationValues() { this.setConfigurationParameterFromFile("CONNECTION_TIMEOUT", ConfigurationParameter.ConnectionTimeoutInMillis); this.setConfigurationParameterFromFile("SOCKET_TIMEOUT", ConfigurationParameter.SocketTimeoutInMillis); this.setConfigurationParameterFromFile("SIGN_OCSP_REQUESTS", ConfigurationParameter.SignOcspRequests); - this.setConfigurationParameterFromFile("TSL_KEYSTORE_LOCATION", ConfigurationParameter.TslKeyStoreLocation); - this.setConfigurationParameterFromFile("TSL_KEYSTORE_PASSWORD", ConfigurationParameter.TslKeyStorePassword); + this.setConfigurationParameterFromFile(ConfigurationParameter.LotlTruststoreType); + this.setConfigurationParameterFromFile("TSL_KEYSTORE_LOCATION", ConfigurationParameter.LotlTruststorePath); + this.setConfigurationParameterFromFile(ConfigurationParameter.LotlTruststorePath); + this.setConfigurationParameterFromFile("TSL_KEYSTORE_PASSWORD", ConfigurationParameter.LotlTruststorePassword); + this.setConfigurationParameterFromFile(ConfigurationParameter.LotlTruststorePassword); + this.setConfigurationParameterFromFile(ConfigurationParameter.LotlPivotSupportEnabled); this.setConfigurationParameterFromFile("TSL_CACHE_EXPIRATION_TIME", ConfigurationParameter.TslCacheExpirationTimeInMillis); this.setConfigurationParameterFromFile("REVOCATION_AND_TIMESTAMP_DELTA_IN_MINUTES", @@ -1890,6 +2201,8 @@ private void loadInitialConfigurationValues() { this.setConfigurationParameterFromFile("SIGNATURE_PROFILE", ConfigurationParameter.SignatureProfile); this.setConfigurationParameterFromFile("SIGNATURE_DIGEST_ALGORITHM", ConfigurationParameter.SignatureDigestAlgorithm); + this.setConfigurationParameterFromFile("DATAFILE_DIGEST_ALGORITHM", + ConfigurationParameter.DataFileDigestAlgorithm); this.setConfigurationParameterFromFile("PRINT_VALIDATION_REPORT", ConfigurationParameter.PrintValidationReport); this.setDDoc4JDocConfigurationValue("SIGN_OCSP_REQUESTS", Boolean.toString(this.hasToBeOCSPRequestSigned())); this.setDDoc4JDocConfigurationValue("DIGIDOC_PKCS12_CONTAINER", this.getOCSPAccessCertificateFileName()); @@ -1900,6 +2213,8 @@ private void loadInitialConfigurationValues() { this.setConfigurationParameterFromSystemOrFile(Constant.System.HTTPS_PROXY_PORT, ConfigurationParameter.HttpsProxyPort); this.setConfigurationParameterFromFile(ConfigurationParameter.HttpProxyUser); this.setConfigurationParameterFromFile(ConfigurationParameter.HttpProxyPassword); + this.setConfigurationParameterFromFile(ConfigurationParameter.HttpsProxyUser); + this.setConfigurationParameterFromFile(ConfigurationParameter.HttpsProxyPassword); this.setConfigurationParameterFromFile(ConfigurationParameter.SslKeystoreType); this.setConfigurationParameterFromFile(ConfigurationParameter.SslTruststoreType); this.setConfigurationParameterFromSystemOrFile(Constant.System.JAVAX_NET_SSL_KEY_STORE, ConfigurationParameter.SslKeystorePath); @@ -1912,10 +2227,12 @@ private void loadInitialConfigurationValues() { for (ExternalConnectionType connectionType : ExternalConnectionType.values()) { this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpProxyHost)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpProxyPort)); - this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyHost)); - this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPort)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpProxyUser)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpProxyPassword)); + this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyHost)); + this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPort)); + this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyUser)); + this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.HttpsProxyPassword)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.SslKeystoreType)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.SslTruststoreType)); this.setConfigurationParameterFromFile(connectionType.mapToSpecificParameter(ConfigurationParameter.SslKeystorePath)); @@ -1928,12 +2245,13 @@ private void loadInitialConfigurationValues() { } this.setConfigurationParameter(ConfigurationParameter.AllowASN1UnsafeInteger, this.getParameter(Constant .System.ORG_BOUNCYCASTLE_ASN1_ALLOW_UNSAFE_INTEGER, "ALLOW_UNSAFE_INTEGER")); - this.setConfigurationParameter(ConfigurationParameter.preferAiaOcsp, this.getParameterFromFile("PREFER_AIA_OCSP")); + this.setConfigurationParameter(ConfigurationParameter.preferAiaOcsp, this.getStringParameterFromFile("PREFER_AIA_OCSP")); this.setConfigurationParameterFromFile("ZIP_COMPRESSION_RATIO_CHECK_THRESHOLD_IN_BYTES", ConfigurationParameter.ZipCompressionRatioCheckThreshold, this::isValidLongParameter); this.setConfigurationParameterFromFile("MAX_ALLOWED_ZIP_COMPRESSION_RATIO", ConfigurationParameter.MaxAllowedZipCompressionRatio, this::isValidIntegerParameter); this.loadYamlOcspResponders(); + this.loadYamlRequiredTerritories(); this.loadYamlTrustedTerritories(); this.loadYamlTSPs(); this.loadYamlAiaOCSPs(configurationFromFile, false); @@ -2228,6 +2546,13 @@ private void loadYamlOcspResponders() { } } + private void loadYamlRequiredTerritories() { + List territories = getStringListParameterFromFile("REQUIRED_TERRITORIES"); + if (territories != null) { + requiredTerritories = territories; + } + } + private void loadYamlTrustedTerritories() { List territories = getStringListParameterFromFile("TRUSTED_TERRITORIES"); if (territories != null) { @@ -2235,11 +2560,16 @@ private void loadYamlTrustedTerritories() { } } - private String getParameterFromFile(String key) { - if (this.configurationFromFile == null) { + private Object getObjectParameterFromFile(String key) { + if (configurationFromFile != null) { + return configurationFromFile.get(key); + } else { return null; } - Object fileValue = this.configurationFromFile.get(key); + } + + private String getStringParameterFromFile(String key) { + Object fileValue = getObjectParameterFromFile(key); if (fileValue == null) { return null; } @@ -2251,15 +2581,17 @@ private String getParameterFromFile(String key) { } private List getStringListParameterFromFile(String key) { - String value = getParameterFromFile(key); - if (value == null) { - return null; + Object objectValue = getObjectParameterFromFile(key); + if (objectValue instanceof List) { + return ((List) objectValue).stream().map(Objects::toString).collect(Collectors.toList()); + } else if (objectValue != null) { + return Arrays.asList(objectValue.toString().split("\\s*,\\s*")); //Split by comma and trim whitespace } - return Arrays.asList(value.split("\\s*,\\s*")); //Split by comma and trim whitespace + return null; } private void setConfigurationParameterFromFile(String fileKey, ConfigurationParameter parameter, BiPredicate parameterValidator) { - String fileValue = this.getParameterFromFile(fileKey); + String fileValue = this.getStringParameterFromFile(fileKey); if (fileValue != null && (parameterValidator == null || parameterValidator.test(fileKey, fileValue))) { this.setConfigurationParameter(parameter, fileValue); } @@ -2396,7 +2728,7 @@ private void initOcspAccessCertPasswordForDDoc4J() { */ private String getParameter(String systemKey, String fileKey) { String valueFromJvm = System.getProperty(systemKey); - String valueFromFile = this.getParameterFromFile(fileKey); + String valueFromFile = this.getStringParameterFromFile(fileKey); this.log(valueFromJvm, valueFromFile, systemKey, fileKey); return valueFromJvm != null ? valueFromJvm : valueFromFile; } diff --git a/digidoc4j/src/main/java/org/digidoc4j/ConfigurationParameter.java b/digidoc4j/src/main/java/org/digidoc4j/ConfigurationParameter.java index 3d744abad..5ac860592 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/ConfigurationParameter.java +++ b/digidoc4j/src/main/java/org/digidoc4j/ConfigurationParameter.java @@ -7,15 +7,18 @@ public enum ConfigurationParameter { ConnectionTimeoutInMillis, SocketTimeoutInMillis, - TslCacheExpirationTimeInMillis, - TslKeyStorePassword, RevocationAndTimestampDeltaInMinutes, AllowedTimestampAndOCSPResponseDeltaInMinutes, SignatureProfile, SignatureDigestAlgorithm, + DataFileDigestAlgorithm, TspSource, - TslLocation, - TslKeyStoreLocation, + LotlLocation("LOTL_LOCATION"), + LotlTruststorePath("LOTL_TRUSTSTORE_PATH"), + LotlTruststoreType("LOTL_TRUSTSTORE_TYPE"), + LotlTruststorePassword("LOTL_TRUSTSTORE_PASSWORD"), + LotlPivotSupportEnabled("LOTL_PIVOT_SUPPORT_ENABLED"), + TslCacheExpirationTimeInMillis, ValidationPolicy, OcspSource, OcspAccessCertificateFile, @@ -23,10 +26,12 @@ public enum ConfigurationParameter { AllowedOcspRespondersForTM, HttpProxyHost("HTTP_PROXY_HOST"), HttpProxyPort("HTTP_PROXY_PORT"), - HttpsProxyHost("HTTPS_PROXY_HOST"), - HttpsProxyPort("HTTPS_PROXY_PORT"), HttpProxyUser("HTTP_PROXY_USER"), HttpProxyPassword("HTTP_PROXY_PASSWORD"), + HttpsProxyHost("HTTPS_PROXY_HOST"), + HttpsProxyPort("HTTPS_PROXY_PORT"), + HttpsProxyUser("HTTPS_PROXY_USER"), + HttpsProxyPassword("HTTPS_PROXY_PASSWORD"), SslKeystoreType("SSL_KEYSTORE_TYPE"), SslTruststoreType("SSL_TRUSTSTORE_TYPE"), SslKeystorePath("SSL_KEYSTORE_PATH"), @@ -53,10 +58,12 @@ public enum ConfigurationParameter { TslHttpProxyHost("TSL_HTTP_PROXY_HOST"), TslHttpProxyPort("TSL_HTTP_PROXY_PORT"), - TslHttpsProxyHost("TSL_HTTPS_PROXY_HOST"), - TslHttpsProxyPort("TSL_HTTPS_PROXY_PORT"), TslHttpProxyUser("TSL_HTTP_PROXY_USER"), TslHttpProxyPassword("TSL_HTTP_PROXY_PASSWORD"), + TslHttpsProxyHost("TSL_HTTPS_PROXY_HOST"), + TslHttpsProxyPort("TSL_HTTPS_PROXY_PORT"), + TslHttpsProxyUser("TSL_HTTPS_PROXY_USER"), + TslHttpsProxyPassword("TSL_HTTPS_PROXY_PASSWORD"), TslSslKeystoreType("TSL_SSL_KEYSTORE_TYPE"), TslSslTruststoreType("TSL_SSL_TRUSTSTORE_TYPE"), TslSslKeystorePath("TSL_SSL_KEYSTORE_PATH"), @@ -69,10 +76,12 @@ public enum ConfigurationParameter { OcspHttpProxyHost("OCSP_HTTP_PROXY_HOST"), OcspHttpProxyPort("OCSP_HTTP_PROXY_PORT"), - OcspHttpsProxyHost("OCSP_HTTPS_PROXY_HOST"), - OcspHttpsProxyPort("OCSP_HTTPS_PROXY_PORT"), OcspHttpProxyUser("OCSP_HTTP_PROXY_USER"), OcspHttpProxyPassword("OCSP_HTTP_PROXY_PASSWORD"), + OcspHttpsProxyHost("OCSP_HTTPS_PROXY_HOST"), + OcspHttpsProxyPort("OCSP_HTTPS_PROXY_PORT"), + OcspHttpsProxyUser("OCSP_HTTPS_PROXY_USER"), + OcspHttpsProxyPassword("OCSP_HTTPS_PROXY_PASSWORD"), OcspSslKeystoreType("OCSP_SSL_KEYSTORE_TYPE"), OcspSslTruststoreType("OCSP_SSL_TRUSTSTORE_TYPE"), OcspSslKeystorePath("OCSP_SSL_KEYSTORE_PATH"), @@ -85,10 +94,12 @@ public enum ConfigurationParameter { TspHttpProxyHost("TSP_HTTP_PROXY_HOST"), TspHttpProxyPort("TSP_HTTP_PROXY_PORT"), - TspHttpsProxyHost("TSP_HTTPS_PROXY_HOST"), - TspHttpsProxyPort("TSP_HTTPS_PROXY_PORT"), TspHttpProxyUser("TSP_HTTP_PROXY_USER"), TspHttpProxyPassword("TSP_HTTP_PROXY_PASSWORD"), + TspHttpsProxyHost("TSP_HTTPS_PROXY_HOST"), + TspHttpsProxyPort("TSP_HTTPS_PROXY_PORT"), + TspHttpsProxyUser("TSP_HTTPS_PROXY_USER"), + TspHttpsProxyPassword("TSP_HTTPS_PROXY_PASSWORD"), TspSslKeystoreType("TSP_SSL_KEYSTORE_TYPE"), TspSslTruststoreType("TSP_SSL_TRUSTSTORE_TYPE"), TspSslKeystorePath("TSP_SSL_KEYSTORE_PATH"), diff --git a/digidoc4j/src/main/java/org/digidoc4j/Constant.java b/digidoc4j/src/main/java/org/digidoc4j/Constant.java index 1bd5dc538..900dcaa68 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/Constant.java +++ b/digidoc4j/src/main/java/org/digidoc4j/Constant.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j; import java.util.Arrays; @@ -14,19 +24,17 @@ public final class Constant { public static final int ONE_SECOND_IN_MILLISECONDS = 1000; + public static final int ONE_MINUTE_IN_MILLISECONDS = 60000; public static final int ONE_DAY_IN_MINUTES = 24 * 60; public static final long ONE_DAY_IN_MILLISECONDS = 1000 * 60 * 60 * 24; public static final long ONE_MB_IN_BYTES = 1048576; public static final long CACHE_ALL_DATA_FILES = -1; public static final long CACHE_NO_DATA_FILES = 0; - @Deprecated + public static final String DDOC_CONTAINER_TYPE = "DDOC"; public static final String BDOC_CONTAINER_TYPE = "BDOC"; - @Deprecated public static final String ASICE_CONTAINER_TYPE = "ASICE"; - @Deprecated public static final String ASICS_CONTAINER_TYPE = "ASICS"; - @Deprecated public static final String PADES_CONTAINER_TYPE = "PADES"; public static final String USER_AGENT_STRING = "LIB DigiDoc4j"; @@ -46,16 +54,17 @@ public static class System { public static class Default { - public static final String SIGNATURE_PROFILE = "LT"; - public static final String SIGNATURE_DIGEST_ALGORITHM = "SHA256"; + public static final SignatureProfile SIGNATURE_PROFILE = SignatureProfile.LT; + public static final DigestAlgorithm SIGNATURE_DIGEST_ALGORITHM = DigestAlgorithm.SHA256; + public static final DigestAlgorithm DATAFILE_DIGEST_ALGORITHM = DigestAlgorithm.SHA256; public static final String FULL_SIMPLE_REPORT = "false"; } public static class Test { public static final String TSP_SOURCE = "http://demo.sk.ee/tsa"; - public static final String TSL_LOCATION = "https://open-eid.github.io/test-TL/tl-mp-test-EE.xml"; - public static final String TSL_KEYSTORE_LOCATION = "keystore/test-keystore.jks"; + public static final String LOTL_LOCATION = "https://open-eid.github.io/test-TL/tl-mp-test-EE.xml"; + public static final String LOTL_TRUSTSTORE_PATH = "classpath:truststores/test-lotl-truststore.p12"; public static final String VALIDATION_POLICY = "conf/test_constraint.xml"; public static final String OCSP_SOURCE = "http://demo.sk.ee/ocsp"; public static final String[] DEFAULT_OCSP_RESPONDERS = {"TEST of SK OCSP RESPONDER 2020", "TEST of EID-SK 2016 OCSP RESPONDER 2018", "TEST of SK OCSP RESPONDER 2011", @@ -69,11 +78,12 @@ public static class Test { public static class Production { public static final String TSP_SOURCE = "http://tsa.sk.ee"; - public static final String TSL_LOCATION = "https://ec.europa.eu/tools/lotl/eu-lotl.xml"; - public static final String TSL_KEYSTORE_LOCATION = "keystore/keystore.jks"; + public static final String LOTL_LOCATION = "https://ec.europa.eu/tools/lotl/eu-lotl.xml"; + public static final String LOTL_TRUSTSTORE_PATH = "classpath:truststores/lotl-truststore.p12"; public static final String VALIDATION_POLICY = "conf/constraint.xml"; public static final String OCSP_SOURCE = "http://ocsp.sk.ee/"; - public static final List DEFAULT_TRUESTED_TERRITORIES = Collections.unmodifiableList( + public static final List DEFAULT_REQUIRED_TERRITORIES = Collections.singletonList("EE"); + public static final List DEFAULT_TRUSTED_TERRITORIES = Collections.unmodifiableList( Arrays.asList("AT", "BE", "BG", "CY", "CZ", "DE", "DK", "EE", "ES", "FI", "FR", "EL", "HU", "HR", "IE", "IS", "IT", "LT", "LU", "LV", "LI", "MT", "NO", "NL", "PL", "PT", "RO", "SE", "SI", "SK", "UK")); diff --git a/digidoc4j/src/main/java/org/digidoc4j/Container.java b/digidoc4j/src/main/java/org/digidoc4j/Container.java index c87464889..10f732d45 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/Container.java +++ b/digidoc4j/src/main/java/org/digidoc4j/Container.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -14,7 +14,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; -import java.security.cert.X509Certificate; import java.util.List; import eu.europa.esig.dss.model.MimeType; @@ -148,6 +147,14 @@ public interface Container extends Serializable { */ InputStream saveAsStream(); + /** + * Saves the container to the java.io.OutputStream. + * + * @param out output stream. + * @see java.io.OutputStream + */ + void save(OutputStream out); + /** * Validate container * @@ -158,7 +165,7 @@ public interface Container extends Serializable { /** * Adds timestamp token * - * @param timeStampToken + * @param timeStampToken timestamp token */ void setTimeStampToken(DataFile timeStampToken); @@ -169,19 +176,6 @@ public interface Container extends Serializable { */ DataFile getTimeStampToken(); - //Deprecated methods below - - /** - * Prepare signature. - * After preparing the signature the container will have to be signed as well - * - * @param signerCert X509 Certificate to be used for preparing the signature - * @return Signed info - * @deprecated will be removed in the future. - */ - @Deprecated - SignedInfo prepareSigning(X509Certificate signerCert); - /** * Gets Configuration * @return Configuration @@ -223,181 +217,4 @@ public String toString() { } } - /** - * Return signature profile - * @deprecated will be removed in the future. - */ - @Deprecated - String getSignatureProfile(); - - /** - * Set signature parameters - * - * @param signatureParameters Signature parameters. These are related to the signing location and signer roles - * @deprecated will be removed in the future. - */ - @Deprecated - void setSignatureParameters(SignatureParameters signatureParameters); - - /** - * Get digest algorithm - * - * @return Digest algorithm - * @deprecated will be removed in the future. - */ - @Deprecated - DigestAlgorithm getDigestAlgorithm(); - - /** - * Adds a signature to the container. - * - * @param signature signature to be added to the container - * @deprecated will be removed in the future. - */ - @Deprecated - void addRawSignature(byte[] signature); - - /** - * Adds signature from the input stream to the container. - * For BDOC it throws a NotYetImplementedException(). - * - * @param signatureStream signature to be added to the container - * @deprecated will be removed in the future. - */ - @Deprecated - void addRawSignature(InputStream signatureStream); - - /** - * Returns a data file - * - * @param index index number of the data file to return - * @return data file - * @deprecated will be removed in the future. - */ - @Deprecated - DataFile getDataFile(int index); - - /** - * Return the count of DataFile objects - * @return count of DataFile objects - * @deprecated will be removed in the future. Use {@link Container#getDataFiles()} to get the size of data files in the container. - */ - @Deprecated - int countDataFiles(); - - /** - * Removes a data file from the container by data file name. Any corresponding signatures will be deleted. - * - * @param fileName name of the data file to be removed - * @deprecated will be removed in the future. Use {@link Container#removeDataFile(DataFile)} instead. - */ - @Deprecated - void removeDataFile(String fileName); - - /** - * Removes the signature with the given signature id from the container. - * - * @param signatureId id of the signature to be removed - * @deprecated will be removed in the future. - * @see Container#removeSignature(Signature) - */ - @Deprecated - void removeSignature(int signatureId); - - /** - * Saves the container to the specified location. - * - * @param path file name and path. - * @deprecated will be removed in the future. - * @see Container#saveAsFile(String) - */ - @Deprecated - void save(String path); - - /** - * Saves the container to the java.io.OutputStream. - * - * @param out output stream. - * @see java.io.OutputStream - */ - void save(OutputStream out); - - /** - * Signs all data files in the container. - * - * @param signatureToken signatureToken implementation - * @return signature - * @deprecated will be removed in the future. - */ - @Deprecated - Signature sign(SignatureToken signatureToken); - - /** - * Signs all data files in the container. - * - * @param rawSignature raw signature - * @return signature - * @deprecated will be removed in the future. - */ - @Deprecated - Signature signRaw(byte[] rawSignature); - - /** - * Return signature - * - * @param index index number of the signature to return - * @return signature - * @deprecated will be removed in the future. - */ - @Deprecated - Signature getSignature(int index); - - /** - * Return the count of Signature objects - * @return count of Signature objects - * @deprecated will be removed in the future. Use {@link Container#getSignatures()} to get the size of signatures in the container. - */ - @Deprecated - int countSignatures(); - - /** - * Returns document type ASiC or DDOC - * - * @return document type - * @deprecated will be removed in the future. - * @see Container#getType() - */ - @Deprecated - DocumentType getDocumentType(); - - - /** - * Returns container version in case of DDOC. BDOC does not have a version and it returns null - * - * @return version - * @deprecated will be removed in the future. - */ - @Deprecated - String getVersion(); - - /** - * Extends signature profile to SignatureProfile - * * - * - * @param profile signature profile - * @see SignatureProfile - * @deprecated will be removed in the future. - * @see Container#extendSignatureProfile(SignatureProfile) - */ - @Deprecated - void extendTo(SignatureProfile profile); - - /** - * Extends signature profile to @see SignatureProfile - * - * @param profile signature profile - * @deprecated will be removed in the future. - */ - @Deprecated - void setSignatureProfile(SignatureProfile profile); } diff --git a/digidoc4j/src/main/java/org/digidoc4j/ContainerOpener.java b/digidoc4j/src/main/java/org/digidoc4j/ContainerOpener.java index 6b3e45721..fe5c2a291 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/ContainerOpener.java +++ b/digidoc4j/src/main/java/org/digidoc4j/ContainerOpener.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -30,7 +30,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; import java.util.List; /** @@ -87,7 +86,6 @@ public static Container open(String path) throws DigiDoc4JException { * @param stream input stream * @param actAsBigFilesSupportEnabled acts as configuration parameter * @return container - * @see Configuration#isBigFilesSupportEnabled() returns true used for BDOC * @see ContainerBuilder */ public static Container open(InputStream stream, boolean actAsBigFilesSupportEnabled) { diff --git a/digidoc4j/src/main/java/org/digidoc4j/DSSFileLoaderFactory.java b/digidoc4j/src/main/java/org/digidoc4j/DSSFileLoaderFactory.java new file mode 100644 index 000000000..e5958d5ea --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/DSSFileLoaderFactory.java @@ -0,0 +1,31 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j; + +import eu.europa.esig.dss.spi.client.http.DSSFileLoader; + +import java.io.Serializable; + +/** + * Manages the creation of new file loaders. File loaders are used for + * downloading lists of trusted lists (LOTL) and trusted lists (TL). + */ +@FunctionalInterface +public interface DSSFileLoaderFactory extends Serializable { + + /** + * Create a new file loader instance. + * + * @return new file loader. + */ + DSSFileLoader create(); + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/DataFile.java b/digidoc4j/src/main/java/org/digidoc4j/DataFile.java index fdcf469b7..9a32c433f 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DataFile.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DataFile.java @@ -1,23 +1,22 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; +import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.model.DSSDocument; import eu.europa.esig.dss.model.DSSException; -import eu.europa.esig.dss.spi.DSSUtils; -import eu.europa.esig.dss.model.Digest; -import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.model.FileDocument; import eu.europa.esig.dss.model.InMemoryDocument; import eu.europa.esig.dss.model.MimeType; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.digidoc4j.exceptions.DigiDoc4JException; @@ -35,7 +34,6 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.OptionalLong; /** * Data file wrapper providing methods for handling signed files or files to be signed in Container. @@ -44,7 +42,6 @@ public class DataFile implements Serializable { private static final Logger logger = LoggerFactory.getLogger(DataFile.class); private DSSDocument document = null; - private Digest digest = null; private String id; /** @@ -113,8 +110,8 @@ protected MimeType getMimeType(String mimeType) { /** * Calculates digest http://www.w3.org/2001/04/xmlenc#sha256 for the data file. - * If the digest has already been calculated it will return it, otherwise it calculates the digest. - *

    + * If digest values are cached by the implementation and the digest has already been calculated, + * then the cached value will be returned, otherwise the digest value is calculated and returned. * * @return calculated digest */ @@ -123,7 +120,10 @@ public byte[] calculateDigest() { } /** - * Calculates digest for data file. If digest is already calculated returns it, otherwise calculates the digest. + * Calculates digest for data file. + * If digest values are cached by the implementation and the digest has already been calculated, + * then the cached value will be returned, otherwise the digest value is calculated and returned. + * *

    Supported uris for BDoc:

    *
    http://www.w3.org/2000/09/xmldsig#sha1 *
    http://www.w3.org/2001/04/xmldsig-more#sha224 @@ -137,13 +137,9 @@ public byte[] calculateDigest() { */ public byte[] calculateDigest(URL method) { logger.debug("URL method: " + method); - if (digest == null) { - DigestAlgorithm digestAlgorithm = DigestAlgorithm.forXML(method.toString()); - digest = new Digest(digestAlgorithm, calculateDigestInternal(digestAlgorithm)); - } else { - logger.debug("Returning existing digest value"); - } - return digest.getValue(); + DigestAlgorithm digestAlgorithm = DigestAlgorithm.forXML(method.toString()); + String digestBase64String = document.getDigest(digestAlgorithm); + return Base64.decodeBase64(digestBase64String); } /** @@ -154,11 +150,6 @@ public byte[] calculateDigest(org.digidoc4j.DigestAlgorithm digestType) { return calculateDigest(digestType.uri()); } - byte[] calculateDigestInternal(DigestAlgorithm digestAlgorithm) { - logger.debug("Digest algorithm: " + digestAlgorithm); - return DSSUtils.digest(digestAlgorithm, getBytes()); - } - /** * Returns the data file name. * @@ -187,9 +178,9 @@ public String getId() { * @return file size in bytes */ public long getFileSize() { - OptionalLong fileBackedSize = getFileSizeIfBackedByFile(); - if (fileBackedSize.isPresent()) { - return fileBackedSize.getAsLong(); + Long knownFileSize = getFileSizeIfKnown(); + if (knownFileSize != null) { + return knownFileSize; } long fileSize = 0L; try (InputStream inputStream = getStream()) { @@ -213,9 +204,9 @@ public long getFileSize() { * @return {@code true} if the data file is empty */ public boolean isFileEmpty() { - OptionalLong fileBackedSize = getFileSizeIfBackedByFile(); - if (fileBackedSize.isPresent()) { - return (fileBackedSize.getAsLong() < 1L); + Long knownFileSize = getFileSizeIfKnown(); + if (knownFileSize != null) { + return (knownFileSize < 1L); } try (InputStream inputStream = getStream()) { return (inputStream.read() < 0); // read() returns -1 if no bytes to read @@ -224,18 +215,27 @@ public boolean isFileEmpty() { } } - private OptionalLong getFileSizeIfBackedByFile() { - if (document instanceof StreamDocument || document instanceof FileDocument) { + private Long getFileSizeIfKnown() { + if (document instanceof InMemoryDocument) { + InMemoryDocument inMemoryDocument = (InMemoryDocument) document; + if (inMemoryDocument.getBytes() != null) { + return (long) (inMemoryDocument.getBytes().length); + } + } else if (document instanceof StreamDocument) { + StreamDocument streamDocument = (StreamDocument) document; + return streamDocument.getStreamLengthIfKnown(); + } else if (document instanceof FileDocument) { + FileDocument fileDocument = (FileDocument) document; try { - long fileSize = Files.size(Paths.get(document.getAbsolutePath())); + long fileSize = Files.size(Paths.get(fileDocument.getAbsolutePath())); logger.debug("Document size: " + fileSize); - return OptionalLong.of(fileSize); + return fileSize; } catch (IOException e) { logger.error(e.getMessage()); throw new DigiDoc4JException(e); } } - return OptionalLong.empty(); + return null; } /** @@ -261,8 +261,9 @@ public void setMediaType(String mediaType) { * @throws java.io.IOException on file write error */ public void saveAs(OutputStream out) throws IOException { - out.write(getBytes()); - out.close(); + try (OutputStream outputStream = out) { + document.writeTo(outputStream); + } } /** @@ -320,7 +321,7 @@ public void setDocument(DSSDocument document) { this.document = document; } - private URL getSha256DigestMethodUrl() { + private static URL getSha256DigestMethodUrl() { try { return new URL("http://www.w3.org/2001/04/xmlenc#sha256"); } catch (MalformedURLException e) { diff --git a/digidoc4j/src/main/java/org/digidoc4j/DataLoaderFactory.java b/digidoc4j/src/main/java/org/digidoc4j/DataLoaderFactory.java index 154d164d7..f09bf1555 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DataLoaderFactory.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DataLoaderFactory.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -15,9 +15,10 @@ import java.io.Serializable; /** - * Manages the creation of new data loaders. Data loaders are used in getting OCSP and TimeStamp requests and - * downloading certificates from the Trusted List (TSL). + * Manages the creation of new data loaders. Data loaders are used for getting OCSP and time-stamp requests, + * and downloading lists of trusted lists (LOTL), trusted lists (TL) and certificates. */ +@FunctionalInterface public interface DataLoaderFactory extends Serializable { /** diff --git a/digidoc4j/src/main/java/org/digidoc4j/DataToSign.java b/digidoc4j/src/main/java/org/digidoc4j/DataToSign.java index 509c788b3..ab24179b2 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DataToSign.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DataToSign.java @@ -61,7 +61,7 @@ public SignatureParameters getSignatureParameters() { * @return signature digest algorithm. */ public DigestAlgorithm getDigestAlgorithm() { - return signatureFinalizer.getSignatureParameters().getDigestAlgorithm(); + return signatureFinalizer.getSignatureParameters().getSignatureDigestAlgorithm(); } /** diff --git a/digidoc4j/src/main/java/org/digidoc4j/DetachedXadesSignatureBuilder.java b/digidoc4j/src/main/java/org/digidoc4j/DetachedXadesSignatureBuilder.java index 55e0375cd..a9bb0981f 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DetachedXadesSignatureBuilder.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DetachedXadesSignatureBuilder.java @@ -21,12 +21,14 @@ import org.digidoc4j.impl.SignatureFinalizer; import org.digidoc4j.impl.asic.AsicSignatureFinalizer; import org.digidoc4j.utils.CertificateUtils; +import org.digidoc4j.utils.DigestUtils; import org.digidoc4j.utils.Helper; import org.digidoc4j.utils.PolicyUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; import java.util.ArrayList; import java.util.List; @@ -36,8 +38,8 @@ public class DetachedXadesSignatureBuilder { private static final Logger logger = LoggerFactory.getLogger(DetachedXadesSignatureBuilder.class); - private List dataFiles = new ArrayList<>(); - private SignatureParameters signatureParameters = new SignatureParameters(); + private final List dataFiles = new ArrayList<>(); + private final SignatureParameters signatureParameters = new SignatureParameters(); private Configuration configuration; private SignatureToken signatureToken; private SignatureFinalizer signatureFinalizer; @@ -83,7 +85,19 @@ public DetachedXadesSignatureBuilder withSigningCertificate(X509Certificate cert * @return builder for creating a signature. */ public DetachedXadesSignatureBuilder withSignatureDigestAlgorithm(DigestAlgorithm digestAlgorithm) { - signatureParameters.setDigestAlgorithm(digestAlgorithm); + signatureParameters.setSignatureDigestAlgorithm(digestAlgorithm); + return this; + } + + + /** + * Set signature digest algorithm used to generate a signature. + * + * @param digestAlgorithm signature digest algorithm. + * @return builder for creating a signature. + */ + public DetachedXadesSignatureBuilder withDataFileDigestAlgorithm(DigestAlgorithm digestAlgorithm) { + signatureParameters.setDataFileDigestAlgorithm(digestAlgorithm); return this; } @@ -278,7 +292,7 @@ protected Signature invokeSigningProcess() { Signature result = null; byte[] signatureValue = null; try { - signatureValue = signatureToken.sign(signatureParameters.getDigestAlgorithm(), dataToSign); + signatureValue = signatureToken.sign(signatureParameters.getSignatureDigestAlgorithm(), dataToSign); result = finalizeSignature(signatureValue); } catch (TechnicalException e) { String dataToSignHex = Helper.bytesToHex(dataToSign, AsicSignatureFinalizer.HEX_MAX_LENGTH); @@ -305,15 +319,31 @@ private SignatureFinalizer getSignatureFinalizer() { } private void populateSignatureParameters() { - populateDigestAlgorithm(); populateEncryptionAlgorithm(); + populateSignatureDigestAlgorithm(); + populateDataFileDigestAlgorithm(); populateSignatureProfile(); } - private void populateDigestAlgorithm() { - if (signatureParameters.getDigestAlgorithm() == null) { - signatureParameters.setDigestAlgorithm(configuration.getSignatureDigestAlgorithm()); + private void populateSignatureDigestAlgorithm() { + if (signatureParameters.getSignatureDigestAlgorithm() == null) { + DigestAlgorithm digestAlgorithm = configuration.getSignatureDigestAlgorithm(); + signatureParameters.setSignatureDigestAlgorithm(digestAlgorithm != null ? digestAlgorithm : getDefaultSignatureDigestAlgorithm()); + } + } + + private void populateDataFileDigestAlgorithm() { + if (signatureParameters.getDataFileDigestAlgorithm() == null) { + DigestAlgorithm digestAlgorithm = configuration.getDataFileDigestAlgorithm(); + signatureParameters.setDataFileDigestAlgorithm(digestAlgorithm != null ? digestAlgorithm : Constant.Default.DATAFILE_DIGEST_ALGORITHM); + } + } + + private DigestAlgorithm getDefaultSignatureDigestAlgorithm() { + if (signatureParameters.getEncryptionAlgorithm() == EncryptionAlgorithm.ECDSA) { + return DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) signatureParameters.getSigningCertificate().getPublicKey()); } + return Constant.Default.SIGNATURE_DIGEST_ALGORITHM; } private void populateEncryptionAlgorithm() { @@ -327,7 +357,8 @@ private void populateEncryptionAlgorithm() { private void populateSignatureProfile() { if (signatureParameters.getSignatureProfile() == null) { - signatureParameters.setSignatureProfile(configuration.getSignatureProfile()); + SignatureProfile signatureProfile = configuration.getSignatureProfile(); + signatureParameters.setSignatureProfile(signatureProfile != null ? signatureProfile : Constant.Default.SIGNATURE_PROFILE); } } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/DigestAlgorithm.java b/digidoc4j/src/main/java/org/digidoc4j/DigestAlgorithm.java index 9f6df2fea..1007038f1 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DigestAlgorithm.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DigestAlgorithm.java @@ -1,19 +1,19 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; import java.net.MalformedURLException; import java.net.URL; -import org.digidoc4j.exceptions.DigiDoc4JException; +import org.digidoc4j.exceptions.TechnicalException; /** * Supported algorithms @@ -30,16 +30,12 @@ public enum DigestAlgorithm { SHA512("http://www.w3.org/2001/04/xmlenc#sha512", new byte[]{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte) 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}); - private URL uri; - private byte[] digestInfoPrefix; + private final URL uri; + private final byte[] digestInfoPrefix; DigestAlgorithm(String uri, byte[] digestInfoPrefix) { - try { - this.uri = new URL(uri); + this.uri = toDigestAlgorithmUri(uri); this.digestInfoPrefix = digestInfoPrefix; - } catch (MalformedURLException e) { - throw new DigiDoc4JException(e); - } } /** @@ -83,4 +79,29 @@ public static DigestAlgorithm findByAlgorithm(String algorithm) { return null; } + /** + * Obtain digest algorithm URI from DSS digest algorithm. + * + * @param digestAlgorithm DSS digest algorithm + * + * @return URI of the digest algorithm + * + * @throws TechnicalException if there is no URI specified for the algorithm + */ + public static URL getDigestAlgorithmUri(eu.europa.esig.dss.enumerations.DigestAlgorithm digestAlgorithm) { + if (digestAlgorithm.getUri() != null) { + return toDigestAlgorithmUri(digestAlgorithm.getUri()); + } else { + throw new TechnicalException("No digest algorithm URI specified for " + digestAlgorithm.getName()); + } + } + + private static URL toDigestAlgorithmUri(String uriString) { + try { + return new URL(uriString); + } catch (MalformedURLException e) { + throw new TechnicalException("Invalid digest algorithm URI: " + uriString, e); + } + } + } diff --git a/digidoc4j/src/main/java/org/digidoc4j/DigestDataFile.java b/digidoc4j/src/main/java/org/digidoc4j/DigestDataFile.java index 3b624f798..51d390807 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/DigestDataFile.java +++ b/digidoc4j/src/main/java/org/digidoc4j/DigestDataFile.java @@ -30,21 +30,6 @@ public DigestDataFile(String fileName, DigestAlgorithm digestAlgorithm, byte[] d setDigestDataFile(fileName, digestAlgorithm, digest, getMimeType(mimeType)); } - /** - * Creates digest based data file. - * In other words only the content's digest (not the content itself) is provided. - * - * @param fileName name of the file - * @param digestAlgorithm algorithm of the digest - * @param digest digest of the file contents - * @deprecated use DigestDataFile(String fileName, DigestAlgorithm digestAlgorithm, byte[] digest, String mimeType) - * https://github.com/open-eid/digidoc4j/wiki/Examples-of-using-it#detached-xades-containerless-signature-handling - */ - @Deprecated - public DigestDataFile(String fileName, DigestAlgorithm digestAlgorithm, byte[] digest) { - setDigestDataFile(fileName, digestAlgorithm, digest, null); - } - private void setDigestDataFile(String fileName, DigestAlgorithm digestAlgorithm, byte[] digest, MimeType mimeType) { logger.debug("File name: " + fileName + ", digest algorithm: " + digestAlgorithm + ", digest: " + Arrays.toString(digest)); diff --git a/digidoc4j/src/main/java/org/digidoc4j/ExternalConnectionType.java b/digidoc4j/src/main/java/org/digidoc4j/ExternalConnectionType.java index 31fcf0405..5bf7594fd 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/ExternalConnectionType.java +++ b/digidoc4j/src/main/java/org/digidoc4j/ExternalConnectionType.java @@ -2,9 +2,9 @@ import org.apache.commons.lang3.tuple.Pair; -import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.digidoc4j.ConfigurationParameter.*; @@ -13,10 +13,12 @@ public enum ExternalConnectionType { TSL( Pair.of(HttpProxyHost, TslHttpProxyHost), Pair.of(HttpProxyPort, TslHttpProxyPort), - Pair.of(HttpsProxyHost, TslHttpsProxyHost), - Pair.of(HttpsProxyPort, TslHttpsProxyPort), Pair.of(HttpProxyUser, TslHttpProxyUser), Pair.of(HttpProxyPassword, TslHttpProxyPassword), + Pair.of(HttpsProxyHost, TslHttpsProxyHost), + Pair.of(HttpsProxyPort, TslHttpsProxyPort), + Pair.of(HttpsProxyUser, TslHttpsProxyUser), + Pair.of(HttpsProxyPassword, TslHttpsProxyPassword), Pair.of(SslKeystoreType, TslSslKeystoreType), Pair.of(SslTruststoreType, TslSslTruststoreType), Pair.of(SslKeystorePath, TslSslKeystorePath), @@ -31,10 +33,12 @@ public enum ExternalConnectionType { OCSP( Pair.of(HttpProxyHost, OcspHttpProxyHost), Pair.of(HttpProxyPort, OcspHttpProxyPort), - Pair.of(HttpsProxyHost, OcspHttpsProxyHost), - Pair.of(HttpsProxyPort, OcspHttpsProxyPort), Pair.of(HttpProxyUser, OcspHttpProxyUser), Pair.of(HttpProxyPassword, OcspHttpProxyPassword), + Pair.of(HttpsProxyHost, OcspHttpsProxyHost), + Pair.of(HttpsProxyPort, OcspHttpsProxyPort), + Pair.of(HttpsProxyUser, OcspHttpsProxyUser), + Pair.of(HttpsProxyPassword, OcspHttpsProxyPassword), Pair.of(SslKeystoreType, OcspSslKeystoreType), Pair.of(SslTruststoreType, OcspSslTruststoreType), Pair.of(SslKeystorePath, OcspSslKeystorePath), @@ -49,10 +53,12 @@ public enum ExternalConnectionType { TSP( Pair.of(HttpProxyHost, TspHttpProxyHost), Pair.of(HttpProxyPort, TspHttpProxyPort), - Pair.of(HttpsProxyHost, TspHttpsProxyHost), - Pair.of(HttpsProxyPort, TspHttpsProxyPort), Pair.of(HttpProxyUser, TspHttpProxyUser), Pair.of(HttpProxyPassword, TspHttpProxyPassword), + Pair.of(HttpsProxyHost, TspHttpsProxyHost), + Pair.of(HttpsProxyPort, TspHttpsProxyPort), + Pair.of(HttpsProxyUser, TspHttpsProxyUser), + Pair.of(HttpsProxyPassword, TspHttpsProxyPassword), Pair.of(SslKeystoreType, TspSslKeystoreType), Pair.of(SslTruststoreType, TspSslTruststoreType), Pair.of(SslKeystorePath, TspSslKeystorePath), @@ -66,8 +72,10 @@ public enum ExternalConnectionType { private final Map genericToSpecificParameterMap; + @SafeVarargs ExternalConnectionType(Pair... parameterMappings) { - genericToSpecificParameterMap = Arrays.stream(parameterMappings).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + genericToSpecificParameterMap = Stream.of(parameterMappings) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } ConfigurationParameter mapToSpecificParameter(ConfigurationParameter genericParameter) { diff --git a/digidoc4j/src/main/java/org/digidoc4j/Signature.java b/digidoc4j/src/main/java/org/digidoc4j/Signature.java index f1af18905..6d587c9a9 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/Signature.java +++ b/digidoc4j/src/main/java/org/digidoc4j/Signature.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -14,8 +14,6 @@ import java.util.Date; import java.util.List; -import org.digidoc4j.exceptions.DigiDoc4JException; - /** * Signature interface. Provides an interface for handling a signature and the corresponding OCSP response properties. */ @@ -64,17 +62,6 @@ public interface Signature extends Serializable { */ X509Cert getOCSPCertificate(); - /** - * If the container is DDOC then it returns an empty string. - *

    - * For a BDOC Signature it throws a NotYetImplementedException. - * - * @return signature policy - * @deprecated will be removed in the future - */ - @Deprecated - String getPolicy(); - /** * Returns the signature production postal code. * @@ -82,15 +69,6 @@ public interface Signature extends Serializable { */ String getPostalCode(); - /** - * Returns the signature OCSP producedAt timestamp. - * - * @return producedAt timestamp - * @deprecated use {@link Signature#getOCSPResponseCreationTime()} instead. Will be removed in the future. - */ - @Deprecated - Date getProducedAt(); - /** * Returns the signature OCSP producedAt timestamp. * @@ -154,25 +132,6 @@ public interface Signature extends Serializable { */ Date getClaimedSigningTime(); - /** - * Returns the computer's time of signing. - * - * @return signing time - * @deprecated use {@link Signature#getClaimedSigningTime()} instead. Will be removed in the future. - */ - @Deprecated - Date getSigningTime(); - - /** - * If the container is DDoc then it returns an empty string. - * For a BDOC Signature it throws a NotYetImplementedException. - * - * @return signature policy uri - * @deprecated will be removed in the future - */ - @Deprecated - java.net.URI getSignaturePolicyURI(); - /** * Returns the signature production state or province. * @@ -195,26 +154,10 @@ public interface Signature extends Serializable { */ ValidationResult validateSignature(); - /** - * Validates the signature. - * - * @return list of Digidoc4JExceptions - * @deprecated use {@link Signature#validateSignature()} instead. - */ - @Deprecated - List validate(); - /** * Returns signature as XAdES XML * * @return signature as byte array */ byte[] getAdESSignature(); - - /** - * @return signature as byte array - * @deprecated use {@link Signature#getAdESSignature()} instead. - */ - @Deprecated - byte[] getRawSignature(); } diff --git a/digidoc4j/src/main/java/org/digidoc4j/SignatureBuilder.java b/digidoc4j/src/main/java/org/digidoc4j/SignatureBuilder.java index ccc8452f1..3523a3c25 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/SignatureBuilder.java +++ b/digidoc4j/src/main/java/org/digidoc4j/SignatureBuilder.java @@ -257,7 +257,19 @@ public SignatureBuilder withRoles(String... roles) { * @return builder for creating a signature. */ public SignatureBuilder withSignatureDigestAlgorithm(DigestAlgorithm digestAlgorithm) { - signatureParameters.setDigestAlgorithm(digestAlgorithm); + signatureParameters.setSignatureDigestAlgorithm(digestAlgorithm); + return this; + } + + + /** + * Set data file digest algorithm. + * + * @param digestAlgorithm datafile digest algorithm. + * @return builder for creating a signature. + */ + public SignatureBuilder withDataFileDigestAlgorithm(DigestAlgorithm digestAlgorithm) { + signatureParameters.setDataFileDigestAlgorithm(digestAlgorithm); return this; } diff --git a/digidoc4j/src/main/java/org/digidoc4j/SignatureParameters.java b/digidoc4j/src/main/java/org/digidoc4j/SignatureParameters.java index d3bc9cdb5..6a26e9686 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/SignatureParameters.java +++ b/digidoc4j/src/main/java/org/digidoc4j/SignatureParameters.java @@ -45,7 +45,8 @@ public class SignatureParameters implements Serializable { private SignatureProductionPlace productionPlace = new SignatureProductionPlace(); private List roles = new ArrayList<>(); private String signatureId; - private DigestAlgorithm digestAlgorithm; + private DigestAlgorithm dataFileDigestAlgorithm; + private DigestAlgorithm signatureDigestAlgorithm; private EncryptionAlgorithm encryptionAlgorithm; private SignatureProfile signatureProfile; private X509Certificate signingCertificate; @@ -142,21 +143,40 @@ public String getSignatureId() { } /** - * Sets container digest type + * Sets signature digest type * - * @param algorithm digest algorithm + * @param algorithm signature digest algorithm */ - public void setDigestAlgorithm(DigestAlgorithm algorithm) { - digestAlgorithm = algorithm; + public void setSignatureDigestAlgorithm(DigestAlgorithm algorithm) { + signatureDigestAlgorithm = algorithm; } /** - * Gets container digest type + * Gets signature digest type * - * @return container digest algorithm + * @return signature digest algorithm */ - public DigestAlgorithm getDigestAlgorithm() { - return digestAlgorithm; + public DigestAlgorithm getSignatureDigestAlgorithm() { + return signatureDigestAlgorithm; + } + + + /** + * Sets data file digest type + * + * @param algorithm data file digest algorithm + */ + public void setDataFileDigestAlgorithm(DigestAlgorithm algorithm) { + dataFileDigestAlgorithm = algorithm; + } + + /** + * Gets data file digest type + * + * @return data file digest algorithm + */ + public DigestAlgorithm getDataFileDigestAlgorithm() { + return dataFileDigestAlgorithm; } /** diff --git a/digidoc4j/src/main/java/org/digidoc4j/SignedInfo.java b/digidoc4j/src/main/java/org/digidoc4j/SignedInfo.java index f3cd49844..cde0a214b 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/SignedInfo.java +++ b/digidoc4j/src/main/java/org/digidoc4j/SignedInfo.java @@ -29,7 +29,7 @@ public SignedInfo() { } public SignedInfo(byte[] dataToDigest, SignatureParameters signatureParameters) { - DigestAlgorithm digestAlgorithm = signatureParameters.getDigestAlgorithm(); + DigestAlgorithm digestAlgorithm = signatureParameters.getSignatureDigestAlgorithm(); digestToSign = DSSUtils.digest(forXML(digestAlgorithm.toString()), dataToDigest); this.signatureParameters = signatureParameters; } @@ -43,7 +43,7 @@ public byte[] getDigestToSign() { } public DigestAlgorithm getDigestAlgorithm() { - return signatureParameters.getDigestAlgorithm(); + return signatureParameters.getSignatureDigestAlgorithm(); } public SignatureParameters getSignatureParameters() { diff --git a/digidoc4j/src/main/java/org/digidoc4j/Signer.java b/digidoc4j/src/main/java/org/digidoc4j/Signer.java deleted file mode 100644 index a0a80085a..000000000 --- a/digidoc4j/src/main/java/org/digidoc4j/Signer.java +++ /dev/null @@ -1,20 +0,0 @@ -/* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ - -package org.digidoc4j; - -/** - * This interface has been renamed to SignatureToken. Use {@link SignatureToken} instead. - * @deprecated - * @see SignatureToken - */ -@Deprecated -public interface Signer extends SignatureToken{ -} diff --git a/digidoc4j/src/main/java/org/digidoc4j/TSLRefreshCallback.java b/digidoc4j/src/main/java/org/digidoc4j/TSLRefreshCallback.java new file mode 100644 index 000000000..820d6fdb4 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/TSLRefreshCallback.java @@ -0,0 +1,42 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j; + +import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; + +import java.io.Serializable; + +/** + * A callback for ensuring the state of the TSL after a refresh. + * The callback is encouraged to throw an exception, if the TSL is not usable, + * in order to stop the processes early that triggered the TSL refresh. + */ +@FunctionalInterface +public interface TSLRefreshCallback extends Serializable { + + /** + * Ensures the state of the TSL and either:

      + *
    • throws an appropriate exception if the TSL is not in a usable state + * and the process that triggered the TSL refresh may not continue
    • + *
    • returns {@code false}, if the process that triggered the TSL refresh may continue, + * but the time of the TSL refresh must not be updated - the TSL is marked as expired
    • + *
    • returns {@code true}, if the TSL is good and the time of the TSL refresh must be + * updated - the next automatic TSL refresh will not be triggered before the next expiration + * period is over (see {@link Configuration#setTslCacheExpirationTime(long)})
    • + *
    + * + * @param summary the information about the state of the TSL + * + * @return {@code true} if the TSL refresh time must be updated, {@code false} otherwise + */ + boolean ensureTSLState(TLValidationJobSummary summary); + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/LotlTrustStoreNotFoundException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/LotlTrustStoreNotFoundException.java new file mode 100644 index 000000000..813d9b08e --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/exceptions/LotlTrustStoreNotFoundException.java @@ -0,0 +1,9 @@ +package org.digidoc4j.exceptions; + +public class LotlTrustStoreNotFoundException extends DigiDoc4JException { + + public LotlTrustStoreNotFoundException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslDownloadException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslDownloadException.java new file mode 100644 index 000000000..624a71100 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslDownloadException.java @@ -0,0 +1,37 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.exceptions; + +/** + * An exception signalling a TSL download error. + */ +public class TslDownloadException extends TslRefreshException { + + /** + * Constructs a new TSL download exception with the specified detail message. + * + * @param message the detail message + */ + public TslDownloadException(String message) { + super(message); + } + + /** + * Constructs a new TSL download exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause of this exception + */ + public TslDownloadException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslKeyStoreNotFoundException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslKeyStoreNotFoundException.java deleted file mode 100644 index 5a983c7ad..000000000 --- a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslKeyStoreNotFoundException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.digidoc4j.exceptions; - -public class TslKeyStoreNotFoundException extends DigiDoc4JException { - - public TslKeyStoreNotFoundException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslParsingException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslParsingException.java new file mode 100644 index 000000000..b3aebb389 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslParsingException.java @@ -0,0 +1,37 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.exceptions; + +/** + * An exception signalling a TSL parsing exception. + */ +public class TslParsingException extends TslRefreshException { + + /** + * Constructs a new TSL parsing exception with the specified detail message. + * + * @param message the detail message + */ + public TslParsingException(String message) { + super(message); + } + + /** + * Constructs a new TSL parsing exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause of this exception + */ + public TslParsingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslRefreshException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslRefreshException.java new file mode 100644 index 000000000..c3359fb28 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslRefreshException.java @@ -0,0 +1,37 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.exceptions; + +/** + * An exception signalling a TSL refresh error. + */ +public class TslRefreshException extends TechnicalException { + + /** + * Constructs a new TSL refresh exception with the specified detail message. + * + * @param message the detail message + */ + public TslRefreshException(String message) { + super(message); + } + + /** + * Constructs a new TSL refresh exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause of this exception + */ + public TslRefreshException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslValidationException.java b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslValidationException.java new file mode 100644 index 000000000..08b54f9cf --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/exceptions/TslValidationException.java @@ -0,0 +1,37 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.exceptions; + +/** + * An exception signalling a TSL validation error. + */ +public class TslValidationException extends TslRefreshException { + + /** + * Constructs a new TSL validation exception with the specified detail message. + * + * @param message the detail message + */ + public TslValidationException(String message) { + super(message); + } + + /** + * Constructs a new TSL validation exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause of this exception + */ + public TslValidationException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/StreamDocument.java b/digidoc4j/src/main/java/org/digidoc4j/impl/StreamDocument.java index fc5a66c40..b6895eab4 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/StreamDocument.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/StreamDocument.java @@ -1,23 +1,19 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl; import eu.europa.esig.dss.model.CommonDocument; import eu.europa.esig.dss.model.DSSException; -import eu.europa.esig.dss.spi.DSSUtils; -import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.model.MimeType; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +32,8 @@ public class StreamDocument extends CommonDocument { private static final Logger logger = LoggerFactory.getLogger(StreamDocument.class); private static final int MAX_SIZE_IN_MEMORY = 1024 * 5; - File temporaryFile; + + protected final File temporaryFile; //TODO if file is small enough you can read it into byte[] and cache it @@ -49,30 +46,31 @@ public class StreamDocument extends CommonDocument { */ public StreamDocument(InputStream stream, String documentName, MimeType mimeType) { logger.debug("Document name: " + documentName + ", mime type: " + mimeType); - createTemporaryFileOfStream(stream); + this.temporaryFile = createTemporaryFileOfStream(stream); super.name = documentName; super.mimeType = mimeType; } - private void createTemporaryFileOfStream(InputStream stream) { - byte[] bytes = new byte[MAX_SIZE_IN_MEMORY]; - - FileOutputStream out = null; - + private static File createTemporaryFileOfStream(InputStream stream) { try { + File temporaryFile; temporaryFile = File.createTempFile("digidoc4j", ".tmp"); - out = new FileOutputStream(temporaryFile); - int result; - while ((result = stream.read(bytes)) > 0) { - out.write(bytes, 0, result); - } - out.flush(); temporaryFile.deleteOnExit(); + + try (FileOutputStream out = new FileOutputStream(temporaryFile)) { + byte[] bytes = new byte[MAX_SIZE_IN_MEMORY]; + int result; + + while ((result = stream.read(bytes)) > 0) { + out.write(bytes, 0, result); + } + out.flush(); + } + + return temporaryFile; } catch (IOException e) { logger.error(e.getMessage()); throw new DSSException(e); - } finally { - IOUtils.closeQuietly(out); } } @@ -91,11 +89,6 @@ public InputStream openStream() throws DSSException { public void setName(String s) { } - @Override - public String getAbsolutePath() { - return temporaryFile.getAbsolutePath(); - } - @Override public MimeType getMimeType() { MimeType mimeType = super.getMimeType(); @@ -109,33 +102,8 @@ public void setMimeType(MimeType mimeType) { super.setMimeType(mimeType); } - @Override - public void save(String filePath) { - logger.debug("File Path: " + filePath); - try { - FileOutputStream fileOutputStream = new FileOutputStream(filePath); - try { - IOUtils.copy(getTemporaryFileAsStream(), fileOutputStream); - } finally { - fileOutputStream.close(); - } - } catch (IOException e) { - logger.error(e.getMessage()); - throw new DSSException(e); - } - } - - @Override - public String getDigest(DigestAlgorithm digestAlgorithm) { - logger.debug("Digest algorithm: " + digestAlgorithm); - byte[] digestBytes; - try { - digestBytes = DSSUtils.digest(digestAlgorithm, getTemporaryFileAsStream()); - } catch (FileNotFoundException e) { - logger.error(e.getMessage()); - throw new DSSException(e); - } - return Base64.encodeBase64String(digestBytes); + public Long getStreamLengthIfKnown() { + return temporaryFile.length(); } protected FileInputStream getTemporaryFileAsStream() throws FileNotFoundException { diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainer.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainer.java index 59a0a9d83..a4a721f17 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainer.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainer.java @@ -12,26 +12,18 @@ import eu.europa.esig.dss.model.DSSDocument; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.digidoc4j.Configuration; import org.digidoc4j.Constant; import org.digidoc4j.Container; import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.DataFile; -import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.Signature; -import org.digidoc4j.SignatureBuilder; -import org.digidoc4j.SignatureParameters; import org.digidoc4j.SignatureProfile; -import org.digidoc4j.SignatureToken; -import org.digidoc4j.SignedInfo; import org.digidoc4j.exceptions.DataFileNotFoundException; import org.digidoc4j.exceptions.DigiDoc4JException; import org.digidoc4j.exceptions.DuplicateDataFileException; import org.digidoc4j.exceptions.InvalidDataFileException; -import org.digidoc4j.exceptions.InvalidSignatureException; -import org.digidoc4j.exceptions.NotSupportedException; import org.digidoc4j.exceptions.RemovingDataFileException; import org.digidoc4j.exceptions.SignatureNotFoundException; import org.digidoc4j.exceptions.TechnicalException; @@ -57,7 +49,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -549,38 +540,6 @@ public void removeSignature(Signature signature) { } } - @Override - @Deprecated - public void removeSignature(int signatureId) { - LOGGER.debug("Removing signature from index " + signatureId); - if (signatureId >= 0 && signatureId < signatures.size()) { - Signature signature = signatures.get(signatureId); - if (signature != null) { - removeSignature(signature); - } - } - throw new SignatureNotFoundException(String.format("Signature from index %d not found", signatureId)); - } - - @Override - public void removeDataFile(String fileName) { - validateDataFilesRemoval(); - - for (DataFile dataFile : dataFiles) { - String name = dataFile.getName(); - if (StringUtils.equals(fileName, name)) { - removeDataFileFromContainer(dataFile); - dataFilesHaveChanged = true; - if (!isNewContainer()) { - removeExistingFileFromContainer(AsicManifest.XML_PATH); - } - LOGGER.info("Data file named '{}' has been removed", fileName); - return; - } - } - throw new DataFileNotFoundException(fileName); - } - @Override public void removeDataFile(DataFile file) { validateDataFilesRemoval(); @@ -644,159 +603,6 @@ protected void writeAsicContainer(AsicContainerCreator zipCreator) { zipCreator.finalizeZipFile(); } - //=============== Deprecated methods ==================== - - @Override - @Deprecated - public void addRawSignature(byte[] signatureDocument) { - LOGGER.info("Adding raw signature"); - Signature signature = SignatureBuilder. - aSignature(this). - openAdESSignature(signatureDocument); - addSignature(signature); - } - - @Override - @Deprecated - public void addRawSignature(InputStream signatureStream) { - try { - byte[] bytes = IOUtils.toByteArray(signatureStream); - addRawSignature(bytes); - } catch (IOException e) { - LOGGER.error("Failed to read signature stream: " + e.getMessage()); - throw new InvalidSignatureException(); - } - } - - @Override - @Deprecated - public int countDataFiles() { - return getDataFiles().size(); - } - - @Override - @Deprecated - public int countSignatures() { - return getSignatures().size(); - } - - @Override - @Deprecated - public DocumentType getDocumentType() { - return Container.DocumentType.BDOC; - } - - @Override - @Deprecated - public String getVersion() { - return ""; - } - - @Override - @Deprecated - public void extendTo(SignatureProfile profile) { - extendSignatureProfile(profile); - } - - @Override - @Deprecated - public void save(String path) { - saveAsFile(path); - } - - @Override - @Deprecated - public DataFile getDataFile(int index) { - return getDataFiles().get(index); - } - - @Override - @Deprecated - public Signature getSignature(int index) { - return getSignatures().get(index); - } - - /** - * Prepare signing method is not supported by ASiC container. - * - * @param signerCert X509 Certificate to be used for preparing the signature - * @return NotSupportedException - */ - - @Override - @Deprecated - public SignedInfo prepareSigning(X509Certificate signerCert) { - throw new NotSupportedException("Prepare signing method is not supported by Asic container"); - } - - /** - * Getting signature profile method is not supported by ASiC container. - * - * @return NotSupportedException - */ - @Override - @Deprecated - public String getSignatureProfile() { - throw new NotSupportedException("Getting signature profile method is not supported by Asic container"); - } - - /** - * Setting signature parameters method is not supported by ASiC container - * - * @param signatureParameters Signature parameters. These are related to the signing location and signer roles - */ - @Override - @Deprecated - public void setSignatureParameters(SignatureParameters signatureParameters) { - throw new NotSupportedException("Setting signature parameters method is not supported by Asic container"); - } - - /** - * Getting digest algorithm method is not supported by ASiC container. - * - * @return NotSupportedException. - */ - @Override - @Deprecated - public DigestAlgorithm getDigestAlgorithm() { - throw new NotSupportedException("Getting digest algorithm method is not supported by Asic container"); - } - - /** - * Sign method is not supported by ASiC container. - * - * @param signatureToken signatureToken implementation - * @return NotSupportedException - */ - @Override - @Deprecated - public Signature sign(SignatureToken signatureToken) { - throw new NotSupportedException("Sign method is not supported by Asic container"); - } - - /** - * Sign raw method is not supported by ASiC container. - * - * @param rawSignature raw signature - * @return NotSupportedException - */ - @Override - @Deprecated - public Signature signRaw(byte[] rawSignature) { - throw new NotSupportedException("Sign raw method is not supported by Asic container"); - } - - /** - * Setting signature profile method is not supported by ASiC container. - * - * @param profile signature profile - */ - @Override - @Deprecated - public void setSignatureProfile(SignatureProfile profile) { - throw new NotSupportedException("Setting signature profile method is not supported by Asic container"); - } - public AsicParseResult getContainerParseResult() { return containerParseResult; } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainerCreator.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainerCreator.java index 1bdc89173..063a930b9 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainerCreator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainerCreator.java @@ -1,41 +1,37 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.asic; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.zip.CRC32; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - +import eu.europa.esig.dss.model.DSSDocument; +import eu.europa.esig.dss.model.MimeType; import org.apache.commons.io.IOUtils; import org.digidoc4j.Configuration; import org.digidoc4j.Constant; import org.digidoc4j.DataFile; import org.digidoc4j.Signature; -import org.digidoc4j.exceptions.NotSupportedException; import org.digidoc4j.exceptions.TechnicalException; import org.digidoc4j.impl.asic.manifest.AsicManifest; import org.digidoc4j.utils.Helper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.europa.esig.dss.model.DSSDocument; -import eu.europa.esig.dss.model.MimeType; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * ASIC container creator @@ -73,15 +69,6 @@ public void finalizeZipFile() { } } - @Deprecated - public InputStream fetchInputStreamOfFinalizedContainer() { - if (outputStream instanceof ByteArrayOutputStream) { - logger.debug("Fetching input stream of the finalized container"); - return new ByteArrayInputStream(((ByteArrayOutputStream) outputStream).toByteArray()); - } - throw new NotSupportedException("instance not backed by an in-memory stream"); - } - /** * @param containerType type */ @@ -146,7 +133,7 @@ public void writeSignatures(Collection signatures, int nextSignatureF public void writeTimestampToken(DataFile dataFile) { logger.debug("Adding signatures to the asic zip container"); String signatureFileName = "META-INF/timestamp.tst"; - new BytesEntryCallback(new ZipEntry(signatureFileName), dataFile.getBytes()).write(); + new StreamEntryCallback(new ZipEntry(signatureFileName), dataFile.getStream()).write(); } /** @@ -193,7 +180,9 @@ private class StreamEntryCallback extends EntryCallback { @Override void doWithEntryStream(OutputStream stream) throws IOException { - IOUtils.copy(inputStream, stream); + try (InputStream in = inputStream) { + IOUtils.copy(in, stream); + } } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignature.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignature.java index 17282481c..ca8417220 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignature.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignature.java @@ -1,18 +1,23 @@ -package org.digidoc4j.impl.asic; +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ -import java.io.IOException; -import java.net.URI; -import java.util.Date; -import java.util.List; +package org.digidoc4j.impl.asic; +import eu.europa.esig.dss.enumerations.DigestAlgorithm; +import eu.europa.esig.dss.model.DSSDocument; import org.apache.commons.io.IOUtils; import org.digidoc4j.Configuration; import org.digidoc4j.Signature; import org.digidoc4j.SignatureProfile; import org.digidoc4j.ValidationResult; import org.digidoc4j.X509Cert; -import org.digidoc4j.exceptions.DigiDoc4JException; -import org.digidoc4j.exceptions.NotYetImplementedException; import org.digidoc4j.exceptions.TechnicalException; import org.digidoc4j.impl.asic.xades.XadesSignature; import org.digidoc4j.impl.asic.xades.validation.SignatureValidator; @@ -20,8 +25,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.europa.esig.dss.model.DSSDocument; -import eu.europa.esig.dss.enumerations.DigestAlgorithm; +import java.io.IOException; +import java.util.Date; +import java.util.List; /** * Created by Andrei on 29.11.2017. @@ -76,12 +82,6 @@ public X509Cert getOCSPCertificate() { return xadesSignature.getOCSPCertificate(); } - @Override - @Deprecated - public String getPolicy() { - throw new NotYetImplementedException(); - } - @Override public String getPostalCode() { return xadesSignature.getPostalCode(); @@ -98,17 +98,6 @@ public Date getOCSPResponseCreationTime() { return xadesSignature.getOCSPResponseCreationTime(); } - /** - * This method returns Date object, it can be null. - * - * @return Date - */ - @Override - @Deprecated - public Date getProducedAt() { - return getOCSPResponseCreationTime(); - } - @Override public Date getTimeStampCreationTime() { return xadesSignature.getTimeStampCreationTime(); @@ -157,30 +146,6 @@ public Date getClaimedSigningTime() { return xadesSignature.getSigningTime(); } - /** - * Gets signing time depending on the signature profile. - * - * @return Date - */ - @Override - public Date getSigningTime() { - logger.debug("get signing time by profile: " + getProfile()); - switch (getProfile()) { - case B_BES: - return getClaimedSigningTime(); - case B_EPES: - return getClaimedSigningTime(); - default: - return getTrustedSigningTime(); - } - } - - @Override - @Deprecated - public URI getSignaturePolicyURI() { - throw new NotYetImplementedException(); - } - @Override public String getStateOrProvince() { return xadesSignature.getStateOrProvince(); @@ -205,12 +170,6 @@ public ValidationResult validateSignature() { return validationResult; } - @Override - @Deprecated - public List validate() { - return validateSignature().getErrors(); - } - @Override public byte[] getAdESSignature() { logger.debug("Getting full XAdES signature byte array"); @@ -221,12 +180,6 @@ public byte[] getAdESSignature() { } } - @Override - @Deprecated - public byte[] getRawSignature() { - return getAdESSignature(); - } - /** * This method returns XadesSignature object. * diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureBuilder.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureBuilder.java index 22fec3227..7a9e7fece 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureBuilder.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureBuilder.java @@ -1,32 +1,38 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.asic; import eu.europa.esig.dss.model.InMemoryDocument; import org.digidoc4j.Configuration; +import org.digidoc4j.Constant; import org.digidoc4j.DataToSign; +import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.EncryptionAlgorithm; import org.digidoc4j.Signature; import org.digidoc4j.SignatureBuilder; import org.digidoc4j.SignatureFinalizerBuilder; +import org.digidoc4j.SignatureProfile; import org.digidoc4j.exceptions.ContainerWithoutFilesException; import org.digidoc4j.exceptions.InvalidSignatureException; import org.digidoc4j.exceptions.SignerCertificateRequiredException; import org.digidoc4j.exceptions.TechnicalException; import org.digidoc4j.impl.SignatureFinalizer; import org.digidoc4j.utils.CertificateUtils; +import org.digidoc4j.utils.DigestUtils; import org.digidoc4j.utils.Helper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.security.interfaces.ECPublicKey; + /** * Signature builder for Asic container. */ @@ -42,8 +48,8 @@ protected Signature invokeSigningProcess() { byte[] dataToSign = getSignatureFinalizer().getDataToBeSigned(); byte[] signatureValue = null; try { - signatureValue = signatureToken.sign(signatureParameters.getDigestAlgorithm(), dataToSign); - return finalizeSignature(signatureValue); + signatureValue = signatureToken.sign(signatureParameters.getSignatureDigestAlgorithm(), dataToSign); + return getSignatureFinalizer().finalizeSignature(signatureValue); } catch (TechnicalException e) { String dataToSignHex = Helper.bytesToHex(dataToSign, AsicSignatureFinalizer.HEX_MAX_LENGTH); String signatureValueHex = signatureValue == null ? null : Helper.bytesToHex(signatureValue, AsicSignatureFinalizer.HEX_MAX_LENGTH); @@ -70,14 +76,6 @@ public Signature openAdESSignature(byte[] signatureDocument) { return getSignatureFinalizer().createSignature(document); } - /** - * @deprecated use {@link SignatureBuilder#invokeSigningProcess()} or {@link SignatureFinalizer#finalizeSignature(byte[] signatureValue)} instead. - */ - @Deprecated - public Signature finalizeSignature(byte[] signatureValue) { - return getSignatureFinalizer().finalizeSignature(signatureValue); - } - public Configuration getConfiguration() { return container.getConfiguration(); } @@ -91,15 +89,31 @@ private SignatureFinalizer getSignatureFinalizer() { } private void populateSignatureParameters() { - populateDigestAlgorithm(); populateEncryptionAlgorithm(); + populateSignatureDigestAlgorithm(); + populateDataFileDigestAlgorithm(); populateSignatureProfile(); } - private void populateDigestAlgorithm() { - if (signatureParameters.getDigestAlgorithm() == null) { - signatureParameters.setDigestAlgorithm(getConfiguration().getSignatureDigestAlgorithm()); + private void populateSignatureDigestAlgorithm() { + if (signatureParameters.getSignatureDigestAlgorithm() == null) { + DigestAlgorithm digestAlgorithm = getConfiguration().getSignatureDigestAlgorithm(); + signatureParameters.setSignatureDigestAlgorithm(digestAlgorithm != null ? digestAlgorithm : getDefaultSignatureDigestAlgorithm()); + } + } + + private void populateDataFileDigestAlgorithm() { + if (signatureParameters.getDataFileDigestAlgorithm() == null) { + DigestAlgorithm digestAlgorithm = getConfiguration().getDataFileDigestAlgorithm(); + signatureParameters.setDataFileDigestAlgorithm(digestAlgorithm != null ? digestAlgorithm : Constant.Default.DATAFILE_DIGEST_ALGORITHM); + } + } + + private DigestAlgorithm getDefaultSignatureDigestAlgorithm() { + if (signatureParameters.getEncryptionAlgorithm() == EncryptionAlgorithm.ECDSA) { + return DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) signatureParameters.getSigningCertificate().getPublicKey()); } + return Constant.Default.SIGNATURE_DIGEST_ALGORITHM; } private void populateEncryptionAlgorithm() { @@ -112,7 +126,8 @@ private void populateEncryptionAlgorithm() { private void populateSignatureProfile() { if (signatureParameters.getSignatureProfile() == null) { - signatureParameters.setSignatureProfile(getConfiguration().getSignatureProfile()); + SignatureProfile signatureProfile = getConfiguration().getSignatureProfile(); + signatureParameters.setSignatureProfile(signatureProfile != null ? signatureProfile : Constant.Default.SIGNATURE_PROFILE); } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureFinalizer.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureFinalizer.java index bd16d0a67..a30aa381f 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureFinalizer.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicSignatureFinalizer.java @@ -76,7 +76,7 @@ public Signature finalizeSignature(byte[] signatureValue) { if ((signatureParameters.getEncryptionAlgorithm() == EncryptionAlgorithm.ECDSA || CertificateUtils.isEcdsaCertificate(signatureParameters.getSigningCertificate())) && DSSASN1Utils.isAsn1Encoded(signatureValue)) { LOGGER.debug("Finalizing signature ASN1: {} [{}]", Helper.bytesToHex(signatureValue, HEX_MAX_LENGTH), signatureValue.length); - signatureValue = DSSASN1Utils.fromAsn1toSignatureValue(eu.europa.esig.dss.enumerations.EncryptionAlgorithm.ECDSA, + signatureValue = DSSASN1Utils.ensurePlainSignatureValue(eu.europa.esig.dss.enumerations.EncryptionAlgorithm.ECDSA, signatureValue); } LOGGER.debug("Finalizing signature XmlDSig: {} [{}]", Helper.bytesToHex(signatureValue, HEX_MAX_LENGTH), signatureValue.length); @@ -193,7 +193,8 @@ private void initSigningFacade() { } private void populateFacadeParameters() { - setDigestAlgorithm(); + setSignatureDigestAlgorithm(); + setDataFileDigestAlgorithm(); setSigningCertificate(); setEncryptionAlgorithm(); setSignatureProfile(); @@ -205,10 +206,15 @@ private void populateFacadeParameters() { setCustomDataLoader(); } - private void setDigestAlgorithm() { - facade.setSignatureDigestAlgorithm(signatureParameters.getDigestAlgorithm()); + private void setSignatureDigestAlgorithm() { + facade.setSignatureDigestAlgorithm(signatureParameters.getSignatureDigestAlgorithm()); } + private void setDataFileDigestAlgorithm() { + facade.setDataFileDigestAlgorithm(signatureParameters.getDataFileDigestAlgorithm()); + } + + private void setSigningCertificate() { X509Certificate signingCert = signatureParameters.getSigningCertificate(); facade.setSigningCertificate(signingCert); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/DataLoaderDecorator.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/DataLoaderDecorator.java index ec62d9740..17906f77b 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/DataLoaderDecorator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/DataLoaderDecorator.java @@ -58,7 +58,7 @@ public static void decorateWithProxySettings(CommonsDataLoader dataLoader, Confi ); ProxyProperties httpsProxyProperties = createProxyPropertiesIfHostAndPortPresent( configuration.getHttpsProxyPort(), configuration.getHttpsProxyHost(), - configuration.getHttpProxyUser(), configuration.getHttpProxyPassword() + configuration.getHttpsProxyUser(), configuration.getHttpsProxyPassword() ); ProxyConfig proxyConfig = createProxyConfigIfAnyPropertiesPresent(httpProxyProperties, httpsProxyProperties); dataLoader.setProxyConfig(proxyConfig); @@ -78,7 +78,7 @@ public static void decorateWithProxySettingsFor(ExternalConnectionType connectio ); ProxyProperties httpsProxyProperties = createProxyPropertiesIfHostAndPortPresent( configuration.getHttpsProxyPortFor(connectionType), configuration.getHttpsProxyHostFor(connectionType), - configuration.getHttpProxyUserFor(connectionType), configuration.getHttpProxyPasswordFor(connectionType) + configuration.getHttpsProxyUserFor(connectionType), configuration.getHttpsProxyPasswordFor(connectionType) ); ProxyConfig proxyConfig = createProxyConfigIfAnyPropertiesPresent(httpProxyProperties, httpsProxyProperties); dataLoader.setProxyConfig(proxyConfig); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/SKCommonCertificateVerifier.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/SKCommonCertificateVerifier.java index dc3be7387..2cf460f0a 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/SKCommonCertificateVerifier.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/SKCommonCertificateVerifier.java @@ -18,10 +18,11 @@ import eu.europa.esig.dss.spi.client.http.DataLoader; import eu.europa.esig.dss.spi.x509.CertificateSource; import eu.europa.esig.dss.spi.x509.ListCertificateSource; +import eu.europa.esig.dss.spi.x509.aia.AIASource; import eu.europa.esig.dss.spi.x509.revocation.RevocationSource; import eu.europa.esig.dss.validation.CertificateVerifier; import eu.europa.esig.dss.validation.CommonCertificateVerifier; -import eu.europa.esig.dss.validation.ListRevocationSource; +import eu.europa.esig.dss.validation.RevocationDataLoadingStrategy; import java.io.IOException; import java.io.ObjectInputStream; @@ -78,6 +79,16 @@ public void setOcspSource(RevocationSource ocspSource) { this.commonCertificateVerifier.setOcspSource(ocspSource); } + @Override + public RevocationDataLoadingStrategy getRevocationDataLoadingStrategy() { + return this.commonCertificateVerifier.getRevocationDataLoadingStrategy(); + } + + @Override + public void setRevocationDataLoadingStrategy(RevocationDataLoadingStrategy revocationDataLoadingStrategy) { + this.commonCertificateVerifier.setRevocationDataLoadingStrategy(revocationDataLoadingStrategy); + } + @Override public ListCertificateSource getTrustedCertSources() { return this.commonCertificateVerifier.getTrustedCertSources(); @@ -99,43 +110,19 @@ public void setAdjunctCertSources(ListCertificateSource adjunctListCertificateSo } @Override - public DataLoader getDataLoader() { - return this.commonCertificateVerifier.getDataLoader(); - } - - @Override + @Deprecated public void setDataLoader(final DataLoader dataLoader) { this.commonCertificateVerifier.setDataLoader(dataLoader); } @Override - public ListRevocationSource getSignatureCRLSource() { - return this.commonCertificateVerifier.getSignatureCRLSource(); + public AIASource getAIASource() { + return this.commonCertificateVerifier.getAIASource(); } @Override - public void setSignatureCRLSource(ListRevocationSource signatureCRLSource) { - this.commonCertificateVerifier.setSignatureCRLSource(signatureCRLSource); - } - - @Override - public ListRevocationSource getSignatureOCSPSource() { - return this.commonCertificateVerifier.getSignatureOCSPSource(); - } - - @Override - public void setSignatureOCSPSource(ListRevocationSource signatureOCSPSource) { - this.commonCertificateVerifier.setSignatureOCSPSource(signatureOCSPSource); - } - - @Override - public ListCertificateSource getSignatureCertificateSource() { - return this.commonCertificateVerifier.getSignatureCertificateSource(); - } - - @Override - public void setSignatureCertificateSource(ListCertificateSource signatureCertificateSource) { - this.commonCertificateVerifier.setSignatureCertificateSource(signatureCertificateSource); + public void setAIASource(AIASource aiaSource) { + this.commonCertificateVerifier.setAIASource(aiaSource); } @Override @@ -198,6 +185,16 @@ public StatusAlert getAlertOnUncoveredPOE() { return this.commonCertificateVerifier.getAlertOnUncoveredPOE(); } + @Override + public void setAlertOnExpiredSignature(StatusAlert alertOnUncoveredPOE) { + this.commonCertificateVerifier.setAlertOnExpiredSignature(alertOnUncoveredPOE); + } + + @Override + public StatusAlert getAlertOnExpiredSignature() { + return this.commonCertificateVerifier.getAlertOnExpiredSignature(); + } + @Override public boolean isCheckRevocationForUntrustedChains() { return this.commonCertificateVerifier.isCheckRevocationForUntrustedChains(); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/TimeStampTokenValidator.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/TimeStampTokenValidator.java index 59ee686a8..54d6f4918 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/TimeStampTokenValidator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/TimeStampTokenValidator.java @@ -1,6 +1,7 @@ package org.digidoc4j.impl.asic; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -93,7 +94,7 @@ private List validateTimeStamp(DataFile dataFile, TimeStampT if (!isSignatureValid) { errors.add(new DigiDoc4JException("Signature not intact")); } - boolean isMessageImprintsValid = this.isMessageImprintsValid(dataFile.getBytes(), token); + boolean isMessageImprintsValid = isMessageImprintsValid(dataFile, token); if (isSignatureValid && !isMessageImprintsValid) { errors.add(new DigiDoc4JException("Signature not intact")); } @@ -104,9 +105,10 @@ private List validateTimeStamp(DataFile dataFile, TimeStampT return errors; } - private boolean isMessageImprintsValid(byte[] dataFileBytes, TimeStampToken token) { + private boolean isMessageImprintsValid(DataFile dataFile, TimeStampToken token) { + DigestAlgorithm digestAlgorithm = DigestAlgorithm.forOID(token.getTimeStampInfo().getMessageImprintAlgOID().getId()); return Arrays.equals(token.getTimeStampInfo().getMessageImprintDigest(), - DSSUtils.digest(DigestAlgorithm.SHA256, dataFileBytes)); + dataFile.calculateDigest(org.digidoc4j.DigestAlgorithm.getDigestAlgorithmUri(digestAlgorithm))); } private boolean isVersionValid(TimeStampToken token) { @@ -135,8 +137,8 @@ private void validateContainer(AsicParseResult documents) { } private TimeStampToken getTimeStamp(AsicParseResult documents) { - try { - return new TimeStampToken(new CMSSignedData(documents.getTimeStampToken().getBytes())); + try (InputStream inputStream = documents.getTimeStampToken().getStream()) { + return new TimeStampToken(new CMSSignedData(inputStream)); } catch (CMSException | TSPException | IOException e) { throw new DigiDoc4JException("Document malformed or not matching documentType", e); } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/asics/AsicSContainer.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/asics/AsicSContainer.java index 55b771cdc..ddbe0352d 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/asics/AsicSContainer.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/asics/AsicSContainer.java @@ -121,16 +121,4 @@ protected String createUserAgent() { public void addSignature(Signature signature) { throw new NotSupportedException("Not for ASiC-S container"); } - - @Override - @Deprecated - public void addRawSignature(byte[] signatureDocument) { - throw new NotSupportedException("Not for ASiC-S container"); - } - - @Override - @Deprecated - public void addRawSignature(InputStream signatureStream) { - throw new NotSupportedException("Not for ASiC-S container"); - } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/report/SignatureValidationReport.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/report/SignatureValidationReport.java index 8839d0513..a0f930ea5 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/report/SignatureValidationReport.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/report/SignatureValidationReport.java @@ -1,49 +1,235 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.asic.report; +import eu.europa.esig.dss.enumerations.Indication; +import eu.europa.esig.dss.enumerations.SignatureLevel; +import eu.europa.esig.dss.enumerations.SubIndication; +import eu.europa.esig.dss.simplereport.jaxb.Adapter1; +import eu.europa.esig.dss.simplereport.jaxb.Adapter3; +import eu.europa.esig.dss.simplereport.jaxb.Adapter4; +import eu.europa.esig.dss.simplereport.jaxb.Adapter6; +import eu.europa.esig.dss.simplereport.jaxb.XmlCertificateChain; +import eu.europa.esig.dss.simplereport.jaxb.XmlDetails; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureLevel; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureScope; +import eu.europa.esig.dss.simplereport.jaxb.XmlTimestamps; +import eu.europa.esig.dss.simplereport.jaxb.XmlToken; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; - -import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "") -public class SignatureValidationReport extends XmlSignature { +@XmlType(name = "", propOrder = { + "certificateChain", + "indication", + "subIndication", + "errors", + "warnings", + "infos", + "signingTime", + "bestSignatureTime", + "signedBy", + "signatureLevel", + "signatureScope", + "documentName" +}) +public class SignatureValidationReport implements Serializable { + + private final static long serialVersionUID = 1L; + + @XmlElement(name = "CertificateChain") + protected XmlCertificateChain certificateChain; + + @XmlElement(name = "Indication", required = true, type = String.class) + @XmlJavaTypeAdapter(Adapter3.class) + protected Indication indication; + + @XmlElement(name = "SubIndication", type = String.class) + @XmlJavaTypeAdapter(Adapter4.class) + protected SubIndication subIndication; + + @XmlElement(name = "Errors") + protected List errors; + + @XmlElement(name = "Warnings") + protected List warnings; + + @XmlElement(name = "Infos") + protected List infos; + + @XmlElement(name = "SigningTime", type = String.class) + @XmlJavaTypeAdapter(Adapter1.class) + @XmlSchemaType(name = "dateTime") + protected Date signingTime; + + @XmlElement(name = "BestSignatureTime", required = true, type = String.class) + @XmlJavaTypeAdapter(Adapter1 .class) + @XmlSchemaType(name = "dateTime") + protected Date bestSignatureTime; + + @XmlElement(name = "SignedBy") + protected String signedBy; + + @XmlElement(name = "SignatureLevel") + protected XmlSignatureLevel signatureLevel; + + @XmlElement(name = "SignatureScope") + protected List signatureScope; @XmlElement(name = "DocumentName") protected String documentName; + @XmlAttribute(name = "SignatureFormat", required = true) + @XmlJavaTypeAdapter(Adapter6.class) + protected SignatureLevel signatureFormat; + + @XmlAttribute(name = "Id", required = true) + protected String id; + public static SignatureValidationReport create(XmlSignature xmlSignature) { SignatureValidationReport report = new SignatureValidationReport(); report.setSigningTime(xmlSignature.getSigningTime()); + report.setBestSignatureTime(xmlSignature.getBestSignatureTime()); report.setSignedBy(xmlSignature.getSignedBy()); report.setIndication(xmlSignature.getIndication()); report.setSignatureLevel(xmlSignature.getSignatureLevel()); report.setSubIndication(xmlSignature.getSubIndication()); - report.getErrors().addAll(xmlSignature.getErrors()); - report.getWarnings().addAll(xmlSignature.getWarnings()); - report.getInfos().addAll(xmlSignature.getInfos()); + report.getErrors().addAll(getAllMessages(xmlSignature, XmlDetails::getError)); + report.getWarnings().addAll(getAllMessages(xmlSignature, XmlDetails::getWarning)); + report.getInfos().addAll(getAllMessages(xmlSignature, XmlDetails::getInfo)); report.getSignatureScope().addAll(xmlSignature.getSignatureScope()); report.setId(xmlSignature.getId()); - //TODO not in use in DSS 5.2 - //report.setType(xmlSignature.getType()); - report.setParentId(xmlSignature.getParentId()); report.setSignatureFormat(xmlSignature.getSignatureFormat()); report.setCertificateChain(xmlSignature.getCertificateChain()); return report; } + static List getAllMessages(XmlToken xmlToken, Function> messageListExtractor) { + final Set allMessages = new LinkedHashSet<>(); + Stream.concat( + Optional.ofNullable(xmlToken.getAdESValidationDetails()).map(Stream::of).orElseGet(Stream::empty), + Optional.ofNullable(xmlToken.getQualificationDetails()).map(Stream::of).orElseGet(Stream::empty) + ).flatMap(xmlDetails -> Optional + .ofNullable(messageListExtractor.apply(xmlDetails)).map(List::stream).orElseGet(Stream::empty) + ).forEach(xmlMessage -> allMessages.add(xmlMessage.getValue())); + if (xmlToken instanceof XmlSignature) { + Optional.ofNullable(((XmlSignature) xmlToken).getTimestamps()) + .map(XmlTimestamps::getTimestamp).map(List::stream).orElseGet(Stream::empty) + .map(xmlTimestamp -> getAllMessages(xmlTimestamp, messageListExtractor)) + .forEach(allMessages::addAll); + } + return new ArrayList<>(allMessages); + } + + public XmlCertificateChain getCertificateChain() { + return certificateChain; + } + + public void setCertificateChain(XmlCertificateChain value) { + this.certificateChain = value; + } + + public Indication getIndication() { + return indication; + } + + public void setIndication(Indication value) { + this.indication = value; + } + + public SubIndication getSubIndication() { + return subIndication; + } + + public void setSubIndication(SubIndication value) { + this.subIndication = value; + } + + public List getErrors() { + if (errors == null) { + errors = new ArrayList<>(); + } + return this.errors; + } + + public List getWarnings() { + if (warnings == null) { + warnings = new ArrayList<>(); + } + return this.warnings; + } + + public List getInfos() { + if (infos == null) { + infos = new ArrayList<>(); + } + return this.infos; + } + + public Date getSigningTime() { + return signingTime; + } + + public void setSigningTime(Date value) { + this.signingTime = value; + } + + public Date getBestSignatureTime() { + return bestSignatureTime; + } + + public void setBestSignatureTime(Date value) { + this.bestSignatureTime = value; + } + + public String getSignedBy() { + return signedBy; + } + + public void setSignedBy(String value) { + this.signedBy = value; + } + + public XmlSignatureLevel getSignatureLevel() { + return signatureLevel; + } + + public void setSignatureLevel(XmlSignatureLevel value) { + this.signatureLevel = value; + } + + public List getSignatureScope() { + if (signatureScope == null) { + signatureScope = new ArrayList<>(); + } + return this.signatureScope; + } + public String getDocumentName() { return documentName; } @@ -51,4 +237,21 @@ public String getDocumentName() { public void setDocumentName(String documentName) { this.documentName = documentName; } + + public SignatureLevel getSignatureFormat() { + return signatureFormat; + } + + public void setSignatureFormat(SignatureLevel value) { + this.signatureFormat = value; + } + + public String getId() { + return id; + } + + public void setId(String value) { + this.id = value; + } + } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallback.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallback.java new file mode 100644 index 000000000..0e8d470bc --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallback.java @@ -0,0 +1,291 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.impl.asic.tsl; + +import eu.europa.esig.dss.spi.tsl.DownloadInfoRecord; +import eu.europa.esig.dss.spi.tsl.InfoRecord; +import eu.europa.esig.dss.spi.tsl.LOTLInfo; +import eu.europa.esig.dss.spi.tsl.ParsingInfoRecord; +import eu.europa.esig.dss.spi.tsl.PivotInfo; +import eu.europa.esig.dss.spi.tsl.TLInfo; +import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; +import eu.europa.esig.dss.spi.tsl.ValidationInfoRecord; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.digidoc4j.Configuration; +import org.digidoc4j.TSLRefreshCallback; +import org.digidoc4j.exceptions.TslDownloadException; +import org.digidoc4j.exceptions.TslParsingException; +import org.digidoc4j.exceptions.TslRefreshException; +import org.digidoc4j.exceptions.TslValidationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Default implementation of the {@link TSLRefreshCallback}. + */ +public class DefaultTSLRefreshCallback implements TSLRefreshCallback { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTSLRefreshCallback.class); + + private static final String LoTL = "LoTL"; + private static final String Pivot_LoTL = "Pivot LoTL"; + private static final String TL = "TL"; + + private final Configuration configuration; + + /** + * Creates an instance of this callback with the specified configuration. + * + * @param configuration configuration to use + */ + public DefaultTSLRefreshCallback(Configuration configuration) { + this.configuration = Objects.requireNonNull(configuration); + } + + /** + * Ensures the state of the TSL and either throws an exception or returns {@code true}. + * + * @param summary the information about the state of the TSL + * + * @return always {@code true}, unless an exception is thrown + * + * @throws TslRefreshException if:
      + *
    • the summary contains no information about any LoTL-s
    • + *
    • a LoTL has failed to download, parse or validate
    • + *
    • all trusted lists in a LoTL have failed to download, parse or validate
    • + *
    • the trusted list of any required territory has failed to download, parse or validate
    • + *
    + * + * @see Configuration#getRequiredTerritories() + * @see Configuration#setRequiredTerritories(String...) + */ + @Override + public boolean ensureTSLState(TLValidationJobSummary summary) { + if (CollectionUtils.isEmpty(summary.getLOTLInfos())) { + throw new TslRefreshException("No TSL refresh info found!"); + } + + for (LOTLInfo lotlInfo : summary.getLOTLInfos()) { + ensureLOTLState(lotlInfo); + } + + return true; + } + + private void ensureLOTLState(LOTLInfo lotlInfo) { + List lotlErrors = validateState(lotlInfo, LoTL); + if (CollectionUtils.isNotEmpty(lotlErrors)) { + Iterator iterator = lotlErrors.iterator(); + TslRefreshException toThrow = iterator.next(); + while (iterator.hasNext()) { + toThrow.addSuppressed(iterator.next()); + } + throw toThrow; + } + + Optional.ofNullable(lotlInfo.getPivotInfos()) + .map(List::stream).orElseGet(Stream::empty) + .forEach(DefaultTSLRefreshCallback::checkPivotState); + + ensureStateOfTLsOfLOTL(lotlInfo); + } + + private void ensureStateOfTLsOfLOTL(LOTLInfo lotlInfo) { + Map tlExceptions = new LinkedHashMap<>(); + boolean hasValidTrustedList = false; + + if (CollectionUtils.isNotEmpty(lotlInfo.getTLInfos())) { + for (TLInfo tlInfo : lotlInfo.getTLInfos()) { + List tlErrors = validateState(tlInfo, TL); + if (CollectionUtils.isNotEmpty(tlErrors)) { + tlErrors.forEach(exception -> tlExceptions.put(exception, tlInfo)); + } else { + hasValidTrustedList = true; + } + } + } + + if (hasValidTrustedList) { + ensureStateOfTLsOfRequiredTerritories(lotlInfo.getTLInfos(), tlExceptions); + tlExceptions.keySet().forEach(DefaultTSLRefreshCallback::logExceptionMessageAsWarningIfExists); + } else { + String name = augmentEntityNameWithTerritoryIfPresent(LoTL, lotlInfo); + String message = String.format("Failed to load any trusted lists for %s: %s", name, lotlInfo.getUrl()); + throwTslRefreshException(message, tlExceptions.keySet()); + } + } + + private void ensureStateOfTLsOfRequiredTerritories(List tlInfoList, Map tlExceptions) { + List requiredTerritories = configuration.getRequiredTerritories(); + if (CollectionUtils.isEmpty(requiredTerritories)) { + return; + } + + List trustedTerritories = configuration.getTrustedTerritories(); + boolean trustedCheckRequired = CollectionUtils.isNotEmpty(trustedTerritories); + List failedRequiredTerritories = new ArrayList<>(); + + for (String requiredTerritory : requiredTerritories) { + if (trustedCheckRequired && !trustedTerritories.contains(requiredTerritory)) { + // If this is not a trusted territory, then skip it + continue; + } + TLInfo territoryInfo = tlInfoList.stream() + .filter(tlInfoTerritoryFilter(requiredTerritory)) + .findFirst().orElse(null); + if (territoryInfo != null && !tlExceptions.containsValue(territoryInfo)) { + // If info exists for this territory and there are no exceptions related to the info, then skip it + continue; + } + failedRequiredTerritories.add(requiredTerritory); + } + + if (CollectionUtils.isNotEmpty(failedRequiredTerritories)) { + String message = failedRequiredTerritories.stream().collect(Collectors.joining( + ", ", "Failed to load trusted lists for required territories: ", StringUtils.EMPTY + )); + throwTslRefreshException(message, tlExceptions.keySet()); + } + } + + private static List validateState(TLInfo tlInfo, String entityName) { + entityName = augmentEntityNameWithTerritoryIfPresent(entityName, tlInfo); + + TslRefreshException downloadException = validateDownloadState(tlInfo.getDownloadCacheInfo(), entityName, tlInfo.getUrl()); + TslRefreshException parsingException = validateParsingState(tlInfo.getParsingCacheInfo(), entityName, tlInfo.getUrl()); + TslRefreshException validationException = validateValidationState(tlInfo.getValidationCacheInfo(), entityName, tlInfo.getUrl()); + + return Stream.of(downloadException, parsingException, validationException) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private static void checkPivotState(PivotInfo pivotInfo) { + String entityName = augmentEntityNameWithTerritoryIfPresent(Pivot_LoTL, pivotInfo); + logExceptionMessageAsWarningIfExists(validateDownloadState(pivotInfo.getDownloadCacheInfo(), entityName, pivotInfo.getUrl())); + logExceptionMessageAsWarningIfExists(validateParsingState(pivotInfo.getParsingCacheInfo(), entityName, pivotInfo.getUrl())); + logExceptionMessageAsWarningIfExists(validateValidationState(pivotInfo.getValidationCacheInfo(), entityName, pivotInfo.getUrl())); + } + + private static String augmentEntityNameWithTerritoryIfPresent(String entityName, TLInfo tlInfo) { + return Optional.ofNullable(getTerritory(tlInfo)) + .filter(StringUtils::isNotBlank) + .map(territory -> String.format("<%s> %s", territory, entityName)) + .orElse(entityName); + } + + private static TslDownloadException validateDownloadState(DownloadInfoRecord downloadInfo, String entityName, String url) { + if (downloadInfo == null) { + String message = String.format("No download info found for %s: %s", entityName, url); + return new TslDownloadException(message); + } else if (downloadInfo.isError()) { + String message = String.format("Failed to download %s: %s", entityName, url); + return Optional.ofNullable(createCauseIfExceptionMessageExists(downloadInfo, TslDownloadException::new)) + .map(cause -> new TslDownloadException(message, cause)) + .orElseGet(() -> new TslDownloadException(message)); + } else if (downloadInfo.isRefreshNeeded()) { + String message = String.format("(Re)download needed for %s: %s", entityName, url); + return new TslDownloadException(message); + } else if (!downloadInfo.isSynchronized()) { + String message = String.format("Unexpected download status '%s' for %s: %s", downloadInfo.getStatusName(), entityName, url); + return new TslDownloadException(message); + } + return null; + } + + private static TslParsingException validateParsingState(ParsingInfoRecord parsingInfo, String entityName, String url) { + if (parsingInfo == null) { + String message = String.format("No parsing info found for %s: %s", entityName, url); + return new TslParsingException(message); + } else if (parsingInfo.isError()) { + String message = String.format("Failed to parse %s: %s", entityName, url); + return Optional.ofNullable(createCauseIfExceptionMessageExists(parsingInfo, TslParsingException::new)) + .map(cause -> new TslParsingException(message, cause)) + .orElseGet(() -> new TslParsingException(message)); + } else if (parsingInfo.isRefreshNeeded()) { + String message = String.format("(Re)parsing needed for %s: %s", entityName, url); + return new TslParsingException(message); + } else if (!parsingInfo.isSynchronized()) { + String message = String.format("Unexpected parsing status '%s' for %s: %s", parsingInfo.getStatusName(), entityName, url); + return new TslParsingException(message); + } + return null; + } + + private static TslValidationException validateValidationState(ValidationInfoRecord validationInfo, String entityName, String url) { + if (validationInfo == null) { + String message = String.format("No validation info found for %s: %s", entityName, url); + return new TslValidationException(message); + } else if (validationInfo.isError()) { + String message = String.format("Failed to validate %s: %s", entityName, url); + return Optional.ofNullable(createCauseIfExceptionMessageExists(validationInfo, TslValidationException::new)) + .map(cause -> new TslValidationException(message, cause)) + .orElseGet(() -> new TslValidationException(message)); + } else if (validationInfo.getIndication() != null && !validationInfo.isValid()) { + String message = String.format("Failed to validate %s: %s", entityName, url); + StringBuilder causeMessage = new StringBuilder(entityName).append(" validation failed; indication: ").append(validationInfo.getIndication()); + Optional.ofNullable(validationInfo.getSubIndication()).ifPresent(subIndication -> causeMessage.append("; sub-indication: ").append(subIndication)); + return new TslValidationException(message, new TslValidationException(causeMessage.toString())); + } else if (validationInfo.isRefreshNeeded()) { + String message = String.format("(Re)validation needed for %s: %s", entityName, url); + return new TslValidationException(message); + } else if (!validationInfo.isSynchronized()) { + String message = String.format("Unexpected validation status '%s' for %s: %s", validationInfo.getStatusName(), entityName, url); + return new TslValidationException(message); + } + return null; + } + + private static String getTerritory(TLInfo tlInfo) { + return Optional.ofNullable(tlInfo.getParsingCacheInfo()).map(ParsingInfoRecord::getTerritory).orElse(null); + } + + private static Predicate tlInfoTerritoryFilter(String territory) { + return tlInfo -> Optional.ofNullable(getTerritory(tlInfo)).map(territory::equals).orElse(Boolean.FALSE); + } + + private static TslRefreshException createCauseIfExceptionMessageExists(InfoRecord infoRecord, Function exceptionFactory) { + return Optional.ofNullable(infoRecord.getExceptionMessage()).map(exceptionFactory).orElse(null); + } + + private static void throwTslRefreshException(String message, Collection possibleCauses) { + if (possibleCauses.size() == 1) { + throw new TslRefreshException(message, possibleCauses.iterator().next()); + } else { + TslRefreshException tslException = new TslRefreshException(message); + possibleCauses.forEach(tslException::addSuppressed); + throw tslException; + } + } + + private static void logExceptionMessageAsWarningIfExists(TslRefreshException exception) { + if (exception != null && exception.getCause() != null) { + LOGGER.warn("{} - {}", exception.getMessage(), exception.getCause().getMessage()); + } else if (exception != null) { + LOGGER.warn(exception.getMessage()); + } + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/LazyTslCertificateSource.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/LazyTslCertificateSource.java index 92ea5a4eb..282597dd9 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/LazyTslCertificateSource.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/LazyTslCertificateSource.java @@ -14,7 +14,6 @@ import eu.europa.esig.dss.model.DSSException; import eu.europa.esig.dss.model.x509.CertificateToken; import eu.europa.esig.dss.model.x509.X500PrincipalHelper; -import eu.europa.esig.dss.spi.tsl.LOTLInfo; import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; import eu.europa.esig.dss.spi.tsl.TrustProperties; import eu.europa.esig.dss.spi.tsl.TrustedListsCertificateSource; @@ -44,7 +43,7 @@ public class LazyTslCertificateSource extends TrustedListsCertificateSource implements TSLCertificateSource { private static final Logger LOGGER = LoggerFactory.getLogger(LazyTslCertificateSource.class); - private static final String CACHE_ERROR_STATUS = "ERROR"; + private transient TLValidationJob tlValidationJob; private TSLCertificateSource certificateSource; private Long lastCacheReloadingTime; @@ -154,9 +153,14 @@ private synchronized void refreshTsl() { this.populateTsl(); LOGGER.debug("Refreshing TSL"); this.tlValidationJob.onlineRefresh(); - this.lastCacheReloadingTime = new Date().getTime(); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Finished refreshing TSL, cache expires at {}", this.getNextCacheExpirationDate()); + this.lastCacheReloadingTime = null; + if (tslLoader.getTslRefreshCallback().ensureTSLState(tlValidationJob.getSummary())) { + this.lastCacheReloadingTime = new Date().getTime(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Finished refreshing TSL, cache expires at {}", this.getNextCacheExpirationDate()); + } + } else { + LOGGER.debug("Finished refreshing TSL, cache is still expired"); } } catch (DSSException e) { throw new TslCertificateSourceInitializationException("Failed to initialize TSL: " + e.getMessage(), e); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TSLCertificateSourceImpl.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TSLCertificateSourceImpl.java index f3ee6a7ba..61fc31dcb 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TSLCertificateSourceImpl.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TSLCertificateSourceImpl.java @@ -104,7 +104,7 @@ public void addTSLCertificate(X509Certificate certificate) { MutableTimeDependentValues statusHistoryList = new MutableTimeDependentValues<>(); statusHistoryList.addOldest(statusAndInformationExtensions); - TrustProperties trustProperties = new TrustProperties(getFirstSuitableTLInfo().getIdentifier(), + TrustProperties trustProperties = new TrustProperties(getFirstSuitableTLInfo().getDSSId(), trustServiceProviderBuilder.build(), statusHistoryList); addCertificate(new CertificateToken(certificate), Arrays.asList(trustProperties)); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactory.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactory.java deleted file mode 100644 index 41df0a1ee..000000000 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ - -package org.digidoc4j.impl.asic.tsl; - -import java.io.File; - -import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; -import eu.europa.esig.dss.service.http.commons.FileCacheDataLoader; -import eu.europa.esig.dss.spi.client.http.DataLoader; -import eu.europa.esig.dss.spi.client.http.Protocol; -import org.digidoc4j.Configuration; -import org.digidoc4j.DataLoaderFactory; -import org.digidoc4j.ExternalConnectionType; -import org.digidoc4j.impl.asic.DataLoaderDecorator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Manages the creation of data loaders for downloading certificates from the Trust Store (TSL). - */ -public class TslDataLoaderFactory implements DataLoaderFactory { - - private static final Logger logger = LoggerFactory.getLogger(TslDataLoaderFactory.class); - private Configuration configuration; - private File fileCacheDirectory; - - public TslDataLoaderFactory(Configuration configuration, File fileCacheDirectory) { - this.configuration = configuration; - this.fileCacheDirectory = fileCacheDirectory; - } - - @Override - public DataLoader create() { - if (configuration.getTslDataLoaderFactory() == null) { - return createDataLoader(); - } else { - logger.debug("Using custom TSL data loader factory provided by the configuration"); - return configuration.getTslDataLoaderFactory().create(); - } - } - - private DataLoader createDataLoader() { - CommonsDataLoader commonsDataLoader = new CommonsDataLoader(); - if (Protocol.isHttpUrl(this.configuration.getTslLocation())) { - DataLoaderDecorator.decorateWithProxySettingsFor(ExternalConnectionType.TSL, commonsDataLoader, configuration); - DataLoaderDecorator.decorateWithSslSettingsFor(ExternalConnectionType.TSL, commonsDataLoader, configuration); - commonsDataLoader.setTimeoutConnection(this.configuration.getConnectionTimeout()); - commonsDataLoader.setTimeoutSocket(this.configuration.getSocketTimeout()); - FileCacheDataLoader fileCacheDataLoader = new FileCacheDataLoader(commonsDataLoader); - fileCacheDataLoader.setCacheExpirationTime(this.configuration.getTslCacheExpirationTime()); - fileCacheDataLoader.setFileCacheDirectory(this.fileCacheDirectory); - logger.debug("Using file cache directory for storing TSL: {}", this.fileCacheDirectory); - return fileCacheDataLoader; - } else { - return commonsDataLoader; - } - } -} diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactory.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactory.java new file mode 100644 index 000000000..538f824f1 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactory.java @@ -0,0 +1,79 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.impl.asic.tsl; + +import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; +import eu.europa.esig.dss.service.http.commons.FileCacheDataLoader; +import eu.europa.esig.dss.spi.client.http.DSSFileLoader; +import eu.europa.esig.dss.spi.client.http.DataLoader; +import org.digidoc4j.Configuration; +import org.digidoc4j.DSSFileLoaderFactory; +import org.digidoc4j.ExternalConnectionType; +import org.digidoc4j.impl.asic.DataLoaderDecorator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +/** + * Manages the creation of file loaders for downloading certificates from the Trust Store (TSL). + */ +public class TslFileLoaderFactory implements DSSFileLoaderFactory { + + private static final Logger logger = LoggerFactory.getLogger(TslFileLoaderFactory.class); + + private final Configuration configuration; + private final File fileCacheDirectory; + + public TslFileLoaderFactory(Configuration configuration, File fileCacheDirectory) { + this.configuration = configuration; + this.fileCacheDirectory = fileCacheDirectory; + } + + @Override + public DSSFileLoader create() { + if (configuration.getTslFileLoaderFactory() != null) { + logger.debug("Using custom TSL file loader factory provided by the configuration"); + return configuration.getTslFileLoaderFactory().create(); + } else if (configuration.getTslDataLoaderFactory() != null) { + DataLoader customDataLoader = configuration.getTslDataLoaderFactory().create(); + if (customDataLoader instanceof DSSFileLoader) { + logger.debug("Using custom TSL data loader factory provided by the configuration"); + return (DSSFileLoader) customDataLoader; + } else { + logger.debug("Using custom TSL data loader factory with default file cache"); + return wrapIntoFileCacheDataLoader(customDataLoader); + } + } else { + logger.debug("Using default TSL file loader factory"); + return createDefaultFileLoader(); + } + } + + private DSSFileLoader createDefaultFileLoader() { + CommonsDataLoader commonsDataLoader = new CommonsDataLoader(); + DataLoaderDecorator.decorateWithProxySettingsFor(ExternalConnectionType.TSL, commonsDataLoader, configuration); + DataLoaderDecorator.decorateWithSslSettingsFor(ExternalConnectionType.TSL, commonsDataLoader, configuration); + commonsDataLoader.setTimeoutConnection(this.configuration.getConnectionTimeout()); + commonsDataLoader.setTimeoutConnectionRequest(this.configuration.getConnectionTimeout()); + commonsDataLoader.setTimeoutSocket(this.configuration.getSocketTimeout()); + return wrapIntoFileCacheDataLoader(commonsDataLoader); + } + + private DSSFileLoader wrapIntoFileCacheDataLoader(DataLoader dataLoader) { + FileCacheDataLoader fileCacheDataLoader = new FileCacheDataLoader(dataLoader); + fileCacheDataLoader.setCacheExpirationTime(this.configuration.getTslCacheExpirationTime()); + logger.debug("Using file cache directory for storing TSL: {}", this.fileCacheDirectory); + fileCacheDataLoader.setFileCacheDirectory(this.fileCacheDirectory); + return fileCacheDataLoader; + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslLoader.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslLoader.java index 7e1f5bc51..821eea4bf 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslLoader.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/tsl/TslLoader.java @@ -11,9 +11,7 @@ package org.digidoc4j.impl.asic.tsl; import eu.europa.esig.dss.model.DSSException; -import eu.europa.esig.dss.service.http.commons.FileCacheDataLoader; import eu.europa.esig.dss.spi.client.http.DSSFileLoader; -import eu.europa.esig.dss.spi.client.http.DataLoader; import eu.europa.esig.dss.spi.x509.KeyStoreCertificateSource; import eu.europa.esig.dss.tsl.alerts.TLAlert; import eu.europa.esig.dss.tsl.alerts.detections.TLExpirationDetection; @@ -26,25 +24,25 @@ import eu.europa.esig.dss.tsl.function.XMLOtherTSLPointer; import eu.europa.esig.dss.tsl.job.TLValidationJob; import eu.europa.esig.dss.tsl.source.LOTLSource; -import eu.europa.esig.dss.tsl.sync.AcceptAllStrategy; import eu.europa.esig.dss.tsl.sync.ExpirationAndSignatureCheckStrategy; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FileUtils; import org.digidoc4j.Configuration; +import org.digidoc4j.TSLRefreshCallback; import org.digidoc4j.exceptions.DigiDoc4JException; +import org.digidoc4j.exceptions.LotlTrustStoreNotFoundException; import org.digidoc4j.exceptions.TslCertificateSourceInitializationException; -import org.digidoc4j.exceptions.TslKeyStoreNotFoundException; import org.digidoc4j.utils.ResourceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.Arrays; import java.util.HashSet; +import java.util.Optional; import java.util.Set; /** @@ -54,7 +52,6 @@ public class TslLoader implements Serializable { public static final File fileCacheDirectory = new File(System.getProperty("java.io.tmpdir") + "/digidoc4jTSLCache"); private static final Logger logger = LoggerFactory.getLogger(TslLoader.class); - private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; private transient TSLCertificateSourceImpl tslCertificateSource; private transient TLValidationJob tlValidationJob; private final Configuration configuration; @@ -88,15 +85,17 @@ public void prepareTsl() { } } + public TSLRefreshCallback getTslRefreshCallback() { + return Optional.ofNullable(configuration.getTslRefreshCallback()) + .orElseGet(() -> new DefaultTSLRefreshCallback(configuration)); + } + private TLValidationJob createTslValidationJob() { TLValidationJob job = new TLValidationJob(); - DataLoader tslDataLoader = new TslDataLoaderFactory(this.configuration, fileCacheDirectory).create(); - if (tslDataLoader instanceof DSSFileLoader) { - job.setOnlineDataLoader((DSSFileLoader) tslDataLoader); - } else { - job.setOnlineDataLoader(new FileCacheDataLoader(tslDataLoader)); - } + DSSFileLoader tslFileLoader = new TslFileLoaderFactory(this.configuration, fileCacheDirectory).create(); + job.setOnlineDataLoader(tslFileLoader); + LOTLSource lotlSource = createLOTLSource(); job.setListOfTrustedListSources(lotlSource); job.setTrustedListCertificateSource(this.tslCertificateSource); @@ -121,10 +120,11 @@ public TLAlert tlExpirationDetection() { private LOTLSource createLOTLSource() { LOTLSource lotlSource = new LOTLSource(); - lotlSource.setUrl(this.configuration.getTslLocation()); + lotlSource.setUrl(this.configuration.getLotlLocation()); lotlSource.setCertificateSource(this.tslCertificateSource); + lotlSource.setPivotSupport(this.configuration.isLotlPivotSupportEnabled()); - lotlSource.setCertificateSource(getKeyStore()); + lotlSource.setCertificateSource(getTrustStore()); Set trustedTerritories = new HashSet<>(); CollectionUtils.addAll(trustedTerritories, this.configuration.getTrustedTerritories()); @@ -142,26 +142,25 @@ private LOTLSource createLOTLSource() { } - private KeyStoreCertificateSource getKeyStore() { - try (InputStream tslKeyStoreInputStream = openTslKeyStoreInputStream()) { - return new KeyStoreCertificateSource(tslKeyStoreInputStream, DEFAULT_KEYSTORE_TYPE, - this.configuration.getTslKeyStorePassword()); + private KeyStoreCertificateSource getTrustStore() { + try (InputStream lotlTrustStoreInputStream = openLotlTrustStoreInputStream()) { + return new KeyStoreCertificateSource(lotlTrustStoreInputStream, + configuration.getLotlTruststoreType(), + configuration.getLotlTruststorePassword()); } catch (IOException e) { - throw new TslKeyStoreNotFoundException("Unable to retrieve keystore", e); + throw new LotlTrustStoreNotFoundException("Unable to retrieve trust-store", e); } } - private InputStream openTslKeyStoreInputStream() throws IOException, TslKeyStoreNotFoundException { - String keystoreLocation = this.configuration.getTslKeyStoreLocation(); - if (ResourceUtils.isFileReadable(keystoreLocation)) { - return new FileInputStream(keystoreLocation); - } - InputStream in = getClass().getClassLoader().getResourceAsStream(keystoreLocation); - if (in == null) { - throw new TslKeyStoreNotFoundException("Unable to retrieve TSL keystore", new RuntimeException(String.format - ("Keystore not found by location <%s>", keystoreLocation))); + private InputStream openLotlTrustStoreInputStream() throws IOException, LotlTrustStoreNotFoundException { + String trustStorePath = this.configuration.getLotlTruststorePath(); + try { + return ResourceUtils.getResource(trustStorePath); + } catch (Exception e) { + throw new LotlTrustStoreNotFoundException( + "Unable to retrieve LOTL trust-store from path: " + trustStorePath, e + ); } - return in; } /* diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/TimestampSignature.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/TimestampSignature.java index 32ed53e0f..30dec5fde 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/TimestampSignature.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/TimestampSignature.java @@ -88,7 +88,7 @@ public Date getTrustedSigningTime() { private TimeStampToken findTimestampToken() { XAdESPaths xAdESPaths = getxPathQueryHolder(); logger.debug("Finding timestamp token"); - NodeList timestampNodes = DomUtils.getNodeList(getSignatureElement(), xAdESPaths.getSignatureTimestampsPath()); + NodeList timestampNodes = DomUtils.getNodeList(getSignatureElement(), xAdESPaths.getSignatureTimestampPath()); if (timestampNodes.getLength() == 0) { logger.warn("Signature timestamp element was not found"); return null; diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSignatureParser.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSignatureParser.java index 9dc148ea7..03073e18d 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSignatureParser.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSignatureParser.java @@ -101,7 +101,7 @@ private boolean isTimeMarkSignature(XAdESSignature xAdESSignature) { private static void assertNoExcessEncapsulatedTimeStamps(final XAdESSignature xadesSignature) { final XAdESPaths xadesPaths = xadesSignature.getXAdESPaths(); - final NodeList signatureTimeStamps = DomUtils.getNodeList(xadesSignature.getSignatureElement(), xadesPaths.getSignatureTimestampsPath()); + final NodeList signatureTimeStamps = DomUtils.getNodeList(xadesSignature.getSignatureElement(), xadesPaths.getSignatureTimestampPath()); if (signatureTimeStamps == null || signatureTimeStamps.getLength() < 1) { return; } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSigningDssFacade.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSigningDssFacade.java index 1b269faa8..6a3e43c6f 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSigningDssFacade.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesSigningDssFacade.java @@ -46,7 +46,6 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; @@ -128,15 +127,6 @@ public DSSDocument signDocument(byte[] signatureValue, Collection data return correctedSignedDocument; } - @Deprecated - public DSSDocument extendSignature(DSSDocument xadesSignature, DSSDocument detachedContent) { - logger.debug("Extending signature with DSS"); - xAdESSignatureParameters.setDetachedContents(Arrays.asList(detachedContent)); - DSSDocument extendedSignature = xAdESService.extendDocument(xadesSignature, xAdESSignatureParameters); - logger.debug("Finished extending signature with DSS"); - return extendedSignature; - } - public DSSDocument extendSignature(DSSDocument xadesSignature, List detachedContents) { logger.debug("Extending signature with DSS"); xAdESSignatureParameters.setDetachedContents(detachedContents); @@ -166,6 +156,10 @@ public void setSignatureDigestAlgorithm(org.digidoc4j.DigestAlgorithm digestAlgo xAdESSignatureParameters.setDigestAlgorithm(digestAlgorithm.getDssDigestAlgorithm()); } + public void setDataFileDigestAlgorithm(org.digidoc4j.DigestAlgorithm digestAlgorithm) { + xAdESSignatureParameters.setReferenceDigestAlgorithm(digestAlgorithm.getDssDigestAlgorithm()); + } + public void setEncryptionAlgorithm(EncryptionAlgorithm encryptionAlgorithm) { xAdESSignatureParameters.setEncryptionAlgorithm(encryptionAlgorithm); } @@ -231,7 +225,6 @@ private void initDefaultXadesParameters() { private void initCertificateVerifier() { certificateVerifier.setCrlSource(null); //Disable CRL checks - certificateVerifier.setSignatureCRLSource(null); //Disable CRL checks } private void initXadesMultipleService() { diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationDssFacade.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationDssFacade.java index 55dda9020..b3ae40652 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationDssFacade.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationDssFacade.java @@ -12,6 +12,7 @@ import java.util.List; +import eu.europa.esig.dss.exception.IllegalInputException; import org.digidoc4j.Configuration; import org.digidoc4j.Constant; import org.digidoc4j.exceptions.InvalidSignatureException; @@ -51,7 +52,7 @@ public SignedDocumentValidator openXadesValidator(DSSDocument signature) { SignaturePolicyProvider signaturePolicyProvider = Helper.getBdocSignaturePolicyProvider(signature); validator.setSignaturePolicyProvider(signaturePolicyProvider); return validator; - } catch (DSSException e) { + } catch (DSSException | IllegalInputException e) { logger.error("Failed to parse xades signature: " + e.getMessage()); throw new InvalidSignatureException(); } @@ -61,7 +62,6 @@ private CertificateVerifier createCertificateVerifier() { logger.debug("Creating new certificate verifier"); CertificateVerifier certificateVerifier = new SKCommonCertificateVerifier(); certificateVerifier.setCrlSource(null); //Disable CRL checks - certificateVerifier.setSignatureCRLSource(null); //Disable CRL checks logger.debug("Setting trusted cert source to the certificate verifier"); certificateVerifier.setTrustedCertSources(configuration.getTSL()); logger.debug("Setting custom data loader to the certificate verifier"); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationReportProcessor.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationReportProcessor.java index 6db77cd3d..031f56a9e 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationReportProcessor.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/XadesValidationReportProcessor.java @@ -2,9 +2,13 @@ import eu.europa.esig.dss.i18n.I18nProvider; import eu.europa.esig.dss.i18n.MessageTag; +import eu.europa.esig.dss.simplereport.jaxb.XmlDetails; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; +import eu.europa.esig.dss.simplereport.jaxb.XmlTimestamp; import eu.europa.esig.dss.simplereport.jaxb.XmlToken; import eu.europa.esig.dss.validation.reports.Reports; +import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,10 +46,30 @@ private static void removeFalsePositiveWarningsFromValidationReports(Reports val } private static void removeFalsePositiveWarningsFromSignatureResult(XmlSignature signatureResult) { - for (String warning : new ArrayList<>(signatureResult.getWarnings())) { - if (WARNING_MESSAGES_TO_IGNORE.contains(warning)) { - signatureResult.getWarnings().remove(warning); - LOGGER.debug("Removed false-positive warning message: {}", warning); + removeFalsePositiveWarningsFromToken(signatureResult); + if (signatureResult.getTimestamps() != null && CollectionUtils.isNotEmpty(signatureResult.getTimestamps().getTimestamp())) { + for (XmlTimestamp timestampResult : signatureResult.getTimestamps().getTimestamp()) { + if (timestampResult != null) { + removeFalsePositiveWarningsFromToken(timestampResult); + } + } + } + } + + private static void removeFalsePositiveWarningsFromToken(XmlToken token) { + if (token.getAdESValidationDetails() != null) { + removeFalsePositiveWarningsFromDetails(token.getAdESValidationDetails()); + } + if (token.getQualificationDetails() != null) { + removeFalsePositiveWarningsFromDetails(token.getQualificationDetails()); + } + } + + private static void removeFalsePositiveWarningsFromDetails(XmlDetails details) { + for (XmlMessage warning : new ArrayList<>(details.getWarning())) { + if (WARNING_MESSAGES_TO_IGNORE.contains(warning.getValue())) { + details.getWarning().remove(warning); + LOGGER.debug("Removed false-positive warning message: \"{}\":\"{}\"", warning.getKey(), warning.getValue()); } } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/FullSimpleReportBuilder.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/FullSimpleReportBuilder.java index c6d36e2e7..091a40a24 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/FullSimpleReportBuilder.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/FullSimpleReportBuilder.java @@ -1,30 +1,27 @@ package org.digidoc4j.impl.asic.xades.validation; -import java.util.ArrayList; -import java.util.List; - +import eu.europa.esig.dss.detailedreport.DetailedReport; +import eu.europa.esig.dss.detailedreport.jaxb.XmlBasicBuildingBlocks; +import eu.europa.esig.dss.detailedreport.jaxb.XmlConclusion; +import eu.europa.esig.dss.detailedreport.jaxb.XmlMessage; +import eu.europa.esig.dss.detailedreport.jaxb.XmlSubXCV; +import eu.europa.esig.dss.enumerations.Context; import org.digidoc4j.exceptions.DigiDoc4JException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.europa.esig.dss.detailedreport.jaxb.XmlBasicBuildingBlocks; -import eu.europa.esig.dss.detailedreport.jaxb.XmlName; -import eu.europa.esig.dss.detailedreport.jaxb.XmlSubXCV; -import eu.europa.esig.dss.enumerations.Context; -import eu.europa.esig.dss.detailedreport.DetailedReport; +import java.util.List; /** * Created by Andrei on 1.03.2018. */ public class FullSimpleReportBuilder { - private final Logger log = LoggerFactory.getLogger(FullSimpleReportBuilder.class); + private static final Logger log = LoggerFactory.getLogger(FullSimpleReportBuilder.class); private static final int BUILDING_BLOCK_ID_LIMIT = 15; - private DetailedReport detailedReport; - private List validationErrors = new ArrayList<>(); - private List validationWarnings = new ArrayList<>(); + private final DetailedReport detailedReport; FullSimpleReportBuilder(DetailedReport detailedReport) { this.detailedReport = detailedReport; @@ -36,100 +33,87 @@ public class FullSimpleReportBuilder { * @param validationErrors * @param validationWarnings */ - public void addDetailedReportEexeptions(List validationErrors, List validationWarnings){ - this.validationErrors = validationErrors; - this.validationWarnings = validationWarnings; - errorsAndWarningsBuilder(); - } - - private void errorsAndWarningsBuilder(){ + public void addDetailedReportExceptions(List validationErrors, List validationWarnings){ log.debug("Errors and warnings parsing from DetailedReport"); List basicBuildingBlocks = this.detailedReport.getJAXBModel().getBasicBuildingBlocks(); - List errors = new ArrayList<>(); - List warnings = new ArrayList<>(); - for (XmlBasicBuildingBlocks xmlBasicBuildingBlocks: basicBuildingBlocks){ + for (XmlBasicBuildingBlocks xmlBasicBuildingBlocks : basicBuildingBlocks) { + String typeId = transformTypeId(xmlBasicBuildingBlocks.getId()); + Context type = xmlBasicBuildingBlocks.getType(); + if (xmlBasicBuildingBlocks.getCV() != null) { - errors.addAll(xmlBasicBuildingBlocks.getCV().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getCV().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getCV().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getFC() != null) { - errors.addAll(xmlBasicBuildingBlocks.getFC().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getFC().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getFC().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getISC() != null) { - errors.addAll(xmlBasicBuildingBlocks.getISC().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getISC().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getISC().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getPCV() != null) { - errors.addAll(xmlBasicBuildingBlocks.getPCV().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getPCV().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getPCV().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getSAV() != null) { - errors.addAll(xmlBasicBuildingBlocks.getSAV().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getCV().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getSAV().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getPSV() != null) { - errors.addAll(xmlBasicBuildingBlocks.getPSV().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getPSV().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getPSV().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getVCI() != null) { - errors.addAll(xmlBasicBuildingBlocks.getVCI().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getVCI().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getVCI().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getVTS() != null) { - errors.addAll(xmlBasicBuildingBlocks.getVTS().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getVTS().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getVTS().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); } if (xmlBasicBuildingBlocks.getXCV() != null) { - errors.addAll(xmlBasicBuildingBlocks.getXCV().getConclusion().getErrors()); - warnings.addAll(xmlBasicBuildingBlocks.getXCV().getConclusion().getWarnings()); + XmlConclusion xmlConclusion = xmlBasicBuildingBlocks.getXCV().getConclusion(); + addExceptions(validationErrors, xmlConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlConclusion.getWarnings(), typeId, type); if (xmlBasicBuildingBlocks.getXCV().getSubXCV() != null) { List subXCV = xmlBasicBuildingBlocks.getXCV().getSubXCV(); for (XmlSubXCV xmlSubXCV : subXCV){ - errors.addAll(xmlSubXCV.getConclusion().getErrors()); - warnings.addAll(xmlSubXCV.getConclusion().getWarnings()); + XmlConclusion xmlSubConclusion = xmlSubXCV.getConclusion(); + addExceptions(validationErrors, xmlSubConclusion.getErrors(), typeId, type); + addExceptions(validationWarnings, xmlSubConclusion.getWarnings(), typeId, type); } } } - validationErrors.addAll(getErrors(errors, xmlBasicBuildingBlocks.getId(), xmlBasicBuildingBlocks - .getType())); - - validationWarnings.addAll(getWarnings(warnings, xmlBasicBuildingBlocks.getId(), xmlBasicBuildingBlocks.getType())); - } - } - - private List getWarnings(List warnings, String id, Context type) { - List warningsAsString = new ArrayList<>(); - String typeId = transformTypeId(id); - for (XmlName xmlName : warnings){ - if (isNewException(xmlName.getValue(), this.validationWarnings)){ - warningsAsString.add(getExcetpions(xmlName, typeId, type)); - } } - return warningsAsString; } - private List getErrors(List errors, String id, Context type) { - List errorsAsString = new ArrayList<>(); - String typeId = transformTypeId(id); - for (XmlName xmlName : errors){ - if (isNewException(xmlName.getValue(), this.validationErrors)){ - errorsAsString.add(getExcetpions(xmlName, typeId, type)); + private static void addExceptions(List exceptions, List messages, String typeId, Context type) { + for (XmlMessage xmlMessage : messages) { + if (isNewException(xmlMessage.getValue(), exceptions)) { + exceptions.add(getException(xmlMessage, typeId, type)); } } - return errorsAsString; } - private DigiDoc4JException getExcetpions(XmlName xmlName, String typeId, Context type) { - String nameId = xmlName.getNameId(); - String value = xmlName.getValue(); - return new DigiDoc4JException("Block Id: " + typeId + ". Type = " + type.name() + ". " + nameId + ": " + + private static DigiDoc4JException getException(XmlMessage xmlMessage, String typeId, Context type) { + String key = xmlMessage.getKey(); + String value = xmlMessage.getValue(); + return new DigiDoc4JException("Block Id: " + typeId + ". Type = " + type.name() + ". " + key + ": " + value); } - private String transformTypeId(String id) { + private static String transformTypeId(String id) { if (id.length() > BUILDING_BLOCK_ID_LIMIT){ log.debug("BasicBuildingBlock Id is too big for report: {}", id); return id.substring(0, BUILDING_BLOCK_ID_LIMIT).concat(".."); @@ -137,9 +121,9 @@ private String transformTypeId(String id) { return id; } - private boolean isNewException(String exccceptionValue, List exceptions) { + private static boolean isNewException(String exceptionValue, List exceptions) { for (DigiDoc4JException digiDoc4JException : exceptions){ - if (digiDoc4JException.getMessage().contains(exccceptionValue)){ + if (digiDoc4JException.getMessage().contains(exceptionValue)){ return false; } } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/TimestampSignatureValidator.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/TimestampSignatureValidator.java index d8289f299..ad71851b9 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/TimestampSignatureValidator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/TimestampSignatureValidator.java @@ -12,7 +12,6 @@ import java.io.IOException; import java.math.BigInteger; -import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -26,7 +25,6 @@ import org.digidoc4j.Configuration; import org.digidoc4j.X509Cert; import org.digidoc4j.exceptions.DigiDoc4JException; -import org.digidoc4j.exceptions.SignedWithExpiredCertificateException; import org.digidoc4j.exceptions.TimestampAfterOCSPResponseTimeException; import org.digidoc4j.exceptions.TimestampAndOcspResponseTimeDeltaTooLargeException; import org.digidoc4j.exceptions.UntrustedRevocationSourceException; @@ -54,7 +52,6 @@ public TimestampSignatureValidator(XadesSignature signature) { @Override protected void populateValidationErrors() { super.populateValidationErrors(); - this.addCertificateExpirationError(); this.addSigningTimeErrors(); this.addRevocationErrors(); } @@ -101,20 +98,6 @@ private void addSigningTimeErrors() { } } - private void addCertificateExpirationError() { - Date signingTime = this.signature.getTrustedSigningTime(); - if (signingTime == null) { - return; - } - X509Certificate signerCert = this.signature.getSigningCertificate().getX509Certificate(); - boolean isCertValid = signingTime.compareTo(signerCert.getNotBefore()) >= 0 - && signingTime.compareTo(signerCert.getNotAfter()) <= 0; - if (!isCertValid) { - this.log.error("Signature has been created with expired certificate"); - this.addValidationError(new SignedWithExpiredCertificateException()); - } - } - private void addRevocationErrors() { Reports reports = this.signature.validate().getReports(); DiagnosticData diagnosticData = reports.getDiagnosticData(); diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/XadesSignatureValidator.java b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/XadesSignatureValidator.java index 26c604207..06e0372db 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/XadesSignatureValidator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/asic/xades/validation/XadesSignatureValidator.java @@ -17,7 +17,11 @@ import eu.europa.esig.dss.enumerations.ObjectIdentifierQualifier; import eu.europa.esig.dss.i18n.I18nProvider; import eu.europa.esig.dss.i18n.MessageTag; +import eu.europa.esig.dss.jaxb.object.Message; import eu.europa.esig.dss.simplereport.SimpleReport; +import eu.europa.esig.dss.simplereport.jaxb.XmlDetails; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; +import eu.europa.esig.dss.simplereport.jaxb.XmlToken; import eu.europa.esig.dss.validation.SignaturePolicy; import eu.europa.esig.dss.validation.reports.Reports; import eu.europa.esig.dss.xades.definition.XAdESPaths; @@ -49,6 +53,9 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; /** * Signature validator for Xades signatures. @@ -57,20 +64,20 @@ public class XadesSignatureValidator implements SignatureValidator { private static final Logger LOGGER = LoggerFactory.getLogger(XadesSignatureValidator.class); private static final String XADES_SIGNED_PROPERTIES = "http://uri.etsi.org/01903#SignedProperties"; - protected XadesSignature signature; + protected final XadesSignature signature; private transient Reports validationReport; private transient SimpleReport simpleReport; - private List validationErrors = new ArrayList<>(); - private List validationWarnings = new ArrayList<>(); - private String signatureId; - private String signatureUniqueId; - protected Configuration configuration; + private final List validationErrors = new ArrayList<>(); + private final List validationWarnings = new ArrayList<>(); + private final String signatureId; + private final String signatureUniqueId; + protected final Configuration configuration; /** * Constructor. * * @param signature Signature object for validation - * @param configuration configuretion + * @param configuration configuration */ public XadesSignatureValidator(XadesSignature signature, Configuration configuration) { this.signature = signature; @@ -88,7 +95,7 @@ public ValidationResult extractResult() { this.populateValidationErrors(); if (configuration.isFullReportNeeded()) { FullSimpleReportBuilder detailedReportParser = new FullSimpleReportBuilder(validationReport.getDetailedReport()); - detailedReportParser.addDetailedReportEexeptions(validationErrors, validationWarnings); + detailedReportParser.addDetailedReportExceptions(validationErrors, validationWarnings); } return this.createValidationResult(); } @@ -125,7 +132,7 @@ protected void addPolicyErrors() { protected boolean isSignaturePolicyImpliedElementPresented() { XAdESPaths xAdESPaths = this.getDssSignature().getXAdESPaths(); Element signaturePolicyImpliedElement = DomUtils.getElement(this.getDssSignature().getSignatureElement(), - String.format("%s%s", xAdESPaths.getSignaturePolicyIdentifier(), + String.format("%s%s", xAdESPaths.getSignaturePolicyIdentifierPath(), xAdESPaths.getCurrentSignaturePolicyImplied().replace(".", ""))); return signaturePolicyImpliedElement != null; } @@ -186,7 +193,7 @@ private void addPolicyIdentifierQualifierValidationErrors() { XAdESPaths xAdESPaths = getDssSignature().getXAdESPaths(); Element signatureElement = getDssSignature().getSignatureElement(); String xAdESPrefix = xAdESPaths.getNamespace().getPrefix(); - Element element = DomUtils.getElement(signatureElement, xAdESPaths.getSignaturePolicyIdentifier()); + Element element = DomUtils.getElement(signatureElement, xAdESPaths.getSignaturePolicyIdentifierPath()); Element identifier = DomUtils.getElement(element, "./" + xAdESPrefix + ":SignaturePolicyId/" + xAdESPrefix + ":SigPolicyId/" + xAdESPrefix + ":Identifier"); String qualifier = identifier.getAttribute("Qualifier"); @@ -218,13 +225,16 @@ private int findSignedPropertiesReferencesCount() { private void addReportedErrors() { LOGGER.debug("Extracting reported errors"); if (this.simpleReport != null) { - for (String errorMessage : this.simpleReport.getErrors(this.signatureUniqueId)) { - I18nProvider i18nProvider = new I18nProvider(); - /*if (this.isRedundantErrorMessage(errorMessage)) { - LOGGER.debug("Ignoring redundant error message: " + errorMessage); - continue; - }*/ - + I18nProvider i18nProvider = new I18nProvider(); + Stream.concat( + Stream.concat( + this.simpleReport.getAdESValidationErrors(this.signatureUniqueId).stream(), + this.simpleReport.getQualificationErrors(this.signatureUniqueId).stream() + ).map(Message::getValue), + this.simpleReport.getSignatureTimestamps(this.signatureUniqueId).stream() + .flatMap(timestamp -> getTokenMessages(timestamp, details -> details.getError().stream())) + .map(XmlMessage::getValue) + ).distinct().forEach(errorMessage -> { if (errorMessage.contains(i18nProvider.getMessage(MessageTag.BBB_XCV_ISCR_ANS))) { this.addValidationError(new CertificateRevokedException(errorMessage)); } else if (errorMessage.contains(i18nProvider.getMessage(MessageTag.PSV_IPSVC_ANS))) { @@ -232,16 +242,23 @@ private void addReportedErrors() { } else { this.addValidationError(new DigiDoc4JException(errorMessage, this.signatureId)); } - } + }); } } - private void addReportedWarnings() { if (this.simpleReport != null) { - for (String warning : this.simpleReport.getWarnings(this.signatureUniqueId)) { - this.validationWarnings.add(new DigiDoc4JException(warning, this.signatureId)); - } + Stream.concat( + Stream.concat( + this.simpleReport.getAdESValidationWarnings(this.signatureUniqueId).stream(), + this.simpleReport.getQualificationWarnings(this.signatureUniqueId).stream() + ).map(Message::getValue), + this.simpleReport.getSignatureTimestamps(this.signatureUniqueId).stream() + .flatMap(timestamp -> getTokenMessages(timestamp, details -> details.getWarning().stream())) + .map(XmlMessage::getValue) + ).distinct().forEach(warningMessage -> { + this.addValidationWarning(new DigiDoc4JException(warningMessage, this.signatureId)); + }); } } @@ -296,4 +313,11 @@ private boolean isIndicationValid(Indication indication) { return Arrays.asList(Indication.PASSED, Indication.TOTAL_PASSED).contains(indication); } + private static Stream getTokenMessages(XmlToken token, Function> messageExtractor) { + return (token != null) ? Stream.concat( + Optional.ofNullable(token.getAdESValidationDetails()).map(messageExtractor).orElseGet(Stream::empty), + Optional.ofNullable(token.getQualificationDetails()).map(messageExtractor).orElseGet(Stream::empty) + ) : Stream.empty(); + } + } diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocContainer.java b/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocContainer.java index 25a826887..3a7cad13e 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocContainer.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocContainer.java @@ -1,37 +1,32 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.ddoc; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.cert.X509Certificate; -import java.util.List; - import org.digidoc4j.Configuration; import org.digidoc4j.Container; import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.DataFile; -import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.Signature; -import org.digidoc4j.SignatureParameters; import org.digidoc4j.SignatureProfile; -import org.digidoc4j.SignatureToken; -import org.digidoc4j.SignedInfo; import org.digidoc4j.exceptions.NotSupportedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + /** * Offers functionality for handling DDoc containers. */ @@ -136,146 +131,11 @@ public DataFile getTimeStampToken() { throw new NotSupportedException("Not for DDOC container"); } - /** - * Prepare signature. - * After preparing the signature the container will have to be signed as well - * - * @param signerCert X509 Certificate to be used for preparing the signature - * @return Signed info - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public SignedInfo prepareSigning(X509Certificate signerCert) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - @Override public Configuration getConfiguration() { return ddoc4jFacade.getConfiguration(); } - /** - * Return signature profile - * - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public String getSignatureProfile() { - return ddoc4jFacade.getSignatureProfile(); - } - - /** - * Set signature parameters - * - * @param signatureParameters Signature parameters. These are related to the signing location and signer roles - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void setSignatureParameters(SignatureParameters signatureParameters) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - - /** - * Get digest algorithm - * - * @return Digest algorithm - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public DigestAlgorithm getDigestAlgorithm() { - return ddoc4jFacade.getDigestAlgorithm(); - } - - /** - * Adds a signature to the container. - * - * @param signature signature to be added to the container - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void addRawSignature(byte[] signature) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - - /** - * Adds signature from the input stream to the container. - * For BDOC it throws a NotYetImplementedException(). - * - * @param signatureStream signature to be added to the container - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void addRawSignature(InputStream signatureStream) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - - /** - * Returns a data file - * - * @param index index number of the data file to return - * @return data file - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public DataFile getDataFile(int index) { - return ddoc4jFacade.getDataFiles().get(index); - } - - /** - * Return the count of DataFile objects - * - * @return count of DataFile objects - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public int countDataFiles() { - return ddoc4jFacade.countDataFiles(); - } - - /** - * Removes a data file from the container by data file name. Any corresponding signatures will be deleted. - * - * @param fileName name of the data file to be removed - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void removeDataFile(String fileName) { - throw new NotSupportedException("Removing data files is not supported anymore for DDoc!"); - } - - /** - * Removes the signature with the given signature id from the container. - * - * @param signatureId id of the signature to be removed - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void removeSignature(int signatureId) { - throw new NotSupportedException("Removing signatures is not supported anymore for DDoc!"); - } - - /** - * Saves the container to the specified location. - * - * @param path file name and path. - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void save(String path) { - ddoc4jFacade.save(path); - } - /** * Saves the container to the java.io.OutputStream. * @@ -287,107 +147,6 @@ public void save(OutputStream out) { ddoc4jFacade.save(out); } - /** - * Signs all data files in the container. - * - * @param signatureToken signatureToken implementation - * @return signature - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public Signature sign(SignatureToken signatureToken) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - - /** - * Signs all data files in the container. - * - * @param rawSignature raw signature - * @return signature - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public Signature signRaw(byte[] rawSignature) { - throw new NotSupportedException("Adding new signatures is not supported anymore for DDoc!"); - } - - /** - * Return signature - * - * @param index index number of the signature to return - * @return signature - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public Signature getSignature(int index) { - return ddoc4jFacade.getSignature(index); - } - - /** - * Return the count of Signature objects - * - * @return count of Signature objects - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public int countSignatures() { - return ddoc4jFacade.countSignatures(); - } - - /** - * Returns document type ASiC or DDOC - * - * @return document type - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public DocumentType getDocumentType() { - return ddoc4jFacade.getDocumentType(); - } - - /** - * Returns container version in case of DDOC. BDOC does not have a version and it returns null - * - * @return version - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public String getVersion() { - return ddoc4jFacade.getVersion(); - } - - /** - * Extends signature profile to SignatureProfile - * * - * - * @param profile signature profile - * @see SignatureProfile - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void extendTo(SignatureProfile profile) { - throw new NotSupportedException("Extending signature profile is not supported anymore for DDoc!"); - } - - /** - * Extends signature profile to @see SignatureProfile - * - * @param profile signature profile - * @deprecated will be removed in the future. - */ - @Override - @Deprecated - public void setSignatureProfile(SignatureProfile profile) { - throw new NotSupportedException("Setting signature profile is not supported anymore for DDoc!"); - } - /** * This method returns Returns DDocFacade. * DDocFacade for handling data files and signatures in a container. diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocSignature.java b/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocSignature.java index 3c9e251e1..ce9ec01e0 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocSignature.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocSignature.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.ddoc; @@ -21,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.URI; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; @@ -110,13 +109,6 @@ public X509Cert getOCSPCertificate() { return x509Certificate != null ? new X509Cert(x509Certificate) : null; } - @Override - @Deprecated - public String getPolicy() { - logger.debug("getPolicy"); - return ""; - } - @Override public String getPostalCode() { @@ -140,17 +132,6 @@ public Date getOCSPResponseCreationTime() { return date; } - /** - * This method returns OCSP response creation time (Date object), it can be null. - * - * @return date. - */ - @Override - @Deprecated - public Date getProducedAt() { - return getOCSPResponseCreationTime(); - } - @Override public Date getTimeStampCreationTime() { throw new NotYetImplementedException(); @@ -203,18 +184,6 @@ public Date getClaimedSigningTime() { return origin.getSignedProperties().getSigningTime(); } - @Override - public Date getSigningTime() { - return getClaimedSigningTime(); - } - - @Override - @Deprecated - public URI getSignaturePolicyURI() { - logger.debug("getSignaturePolicyURI"); - return null; - } - @Override public String getStateOrProvince() { logger.debug("getStateOrProvince"); @@ -238,12 +207,6 @@ public ValidationResult validateSignature() { return new DDocSignatureValidationResult(validationResult, origin.getSignedDoc().getFormat()); } - @Override - @Deprecated - public List validate() { - return validateSignature().getErrors(); - } - /** * Retrieves CertValue element with the desired type * @@ -261,12 +224,6 @@ public byte[] getAdESSignature() { return origin.getOrigContent(); } - @Override - @Deprecated - public byte[] getRawSignature() { - return getAdESSignature(); - } - /** * Get index In array. * diff --git a/digidoc4j/src/main/java/org/digidoc4j/impl/pades/PadesContainer.java b/digidoc4j/src/main/java/org/digidoc4j/impl/pades/PadesContainer.java index 2be5b4d6c..b8227e7a0 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/impl/pades/PadesContainer.java +++ b/digidoc4j/src/main/java/org/digidoc4j/impl/pades/PadesContainer.java @@ -1,13 +1,26 @@ -package org.digidoc4j.impl.pades; +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ +package org.digidoc4j.impl.pades; import eu.europa.esig.dss.diagnostic.DiagnosticData; import eu.europa.esig.dss.enumerations.Indication; import eu.europa.esig.dss.enumerations.RevocationType; +import eu.europa.esig.dss.jaxb.object.Message; import eu.europa.esig.dss.model.FileDocument; import eu.europa.esig.dss.pades.PAdESUtils; import eu.europa.esig.dss.pades.validation.PDFDocumentValidator; import eu.europa.esig.dss.pdf.pdfbox.PdfBoxDefaultObjectFactory; +import eu.europa.esig.dss.simplereport.SimpleReport; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; +import eu.europa.esig.dss.simplereport.jaxb.XmlTimestamp; import eu.europa.esig.dss.validation.CertificateVerifier; import eu.europa.esig.dss.validation.SignedDocumentValidator; import eu.europa.esig.dss.validation.reports.Reports; @@ -16,12 +29,8 @@ import org.digidoc4j.Container; import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.DataFile; -import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.Signature; -import org.digidoc4j.SignatureParameters; import org.digidoc4j.SignatureProfile; -import org.digidoc4j.SignatureToken; -import org.digidoc4j.SignedInfo; import org.digidoc4j.exceptions.DigiDoc4JException; import org.digidoc4j.exceptions.NotSupportedException; import org.digidoc4j.exceptions.NotYetImplementedException; @@ -35,7 +44,6 @@ import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; @@ -44,7 +52,6 @@ */ public class PadesContainer extends PdfBoxDefaultObjectFactory implements Container { - private static final Logger logger = LoggerFactory.getLogger(PadesContainer.class); public static final String PADES = "PADES"; @@ -140,13 +147,26 @@ public ContainerValidationResult validate() { SignedDocumentValidator validator = new PDFDocumentValidator(document); validator.setCertificateVerifier(createCertificateVerifier()); Reports reports = validator.validateDocument(this.getClass().getClassLoader().getResourceAsStream(this.configuration.getValidationPolicy())); - PadesContainerValidationResult result = new PadesContainerValidationResult(reports.getSimpleReport()); + SimpleReport simpleReport = reports.getSimpleReport(); + PadesContainerValidationResult result = new PadesContainerValidationResult(simpleReport); result.setReport(reports.getXmlSimpleReport()); - for (String id : reports.getSimpleReport().getSignatureIdList()) { - Indication indication = reports.getSimpleReport().getIndication(id); + for (String id : simpleReport.getSignatureIdList()) { + Indication indication = simpleReport.getIndication(id); if (!Indication.TOTAL_PASSED.equals(indication)) { - result.getErrors().addAll(this.getExceptions(reports.getSimpleReport().getErrors(id))); - result.getWarnings().addAll(this.getExceptions(reports.getSimpleReport().getWarnings(id))); + result.getErrors().addAll(getExceptionsFromMessages(simpleReport.getAdESValidationErrors(id))); + result.getErrors().addAll(getExceptionsFromMessages(simpleReport.getQualificationErrors(id))); + result.getWarnings().addAll(getExceptionsFromMessages(simpleReport.getAdESValidationWarnings(id))); + result.getWarnings().addAll(getExceptionsFromMessages(simpleReport.getQualificationWarnings(id))); + for (XmlTimestamp timestamp : simpleReport.getSignatureTimestamps(id)) { + if (timestamp.getAdESValidationDetails() != null) { + result.getErrors().addAll(getExceptionsFromXmlMessages(timestamp.getAdESValidationDetails().getError())); + result.getWarnings().addAll(getExceptionsFromXmlMessages(timestamp.getAdESValidationDetails().getWarning())); + } + if (timestamp.getQualificationDetails() != null) { + result.getErrors().addAll(getExceptionsFromXmlMessages(timestamp.getQualificationDetails().getError())); + result.getWarnings().addAll(getExceptionsFromXmlMessages(timestamp.getQualificationDetails().getWarning())); + } + } } } addRevocationErrors(result, reports); @@ -189,17 +209,20 @@ public DataFile getTimeStampToken() { throw new NotSupportedException("Not for Pades container"); } - private List getExceptions(List exceptionString) { - List exc = new ArrayList<>(); - for (String s : exceptionString) { - exc.add(new DigiDoc4JException(s)); + private static List getExceptionsFromMessages(List exceptionMessages) { + List exceptions = new ArrayList<>(); + for (Message exceptionMessage : exceptionMessages) { + exceptions.add(new DigiDoc4JException(exceptionMessage.getValue())); } - return exc; + return exceptions; } - @Override - public SignedInfo prepareSigning(X509Certificate signerCert) { - throw new NotYetImplementedException(); + private static List getExceptionsFromXmlMessages(List exceptionMessages) { + List exceptions = new ArrayList<>(); + for (XmlMessage exceptionMessage : exceptionMessages) { + exceptions.add(new DigiDoc4JException(exceptionMessage.getValue())); + } + return exceptions; } @Override @@ -207,106 +230,15 @@ public Configuration getConfiguration() { return configuration; } - @Override - public String getSignatureProfile() { - throw new NotYetImplementedException(); - } - - @Override - public void setSignatureParameters(SignatureParameters signatureParameters) { - throw new NotYetImplementedException(); - } - - @Override - public DigestAlgorithm getDigestAlgorithm() { - throw new NotYetImplementedException(); - } - - @Override - public void addRawSignature(byte[] signature) { - throw new NotYetImplementedException(); - } - - @Override - public void addRawSignature(InputStream signatureStream) { - throw new NotYetImplementedException(); - } - - @Override - public DataFile getDataFile(int index) { - throw new NotYetImplementedException(); - } - - @Override - public int countDataFiles() { - throw new NotYetImplementedException(); - } - - @Override - public void removeDataFile(String fileName) { - throw new NotYetImplementedException(); - } - - @Override - public void removeSignature(int signatureId) { - throw new NotYetImplementedException(); - } - - @Override - public void save(String path) { - throw new NotYetImplementedException(); - } - @Override public void save(OutputStream out) { throw new NotYetImplementedException(); } - @Override - public Signature sign(SignatureToken signatureToken) { - throw new NotYetImplementedException(); - } - - @Override - public Signature signRaw(byte[] rawSignature) { - throw new NotYetImplementedException(); - } - - @Override - public Signature getSignature(int index) { - throw new NotYetImplementedException(); - } - - @Override - public int countSignatures() { - throw new NotYetImplementedException(); - } - - @Override - public DocumentType getDocumentType() { - throw new NotYetImplementedException(); - } - - @Override - public String getVersion() { - throw new NotYetImplementedException(); - } - - @Override - public void extendTo(SignatureProfile profile) { - throw new NotYetImplementedException(); - } - - @Override - public void setSignatureProfile(SignatureProfile profile) { - throw new NotYetImplementedException(); - } - private CertificateVerifier createCertificateVerifier() { logger.debug("Creating new certificate verifier"); CertificateVerifier certificateVerifier = new SKCommonCertificateVerifier(); certificateVerifier.setCrlSource(null); //Disable CRL checks - certificateVerifier.setSignatureCRLSource(null); //Disable CRL checks logger.debug("Setting trusted cert source to the certificate verifier"); certificateVerifier.setTrustedCertSources(configuration.getTSL()); logger.debug("Setting custom data loader to the certificate verifier"); diff --git a/digidoc4j/src/main/java/org/digidoc4j/main/CommandLineExecutor.java b/digidoc4j/src/main/java/org/digidoc4j/main/CommandLineExecutor.java index 258a086a1..7878863ec 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/main/CommandLineExecutor.java +++ b/digidoc4j/src/main/java/org/digidoc4j/main/CommandLineExecutor.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.main; @@ -36,8 +36,8 @@ import org.digidoc4j.SignatureBuilder; import org.digidoc4j.SignatureProfile; import org.digidoc4j.SignatureToken; +import org.digidoc4j.exceptions.DataFileNotFoundException; import org.digidoc4j.exceptions.DigiDoc4JException; -import org.digidoc4j.exceptions.NotSupportedException; import org.digidoc4j.impl.asic.AsicContainer; import org.digidoc4j.impl.asic.asics.AsicSContainer; import org.digidoc4j.impl.ddoc.DDocContainer; @@ -259,7 +259,11 @@ private void manipulateContainer(Container container) { this.addData(container); } if (this.context.getCommandLine().hasOption("remove")) { - container.removeDataFile(this.context.getCommandLine().getOptionValue("remove")); + String fileToRemove = this.context.getCommandLine().getOptionValue("remove"); + container.removeDataFile(container.getDataFiles().stream() + .filter(dataFile -> fileToRemove.equals(dataFile.getName())) + .findFirst().orElseThrow(() -> new DataFileNotFoundException("No datafile found: " + fileToRemove)) + ); this.fileHasChanged = true; } if (this.context.getCommandLine().hasOption(ExecutionOption.EXTRACT.getName())) { diff --git a/digidoc4j/src/main/java/org/digidoc4j/main/KeystoreGenerator.java b/digidoc4j/src/main/java/org/digidoc4j/main/KeystoreGenerator.java index 94c233a02..beaa3caa3 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/main/KeystoreGenerator.java +++ b/digidoc4j/src/main/java/org/digidoc4j/main/KeystoreGenerator.java @@ -28,13 +28,13 @@ */ public final class KeystoreGenerator { - private static final String DEFAULT_KEYSTORE_CERTIFICATES_FILEPATH = "keystore/keystore_certs"; - private static final String DEFAULT_KEYSTORE_FILEPATH = "keystore/keystore.jks"; - private static final String DEFAULT_KEYSTORE_PASSWORD = "digidoc4j-password"; - private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; + private static final String DEFAULT_TRUSTSTORE_CERTIFICATES_FILEPATH = "truststores/truststore_certs"; + private static final String DEFAULT_TRUSTSTORE_FILEPATH = "truststores/lotl-truststore.p12"; + private static final String DEFAULT_TRUSTSTORE_PASSWORD = "digidoc4j-password"; + private static final String DEFAULT_TRUSTSTORE_TYPE = "PKCS12"; - private static final String TEST_KEYSTORE_CERTIFICATES_FILEPATH = "keystore/test_keystore_certs/"; - private static final String TEST_KEYSTORE_FILEPATH = "keystore/test-keystore.jks"; + private static final String TEST_TRUSTSTORE_CERTIFICATES_FILEPATH = "truststores/test_truststore_certs/"; + private static final String TEST_TRUSTSTORE_FILEPATH = "truststores/test-lotl-truststore.p12"; private String keyStoreCertificateFilepath; private String keyStoreFilepath; @@ -46,8 +46,8 @@ public final class KeystoreGenerator { public static void main(String[] args) { try { KeystoreGenerator.aGenerator() - .withCertificateDirectory(TEST_KEYSTORE_CERTIFICATES_FILEPATH) - .withKeyStoreFilepath(TEST_KEYSTORE_FILEPATH) + .withCertificateDirectory(TEST_TRUSTSTORE_CERTIFICATES_FILEPATH) + .withKeyStoreFilepath(TEST_TRUSTSTORE_FILEPATH) .generateKeystore(); } catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException e) { e.printStackTrace(); @@ -83,9 +83,9 @@ public KeystoreGenerator withKeyStorePassword(String keyStorePassword) { * @throws IOException */ public void generateKeystore() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { - keyStoreFilepath = keyStoreFilepath == null ? DEFAULT_KEYSTORE_FILEPATH : keyStoreFilepath; - keyStoreCertificateFilepath = keyStoreCertificateFilepath == null ? DEFAULT_KEYSTORE_CERTIFICATES_FILEPATH : keyStoreCertificateFilepath; - keyStorePassword = keyStorePassword == null ? DEFAULT_KEYSTORE_PASSWORD : keyStorePassword; + keyStoreFilepath = keyStoreFilepath == null ? DEFAULT_TRUSTSTORE_FILEPATH : keyStoreFilepath; + keyStoreCertificateFilepath = keyStoreCertificateFilepath == null ? DEFAULT_TRUSTSTORE_CERTIFICATES_FILEPATH : keyStoreCertificateFilepath; + keyStorePassword = keyStorePassword == null ? DEFAULT_TRUSTSTORE_PASSWORD : keyStorePassword; generateKeystore(keyStoreCertificateFilepath, keyStoreFilepath, keyStorePassword); } @@ -103,7 +103,7 @@ public void generateKeystore() throws CertificateException, NoSuchAlgorithmExcep private void generateKeystore(String keyStoreCertsFilepath, String keyStoreFilepath, String keyStorePassword) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { createKeystore(keyStoreFilepath, keyStorePassword); - KeyStore store = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + KeyStore store = KeyStore.getInstance(DEFAULT_TRUSTSTORE_TYPE); loadIntoKeystoreFormFile(store, keyStoreFilepath, keyStorePassword); File dir = new File(keyStoreCertsFilepath); @@ -145,7 +145,7 @@ private String getPrintableHex(byte[] digest) { } private void readKeyStore(String keyStoreFilepath, String keyStorePassword) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { - KeyStore store = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + KeyStore store = KeyStore.getInstance(DEFAULT_TRUSTSTORE_TYPE); loadIntoKeystoreFormFile(store, keyStoreFilepath, keyStorePassword); Enumeration aliases = store.aliases(); @@ -160,7 +160,7 @@ private void readKeyStore(String keyStoreFilepath, String keyStorePassword) thro } private void createKeystore(String keyStoreFilepath, String keyStorePassword) throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException { - KeyStore trustStore = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + KeyStore trustStore = KeyStore.getInstance(DEFAULT_TRUSTSTORE_TYPE); trustStore.load(null, keyStorePassword.toCharArray()); Path pathToKeystore = Paths.get(keyStoreFilepath); pathToKeystore.getParent().toFile().mkdirs(); diff --git a/digidoc4j/src/main/java/org/digidoc4j/signers/PKCS12Signer.java b/digidoc4j/src/main/java/org/digidoc4j/signers/PKCS12Signer.java deleted file mode 100644 index a1fbc7382..000000000 --- a/digidoc4j/src/main/java/org/digidoc4j/signers/PKCS12Signer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ - -package org.digidoc4j.signers; - -/** - * This class has been renamed to PKCS12SignatureToken. Use {@link PKCS12SignatureToken} instead. - * @deprecated - */ -@Deprecated -public class PKCS12Signer extends PKCS12SignatureToken { - - /** - * This class has been renamed to PKCS12SignatureToken. Use {@link PKCS12SignatureToken} instead. - * @deprecated - */ - @Deprecated - public PKCS12Signer(String fileName, char[] password) { - super(fileName, password); - } -} diff --git a/digidoc4j/src/main/java/org/digidoc4j/signers/TimestampToken.java b/digidoc4j/src/main/java/org/digidoc4j/signers/TimestampToken.java index 94a9d7aad..cdb75bc32 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/signers/TimestampToken.java +++ b/digidoc4j/src/main/java/org/digidoc4j/signers/TimestampToken.java @@ -76,9 +76,7 @@ public static DataFile generateTimestampToken(DigestAlgorithm digestAlgorithm, */ public static DataFile generateTimestampToken(DigestAlgorithm digestAlgorithm, DataFile containerDataFile) { OnlineTSPSource onlineTSPSource = defineOnlineTSPSource(null); - byte[] dataFileDigest; - dataFileDigest = containerDataFile.getBytes(); - byte[] digest = DSSUtils.digest(digestAlgorithm, dataFileDigest); + byte[] digest = containerDataFile.calculateDigest(org.digidoc4j.DigestAlgorithm.getDigestAlgorithmUri(digestAlgorithm)); DataFile timeStampToken = getTimestampToken(onlineTSPSource, digestAlgorithm, digest); return timeStampToken; } diff --git a/digidoc4j/src/main/java/org/digidoc4j/utils/DigestUtils.java b/digidoc4j/src/main/java/org/digidoc4j/utils/DigestUtils.java new file mode 100644 index 000000000..725831c77 --- /dev/null +++ b/digidoc4j/src/main/java/org/digidoc4j/utils/DigestUtils.java @@ -0,0 +1,20 @@ +package org.digidoc4j.utils; + +import org.digidoc4j.DigestAlgorithm; + +import java.security.interfaces.ECPublicKey; + +public final class DigestUtils { + + public static DigestAlgorithm getRecommendedSignatureDigestAlgorithm(ECPublicKey ecPublicKey) { + int keySizeInBits = ecPublicKey.getParams().getOrder().bitLength(); + if (keySizeInBits == 256) { + return DigestAlgorithm.SHA256; + } else if (keySizeInBits == 384) { + return DigestAlgorithm.SHA384; + } else { + return DigestAlgorithm.SHA512; + } + } + +} diff --git a/digidoc4j/src/main/java/org/digidoc4j/utils/Helper.java b/digidoc4j/src/main/java/org/digidoc4j/utils/Helper.java index 412240dbe..9c7b3a2fb 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/utils/Helper.java +++ b/digidoc4j/src/main/java/org/digidoc4j/utils/Helper.java @@ -368,11 +368,7 @@ public static List getAllFilesFromContainerPathAsBytes(String pathFrom) fromExistingFile(pathFrom). build(); - List files = new ArrayList<>(); - for (DataFile dataFile : container.getDataFiles()) { - files.add(dataFile.getBytes()); - } - return files; + return getAllFilesFromContainerAsBytes(container); } /** @@ -383,8 +379,7 @@ public static List getAllFilesFromContainerPathAsBytes(String pathFrom) */ public static void saveAllFilesFromContainerToFolder(Container container, String path) { for (DataFile dataFile : container.getDataFiles()) { - File file = new File(path + File.separator + dataFile.getName()); - DSSUtils.saveToFile(dataFile.getBytes(), file); + dataFile.saveAs(path + File.separator + dataFile.getName()); } } @@ -400,10 +395,7 @@ public static void saveAllFilesFromContainerPathToFolder(String pathFrom, String fromExistingFile(pathFrom). build(); - for (DataFile dataFile : container.getDataFiles()) { - File file = new File(pathTo + File.separator + dataFile.getName()); - DSSUtils.saveToFile(dataFile.getBytes(), file); - } + saveAllFilesFromContainerToFolder(container, pathTo); } /** diff --git a/digidoc4j/src/main/java/org/digidoc4j/utils/ResourceUtils.java b/digidoc4j/src/main/java/org/digidoc4j/utils/ResourceUtils.java index 4c5b63d39..274aeb853 100644 --- a/digidoc4j/src/main/java/org/digidoc4j/utils/ResourceUtils.java +++ b/digidoc4j/src/main/java/org/digidoc4j/utils/ResourceUtils.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.utils; import org.slf4j.Logger; @@ -37,21 +47,26 @@ public static boolean isFileReadable(String path) { } public static InputStream getResource(String path) { - if (path.startsWith(CLASSPATH_PREFIX)) { - path = path.substring(CLASSPATH_PREFIX.length()); + if (path.startsWith(CLASSPATH_PREFIX) || isResourceAccessible(path)) { + if (path.startsWith(CLASSPATH_PREFIX)) { + path = path.substring(CLASSPATH_PREFIX.length()); + } InputStream inputStream = ResourceUtils.class.getClassLoader().getResourceAsStream(path); if (inputStream == null) { - throw new IllegalArgumentException("Resource not found: " + path); + throw new IllegalArgumentException("Classpath resource not found: " + path); } return inputStream; - } else if (path.startsWith(FILE_PREFIX)) { - path = path.substring(FILE_PREFIX.length()); - } - try { - return new FileInputStream(path); - } catch (FileNotFoundException e) { - throw new IllegalArgumentException("Resource not found: " + path); + } else if (path.startsWith(FILE_PREFIX) || isFileReadable(path)) { + if (path.startsWith(FILE_PREFIX)) { + path = path.substring(FILE_PREFIX.length()); + } + try { + return new FileInputStream(path); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException("File resource not found: " + path, e); + } } + throw new IllegalArgumentException("Resource not found: " + path); } private ResourceUtils() { diff --git a/digidoc4j/src/main/resources/conf/constraint.xml b/digidoc4j/src/main/resources/conf/constraint.xml index 78d2a3f7f..81a41a92c 100644 --- a/digidoc4j/src/main/resources/conf/constraint.xml +++ b/digidoc4j/src/main/resources/conf/constraint.xml @@ -21,10 +21,11 @@ - + + nonRepudiation @@ -32,6 +33,7 @@ + @@ -63,6 +65,7 @@ + @@ -162,6 +165,7 @@ + nonRepudiation @@ -179,6 +183,7 @@ + @@ -233,6 +238,7 @@ + timeStamping @@ -269,6 +275,7 @@ + @@ -354,6 +361,7 @@ + @@ -386,6 +394,7 @@ + diff --git a/digidoc4j/src/main/resources/conf/test_constraint.xml b/digidoc4j/src/main/resources/conf/test_constraint.xml index 78d2a3f7f..81a41a92c 100644 --- a/digidoc4j/src/main/resources/conf/test_constraint.xml +++ b/digidoc4j/src/main/resources/conf/test_constraint.xml @@ -21,10 +21,11 @@ - + + nonRepudiation @@ -32,6 +33,7 @@ + @@ -63,6 +65,7 @@ + @@ -162,6 +165,7 @@ + nonRepudiation @@ -179,6 +183,7 @@ + @@ -233,6 +238,7 @@ + timeStamping @@ -269,6 +275,7 @@ + @@ -354,6 +361,7 @@ + @@ -386,6 +394,7 @@ + diff --git a/digidoc4j/src/main/resources/digidoc4j.yaml b/digidoc4j/src/main/resources/digidoc4j.yaml index a4984be82..8304522d7 100644 --- a/digidoc4j/src/main/resources/digidoc4j.yaml +++ b/digidoc4j/src/main/resources/digidoc4j.yaml @@ -159,7 +159,3 @@ DIGIDOC_CAS: CA_CERT: jar://certs/KLASS3-SK.crt CN: SK Proxy OCSP Responder 2009 URL: http://ocsp.sk.ee - -TSL_SSL_TRUSTSTORE_PATH: classpath:ssl/tsl_truststore.p12 -TSL_SSL_TRUSTSTORE_PASSWORD: digidoc4j-password -TSL_SSL_TRUSTSTORE_TYPE: PKCS12 diff --git a/digidoc4j/src/main/resources/keystore/keystore.jks b/digidoc4j/src/main/resources/keystore/keystore.jks deleted file mode 100644 index 755b270ea..000000000 Binary files a/digidoc4j/src/main/resources/keystore/keystore.jks and /dev/null differ diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.1.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.1.crt deleted file mode 100644 index a6c235ef2..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.1.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIG7zCCBNegAwIBAgIQEAAAAAAAnuXHXttK9Tyf2zANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJCRTERMA8GA1UEBxMIQnJ1c3NlbHMxHDAaBgNVBAoTE0NlcnRpcG9zdCBOLlYuL1MuQS4xEzARBgNVBAMTCkNpdGl6ZW4gQ0ExDzANBgNVBAUTBjIwMTgwMzAeFw0xODA2MDEyMjA0MTlaFw0yODA1MzAyMzU5NTlaMHAxCzAJBgNVBAYTAkJFMSMwIQYDVQQDExpQYXRyaWNrIEtyZW1lciAoU2lnbmF0dXJlKTEPMA0GA1UEBBMGS3JlbWVyMRUwEwYDVQQqEwxQYXRyaWNrIEplYW4xFDASBgNVBAUTCzcyMDIwMzI5OTcwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7g7VriDY4as3R4LPOg7uPH5inHzaVMOwFb/8YOW+9IVMHz/V5dJAzeTKvhLG5S4Pk6Kd2E+h18FlRonp70Gv2+ijtkPk7ZQkfez0ycuAbLXiNx2S7fc5GG9LGJafDJgBgTQuQm1aDVLDQ653mqR5tAO+gEf6vs4zRESL3MkYXAUq+S/WocEaGpIheNVAF3iPSkvEe3LvUjF/xXHWF4aMvqGK6kXGseaTcn9hgTbceuW2PAiEr+eDTNczkwGBDFXwzmnGFPMRez3ONk/jIKhha8TylDSfI/MX3ODt0dU3jvJEKPIfUJixBPehxMJMwWxTjFbNu/CK7tJ8qT2i1S4VQIDAQABo4ICjzCCAoswHwYDVR0jBBgwFoAU2TQhPjpCJW3hu7++R0z4Aq3jL1QwcwYIKwYBBQUHAQEEZzBlMDkGCCsGAQUFBzAChi1odHRwOi8vY2VydHMuZWlkLmJlbGdpdW0uYmUvY2l0aXplbjIwMTgwMy5jcnQwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmVpZC5iZWxnaXVtLmJlLzIwggEjBgNVHSAEggEaMIIBFjCCAQcGB2A4DAEBAgEwgfswLAYIKwYBBQUHAgEWIGh0dHA6Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMIHKBggrBgEFBQcCAjCBvQyBukdlYnJ1aWsgb25kZXJ3b3JwZW4gYWFuIGFhbnNwcmFrZWxpamtoZWlkc2JlcGVya2luZ2VuLCB6aWUgQ1BTIC0gVXNhZ2Ugc291bWlzIMOgIGRlcyBsaW1pdGF0aW9ucyBkZSByZXNwb25zYWJpbGl0w6ksIHZvaXIgQ1BTIC0gVmVyd2VuZHVuZyB1bnRlcmxpZWd0IEhhZnR1bmdzYmVzY2hyw6Rua3VuZ2VuLCBnZW3DpHNzIENQUzAJBgcEAIvsQAECMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwuZWlkLmJlbGdpdW0uYmUvZWlkYzIwMTgwMy5jcmwwDgYDVR0PAQH/BAQDAgZAMBMGA1UdJQQMMAoGCCsGAQUFBwMEMGwGCCsGAQUFBwEDBGAwXjAIBgYEAI5GAQEwCAYGBACORgEEMDMGBgQAjkYBBTApMCcWIWh0dHBzOi8vcmVwb3NpdG9yeS5laWQuYmVsZ2l1bS5iZRMCZW4wEwYGBACORgEGMAkGBwQAjkYBBgEwDQYJKoZIhvcNAQELBQADggIBACBY+OLhM7BryzXWklDUh9UK1+cDVboPg+lN1Et1lAEoxV4y9zuXUWLco9t8M5WfDcWFfDxyhatLedku2GurSJ1t8O/knDwLLyoJE1r2Db9VrdG+jtST+j/TmJHAX3yNWjn/9dsjiGQQuTJcce86rlzbGdUqjFTt5mGMm4zy4l/wKy6XiDKiZT8cFcOTevsl+l/vxiLiDnghOwTztVZhmWExeHG9ypqMFYmIucHQ0SFZre8mv3c7Df+VhqV/sY9xLERK3Ffk4l6B5qRPygImXqGzNSWiDISdYeUf4XoZLXJBEP7/36r4mlnP2NWQ+c1ORjesuDAZ8tD/yhMvR4DVG95EScjpTYv1wOmVB2lQrWnEtygZIi60HXfozo8uOekBnqWyDc1kuizZsYRfVNlwhCu7RsOq4zN8gkael0fejuSNtBf2J9A+rc9LQeu6AcdPauWmbxtJV93H46pFptsR8zXo+IJn5m2P9QPZ3mvDkzldNTGLG+ukhN7IF2CCcagt/WoVZLq3qKC35WVcqeoSMEE/XeSrf3/mIJ1OyFQm+tsfhTceOFDXuUgl3E86bR/f8Ur/bapwXpWpFxGIpXLGaJXbzQGSTtyNEYrdENlh71I3OeYdw3xmzU2B3tbaWREOXtj2xjyW2tIv+vvHG6sloR1QkIkGMFfzsT7W5U6ILetv ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.10.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.10.crt deleted file mode 100644 index fda17c467..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.10.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIH9jCCBt6gAwIBAgIQevrCNQpIXiCh355eXjwtpjANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCUFQxLDAqBgNVBAoTI0RpZ2l0YWxTaWduIC0gQ2VydGlmaWNhZG9yYSBEaWdpdGFsMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTUwMwYDVQQLEyxDbGFzcyAyIE1hbmFnZWQgUEtJIEluZGl2aWR1YWwgU3Vic2NyaWJlciBDQTEmMCQGA1UEAxMdRGlnaXRhbFNpZ24gUXVhbGlmaWVkIENBIC0gRzMwHhcNMjAwOTI1MDAwMDAwWhcNMjMwOTI1MjM1OTU5WjCCAZAxCzAJBgNVBAYTAlJPMRwwGgYDVQQKFBNFVVJPUEVBTiBDT01NSVNTSU9OMRkwFwYDVQRhFBBWQVRCRS0wOTQ5MzgzMzQyMT0wOwYDVQQLEzRDZXJ0aWZpY2F0ZSBQcm9maWxlIC0gUXVhbGlmaWVkIENlcnRpZmljYXRlIC0gTWVtYmVyMUUwQwYDVQQLEzxUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9ycGExIjAgBgNVBAsUGUVudGl0bGVtZW50IC0gRUMgT0ZGSUNJQUwxKzApBgkqhkiG9w0BCQEWHGFkcmlhbi5jcm9pdG9ydUBlYy5ldXJvcGEuZXUxETAPBgNVBAQUCENST0lUT1JVMRowGAYDVQQqFBFDT05TVEFOVElOLUFEUklBTjEdMBsGA1UECxQUUmVtb3RlUVNDRE1hbmFnZW1lbnQxIzAhBgNVBAMUGkNPTlNUQU5USU4tQURSSUFOIENST0lUT1JVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAutg6RcTrmbtcPoxGSoMC1O5+151zAdaw21AklQOnkEMKC8aa5d4utJ3nfiQVIGRd6tFGu8hb8osuxzYEb6ycz5y/OiRVUkr96Gi7LzEv/lIFduIAQMmr+FATvolw+QBuId8WJJaVW04/h+DrEPmbXmx8AoNrrSTeJcQanm5gZy5jaDT/fD3cJYpedkAE9XaiLmfv4LnvOvnAHuIVeY+LXvrdLVFtSCn7Y37b0GwVWTUCkvhwY1xoJm1fgM/OLxfN0SFBHFihRPD2qPHdnu/CxH4/CLvEZM2IjJAPgUxIwbJy32IuiIfadTAeHavzNM1ND/sQnKypeDH1WiaeMPsw4QIDAQABo4IDHDCCAxgwCQYDVR0TBAIwADBzBgNVHR8EbDBqMGigZqBkhmJodHRwOi8vb25zaXRlY3JsLnRydXN0d2lzZS5jb20vRGlnaXRhbFNpZ25DZXJ0aWZpY2Fkb3JhRGlnaXRhbFF1YWxpZmllZENlcnRpZmljYXRlRzMvTGF0ZXN0Q1JMLmNybDAOBgNVHQ8BAf8EBAMCBkAwbgYDVR0gBGcwZTBJBgtghkgBhvhFAQcXAjA6MDgGCCsGAQUFBwIBFixodHRwczovL3d3dy5kaWdpdGFsc2lnbi5wdC9FQ0RJR0lUQUxTSUdOL2NwczANBgtghkgBhvhFAQcsAjAJBgcEAIvsQAECMB0GA1UdDgQWBBRF9Lg2cLhB8QApjl2qjMeSz7Q3JDAfBgNVHSMEGDAWgBT7Xo5CnCOoffQbjFx8Oxir2dn3QDAnBgNVHREEIDAegRxhZHJpYW4uY3JvaXRvcnVAZWMuZXVyb3BhLmV1MIHmBggrBgEFBQcBAwSB2TCB1jAVBggrBgEFBQcLAjAJBgcEAIvsSQEBMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGATB9BgYEAI5GAQUwczA2FjBodHRwczovL3d3dy5kaWdpdGFsc2lnbi5wdC9FQ0RJR0lUQUxTSUdOL2Nwcy9kZHATAlBUMDkWM2h0dHBzOi8vd3d3LmRpZ2l0YWxzaWduLnB0L0VDRElHSVRBTFNJR04vY3BzL2RkcF9lbhMCRU4wHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGkBggrBgEFBQcBAQSBlzCBlDApBggrBgEFBQcwAYYdaHR0cDovL3N0ZC1vY3NwLnRydXN0d2lzZS5jb20wZwYIKwYBBQUHMAKGW2h0dHA6Ly9vbnNpdGVjcmwudHJ1c3R3aXNlLmNvbS9EaWdpdGFsU2lnbkNlcnRpZmljYWRvcmFEaWdpdGFsUXVhbGlmaWVkQ2VydGlmaWNhdGVHMy9jYS5jcnQwDQYJKoZIhvcNAQELBQADggEBAF36+WqrFO9d+DnaWN6u+3I+L5GzNZszQ7ojgJBgECIuuM52D1Yiu6a8GlUvnwVFQVJ3jahn7wF0NtKsl4gx43xcuWL4npatQ6Lptt5Zhx9r7e8/gxCwTqSf3wM3obzj0VS2oXNqsbkt4yho+tmdyrbUv43vmrFzV0e95ULtdPV/z9illmd6fBPkMA2ZPZJlufa63loSOK54By40FNX3NIUvsrd9Qp8BN5kgeFzuLTibZA5GSF/hfgbECyDlNOcSRDRNc8qN58S91VgGfLRBvZRgWIyNqZl9fpzc+8qM+iiHkocQl7mFuhKcENmN+EE+VXKIqPjovE5z7QKq0GOmPZw= ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.2.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.2.crt deleted file mode 100644 index c80fcec00..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.2.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHQTCCBSmgAwIBAgIUCowT7Q98oPLpaLF0FnUX3eobcgYwDQYJKoZIhvcNAQELBQAwczELMAkGA1UEBhMCQkUxGTAXBgNVBGEMEE5UUkJFLTA1Mzc2OTgzMTgxIDAeBgNVBAoMF1F1b1ZhZGlzIFRydXN0bGluayBCVkJBMScwJQYDVQQDDB5RdW9WYWRpcyBCZWxnaXVtIElzc3VpbmcgQ0EgRzIwHhcNMjEwMTIxMDg0ODIzWhcNMjQwMTIxMDg1ODAwWjCB0zELMAkGA1UEBhMCQkUxPzA9BgNVBAsMNkRHIGZvciBDb21tdW5pY2F0aW9ucyBOZXR3b3JrcywgQ29udGVudCBhbmQgVGVjaG5vbG9neTEZMBcGA1UEYQwQTlRSQkUtMDk0OTM4MzM0MjFKMEgGA1UECgxBQ09NTUlTU0lPTiBERSBMJ1VOSU9OIEVVUk9QRUVOTkUgLSBDT01NSVNTSUUgVkFOIERFIEVVUk9QRVNFIFVOSUUxHDAaBgNVBAMME0V1cm9wZWFuIENvbW1pc3Npb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtD1bnPz0vyI0gxH+Ye/UEyssx1TWyXmT2SjX8T0oR36yu+FvEI1YB7q7CGA2JNUxKdOPgFi4MZxj9vOoMwqR1+cbPDNzXsdzINLZCDy3mrPt3hfqmijhmqmwwXSQnO2+uDce+BYGXL74oWnqJTc+GT6SjYQMyeXvyff1JU4pC+QL53tcpcNf7dO5EJzHAfLDp8HILebtafvWAQA9+Psf3BT/0lHQZ1nqnyMfjBntCBG6/Cj2mtM44vldCKtRDdGno7MT5lxTvwoIcEA5Lupbdu9sudHsJT4iOub8QshI3bjHqP7n7q+OsN5RX5X/bmIG033j7Yn+DfwCKwE4eKsZHAgMBAAGjggJqMIICZjAfBgNVHSMEGDAWgBSHybwxlxJ6c7t+wD1FUbQBJZVRqzB3BggrBgEFBQcBAQRrMGkwOAYIKwYBBQUHMAKGLGh0dHA6Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZiZWNhZzIuY3J0MC0GCCsGAQUFBzABhiFodHRwOi8vdXcub2NzcC5xdW92YWRpc2dsb2JhbC5jb20wWgYDVR0gBFMwUTBEBgorBgEEAb5YAYMQMDYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwCQYHBACL7EABAzApBgNVHSUEIjAgBggrBgEFBQcDAgYIKwYBBQUHAwQGCisGAQQBgjcKAwwwgYsGCCsGAQUFBwEDBH8wfTAVBggrBgEFBQcLAjAJBgcEAIvsSQECMAgGBgQAjkYBATAIBgYEAI5GAQQwEwYGBACORgEGMAkGBwQAjkYBBgIwOwYGBACORgEFMDEwLxYpaHR0cHM6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkTAmVuMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwucXVvdmFkaXNnbG9iYWwuY29tL3F2YmVjYWcyLmNybDAdBgNVHQ4EFgQUSiKJPwxZvli51U75EfhdERrDf98wDgYDVR0PAQH/BAQDAgbAMBMGCiqGSIb3LwEBCQIEBTADAgEBMDQGCiqGSIb3LwEBCQEEJjAkAgEBhh9odHRwOi8vdHMucXVvdmFkaXNnbG9iYWwuY29tL2JlMA0GCSqGSIb3DQEBCwUAA4ICAQCWLVCxzkKy/s+8kRvxCPvTlExlWkNGsrhCO+PXsh1UgWMdJCpc33OzL1GegNMSL9f3Hw6gqjXV+mJqtTmvrP1ZvXCagv2LRLeyxSYAjlVjwYkaraddydS8Or86OyfA0OIs1UruPe0lClb6rBKwqqx7LvXotk7XvPYQo0HrP57pCqlp4MIiNEpGeW3gRwFq8IBQcecO3k009ad+tuTSB5I+o4t/7kEd//6voViy7d/EmlOgUZzXsJ24NV4pFAmyc2FlkEvYOqw8YvEsOV2hluvcG3wmkMEF/SY4X+kvpw+Ph7JQdWpWGlozzAFVppkIIrSM2Sxw2QXFQZWwah210HiVY0Ax4VkQbRJQNYmFWVizixPONWtc3PIfMz3/TvD9ZbExFfoQzVYXZPmtK2aQjG3CH2bJcefvS18YdR169au8yNKsPvlLaRa1k7Qv6Hv8iE3GtQmszDwnQHlGrbxdft306gOFl8/U0ctyIf2YkG6J/uTnYiiibeDoHK6wBo3BfCJQ2X7/Iab3971k1wSCwe39w4x3Xw72HL9E3czRkcfpg+uTxt5jSJ7HL7BRdMD34ysjQ4gOV8h6NU4z+QQ3W4sZTQkFqHGHKZKt2dTrCjhE+I1hULvo4274heBr/5F0DBAXRi9lHBCBUV5iJDm90bxjHjKuvj893WLEFW3WPkWlRw== ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.3.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.3.crt deleted file mode 100644 index 8b638ef92..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.3.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHLjCCBRagAwIBAgIUP4a8WPhZN++7VkfYyuAcDGmTglEwDQYJKoZIhvcNAQELBQAwczELMAkGA1UEBhMCQkUxGTAXBgNVBGEMEE5UUkJFLTA1Mzc2OTgzMTgxIDAeBgNVBAoMF1F1b1ZhZGlzIFRydXN0bGluayBCVkJBMScwJQYDVQQDDB5RdW9WYWRpcyBCZWxnaXVtIElzc3VpbmcgQ0EgRzIwHhcNMjEwMTIxMDg0ODM4WhcNMjQwMTIxMDg1ODAwWjCBwDELMAkGA1UEBhMCQkUxLDAqBgNVBAsMI0RpcmVjdG9yYXRlLUdlbmVyYWwgZm9yIEluZm9ybWF0aWNzMRkwFwYDVQRhDBBOVFJCRS0wOTQ5MzgzMzQyMUowSAYDVQQKDEFDT01NSVNTSU9OIERFIEwnVU5JT04gRVVST1BFRU5ORSAtIENPTU1JU1NJRSBWQU4gREUgRVVST1BFU0UgVU5JRTEcMBoGA1UEAwwTRXVyb3BlYW4gQ29tbWlzc2lvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCq40SQWaqRkbc5nsdPjLKyxghYzBLJCmeN3/ndD5mMzhy9tsP8WOpsfi8CnMD5tasEEmS5Fj73DQ+sL9PIyfmLzBJVhuCyzwKpDiFAhAa+ec/LTyVRa6+oCh918ZUcPDVXpCtGA3t6WS0pCgrIJNkZequ2yIWUZxiyVOACYmkxmWhWnGe7LRaLv80PCI0QERL2BzV+mKb2tQylUphPPI8hd9LG9EwCvSSXv0tb4rK1C+lIcxuYsui7dNyfw9UHDBnuI5452c3O18N5+GSI9uiEmOI8s++fbubn61RskePhk3ISURPGIAeDKV9pCZezBGysq5IlNkC1C4AtYS2eKFcCAwEAAaOCAmowggJmMB8GA1UdIwQYMBaAFIfJvDGXEnpzu37APUVRtAEllVGrMHcGCCsGAQUFBwEBBGswaTA4BggrBgEFBQcwAoYsaHR0cDovL3RydXN0LnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdmJlY2FnMi5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6Ly91dy5vY3NwLnF1b3ZhZGlzZ2xvYmFsLmNvbTBaBgNVHSAEUzBRMEQGCisGAQQBvlgBgxAwNjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5xdW92YWRpc2dsb2JhbC5jb20vcmVwb3NpdG9yeTAJBgcEAIvsQAEDMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNwoDDDCBiwYIKwYBBQUHAQMEfzB9MBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGAjA7BgYEAI5GAQUwMTAvFilodHRwczovL3d3dy5xdW92YWRpc2dsb2JhbC5jb20vcmVwb3NpdG9yeRMCZW4wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5xdW92YWRpc2dsb2JhbC5jb20vcXZiZWNhZzIuY3JsMB0GA1UdDgQWBBQspnrB2Vq7SM99egtZxs2jZv1QOjAOBgNVHQ8BAf8EBAMCBsAwEwYKKoZIhvcvAQEJAgQFMAMCAQEwNAYKKoZIhvcvAQEJAQQmMCQCAQGGH2h0dHA6Ly90cy5xdW92YWRpc2dsb2JhbC5jb20vYmUwDQYJKoZIhvcNAQELBQADggIBACGQDYsjrM3nsKSpiW1SqzBlZOkvuiphSLNhv5o5V1W+maYLtXYH/fMadrP0+K2X5XB5e+8yMw4Sbrvxv4LRR/CQ2WX03KjYGcqdcIUAH+A/8phwA7eLyKd3ip8k8ukT9kUKMJxbqVR5O8x2vOlAM9VFirOenOI+MufFDSaNKIJKt+PDhcSxDyzjs2MRKHAJcTCs23T8fB6+Qvw3uKUgniVg4MTLFvWpL8bvMXX7QUyvsScskUCns918hHA4Ett7fxdWXJFFJuuculChJIf8jbXZQ/8SAoecPyADnJw0C4uGNI/zc9/DWqMSMMytFwGeOpQb0/pukdmNe3sai8SUQj4+vyhkCHKMD27cak9buDO7cu5yhKEuLCERTga2QvbGSeiFAa6KuyPGY1Ad9AOuz5KPyyfVG0h31FvNL0MnAib1IpZr7mPQgWOsEX9ipgQXoE2Rh11yydTiKwmyTTrp/uMOJp+6UD06IdgPkHmqnqaKkqzGu6RKiHLqYWX5qhWXt0EatHQ0YY+92B03cDTLMgjPHKY+wN6qPfetz0oQNmort+G2HIXb9P+Q43sqMjXpQY/I3YmM0VBmcYWUon11BOavnGGOCVVPBQFKU6Kt7r69li1CmfA7KgK7Jn2o/jb8BupWUPGej++MkkrFDS0T6tmNH9ZDteyO3dSyOcl1IHcs ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.4.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.4.crt deleted file mode 100644 index 6fb536c97..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.4.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIIBjCCBe6gAwIBAgIUS9jpmpft4GNImFU5UsO7UloSpHAwDQYJKoZIhvcNAQENBQAwXzELMAkGA1UEBhMCUFQxKjAoBgNVBAoMIURpZ2l0YWxTaWduIENlcnRpZmljYWRvcmEgRGlnaXRhbDEkMCIGA1UEAwwbRElHSVRBTFNJR04gUVVBTElGSUVEIENBIEcxMB4XDTIxMTAwMTA5MTI1OFoXDTIzMDQwOTA5MTI1OFowggFlMQswCQYDVQQGEwJCRTE9MDsGA1UECww0Q2VydGlmaWNhdGUgUHJvZmlsZSAtIFF1YWxpZmllZCBDZXJ0aWZpY2F0ZSAtIE1lbWJlcjEjMCEGA1UEYQwaTEVJWEctMjU0OTAwWk5ZQTFGTFVROVUzOTMxHDAaBgNVBAoME0VVUk9QRUFOIENPTU1JU1NJT04xIjAgBgNVBAsMGUVudGl0bGVtZW50IC0gRUMgT0ZGSUNJQUwxKDAmBgkqhkiG9w0BCQEWGWplcm9lbi5yYXRoZUBlYy5ldXJvcGEuZXUxHTAbBgNVBAUTFFBOT0JFLTU5Mi01NDQ0NzUwLTI3MQ4wDAYDVQQEDAVSQVRIRTEYMBYGA1UEKgwPSkVST0VOIEFSTk9MRCBMMR0wGwYDVQQLDBRSZW1vdGVRU0NETWFuYWdlbWVudDEeMBwGA1UEAwwVSkVST0VOIEFSTk9MRCBMIFJBVEhFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Xu4L2ZrE0heHhD4huf8MTgiMllyYIovFMV61b96MPAYELPRhaBIVHHF7w082rUdleHZ4zvmDVWtb0b9QGv+kx2KzXQMkOvsH7SvCUVrKZzzmwYFNynPMqEmO3XuCEbDY09Fvl5vaGjwn1US55T/CFA1354Gpa6cfn8KifOFyTLthjMwHPvbQOE4gmx07wW2CHwxt2PV/JPmD1aC4ZakkUNwgMCbG3igKRu8+pMVwWpmil3k1SSfxBLZ4gTchErFE5QyP6jC1iFkLJcX1r/Lgnv3quQrmaXKilLgYX6XnHajHp3Ay+VtXniMRp9mEjPAdYDMlrFZnqH5HtYaFPPI8wIDAQABo4ICsDCCAqwwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRzSfFAHBQEfJoSf/ovzVxnIxjpFDCBhAYIKwYBBQUHAQEEeDB2MEUGCCsGAQUFBzAChjlodHRwOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L0RJR0lUQUxTSUdOUVVBTElGSUVEQ0FHMS5wN2IwLQYIKwYBBQUHMAGGIWh0dHA6Ly9xY2EtZzEuZGlnaXRhbHNpZ24ucHQvb2NzcDAkBgNVHREEHTAbgRlqZXJvZW4ucmF0aGVAZWMuZXVyb3BhLmV1MF4GA1UdIARXMFUwNgYLKwYBBAGBx3wEAQEwJzAlBggrBgEFBQcCARYZaHR0cDovL3BraS5kaWdpdGFsc2lnbi5wdDAQBg4rBgEEAYHHfAQCAQEBBDAJBgcEAIvsQAECMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L0RJR0lUQUxTSUdOUVVBTElGSUVEQ0FHMS5jcmwwHQYDVR0OBBYEFAQUZzttq3ed0in70dPz6mTXzNtpMA4GA1UdDwEB/wQEAwIGQDCB0wYIKwYBBQUHAQMEgcYwgcMwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGATBqBgYEAI5GAQUwYDAuFihodHRwczovL3FjYS1nMS5kaWdpdGFsc2lnbi5wdC9QRFNfcHQucGRmEwJwdDAuFihodHRwczovL3FjYS1nMS5kaWdpdGFsc2lnbi5wdC9QRFNfZW4ucGRmEwJlbjAVBggrBgEFBQcLAjAJBgcEAIvsSQEBMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwDQYJKoZIhvcNAQENBQADggIBAFaBGQoOqqfTTBaj9pllS9IF7MdRM10ZgbB40ZLkZG6V8DtnrTQ9d0mOO+iF5FpNUVxl3u+LkQ3t7Hfw3keF5MPYhFgsNwEQOLTT88hv7r3kQITdrZBxi9kQZ/6DPNPhPlxCMP4awNgXVr0O8wzeIJ+9AoMwF06VgtiE16V5BH40hxIA09Evctk5KdvAtzaTN4C5dKD+1tEZ83mdpT+bd+JePnBImj0HW8Bpw6hKJcLjzrO8bwetX81lATugjg1mFGcAafGDqfL8rkAcUW6T+mx9BYP9P/KOvojpor0j+FfOFJ1YN/bHjKGNrjylPiVtIqcs4ftz/x4oY8leKn/CDDyg96QIlKekBP65uPRxSikUoIeFj1/zoRU+ge2mlsOxO4yGCj/kw7gcBGZOHUWM09HtjAibOXbgQc1YcTcu1YYaesJFaZAqSkX3o6Y2+lXIEoFdVrZmi38b9PDw9QgGNHyp5K8ysrnoZZTw40cjdp7dBQLd4OmsxsYXnFah+UQXLMuDtDlwI5a83UiodqCYKDZ6ZjeN7v3uVsCUl4B5e96WRtllN3feQct+rFIQJM8FQdFflk1NbC5Dye2cq15YXXAo6EeB5jxIbUTrP4Kr1luao9owJKy43Mh3F6kpGd2mMc3mz1jsst0DrSPtNA4brFOpp3KwRHlbDcadiiJZaes8 ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.5.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.5.crt deleted file mode 100644 index 86c0e9be8..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.5.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIH8DCCBdigAwIBAgIUAqEFRGIiNgocV6sZ4jm3XSys6YowDQYJKoZIhvcNAQENBQAwXzELMAkGA1UEBhMCUFQxKjAoBgNVBAoMIURpZ2l0YWxTaWduIENlcnRpZmljYWRvcmEgRGlnaXRhbDEkMCIGA1UEAwwbRElHSVRBTFNJR04gUVVBTElGSUVEIENBIEcxMB4XDTIxMDkzMDE4NTYxN1oXDTI0MDUxMDE4NTYxN1owggFKMQswCQYDVQQGEwJHUjE9MDsGA1UECww0Q2VydGlmaWNhdGUgUHJvZmlsZSAtIFF1YWxpZmllZCBDZXJ0aWZpY2F0ZSAtIE1lbWJlcjEjMCEGA1UEYQwaTEVJWEctMjU0OTAwWk5ZQTFGTFVROVUzOTMxHDAaBgNVBAoME0VVUk9QRUFOIENPTU1JU1NJT04xKTAnBgNVBAsMIEVudGl0bGVtZW50IC0gRUMgU1RBVFVUT1JZIFNUQUZGMS0wKwYJKoZIhvcNAQkBFh5hcG9zdG9sb3MuYXBsYWRhc0BlYy5ldXJvcGEuZXUxEDAOBgNVBAQMB0FQTEFEQVMxEjAQBgNVBCoMCUFQT1NUT0xPUzEdMBsGA1UECwwUUmVtb3RlUVNDRE1hbmFnZW1lbnQxGjAYBgNVBAMMEUFQT1NUT0xPUyBBUExBREFTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsARkOHMiUr+4vsKLAoiP6X4tHeVs0Y59wqRdYwAg+ebeb0ubiNmGzGDMxeunvk8BwJEWnu2Qi+yzTrcbpPhNPTJam1PyhIzxRnbETM27JjrC5AyKHsQ29SbuBJA0cnh36HIetOzLoo23PCfaOBKvSQw+HAJecw5XsEE+YWC+tuBDgRFTVnxobUpGJMcvmmztLdo3SCjvuRTuCRNJEmBDY0WhmK9A98bUFgWir0KDVgP8h1plkZi33pL7Rv/104OQwE8Q4cDq8TCZqZ6xYNlDx6eTZcwzVLniwvds+EhAJhqgkTL7m56r4qkfiFgozy8RdP0gheb8Ob/EyYNFfVW/YQIDAQABo4ICtTCCArEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRzSfFAHBQEfJoSf/ovzVxnIxjpFDCBhAYIKwYBBQUHAQEEeDB2MEUGCCsGAQUFBzAChjlodHRwOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L0RJR0lUQUxTSUdOUVVBTElGSUVEQ0FHMS5wN2IwLQYIKwYBBQUHMAGGIWh0dHA6Ly9xY2EtZzEuZGlnaXRhbHNpZ24ucHQvb2NzcDApBgNVHREEIjAggR5hcG9zdG9sb3MuYXBsYWRhc0BlYy5ldXJvcGEuZXUwXgYDVR0gBFcwVTA2BgsrBgEEAYHHfAQBATAnMCUGCCsGAQUFBwIBFhlodHRwOi8vcGtpLmRpZ2l0YWxzaWduLnB0MBAGDisGAQQBgcd8BAIBAQEEMAkGBwQAi+xAAQIwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly9xY2EtZzEuZGlnaXRhbHNpZ24ucHQvRElHSVRBTFNJR05RVUFMSUZJRURDQUcxLmNybDAdBgNVHQ4EFgQUTK7kKcckq1yO29zWWVbTXsoQDNswDgYDVR0PAQH/BAQDAgZAMIHTBggrBgEFBQcBAwSBxjCBwzAIBgYEAI5GAQEwCAYGBACORgEEMBMGBgQAjkYBBjAJBgcEAI5GAQYBMGoGBgQAjkYBBTBgMC4WKGh0dHBzOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L1BEU19wdC5wZGYTAnB0MC4WKGh0dHBzOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L1BEU19lbi5wZGYTAmVuMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQEwFQYIKwYBBQUHCwIwCQYHBACL7EkBAjANBgkqhkiG9w0BAQ0FAAOCAgEAJu2ay08mPKn2pS/Mc96oRLsQxEAlx7baADy3Pe9p1DBdmXXDkuTCLH4P2ALzrPRRlgrTnQ5w7ORxnZw6pNZyBj/d3yQutsLlkJnjmxBhR76eqgGft/+l4eiwRUPyUi01KSCaLSf1mYocvgJgmjdQljpoeOeb6n7Ua8tY7aflWPgI7o8tbTLyMSb4Lh2ZcYqTgV65ZxHD6IfWu1/m7GzKeTLE1+lNJxjjLRgkloQHUAe8bKyugMJW21i1PELrhSp1LUie5Yknq/F2lN7bl9AK+cAWDfxUQhtq3EI3gkkn3Nd80sTbua0cn9GNWpSJhd82/fiCgHEoOl9LqWpRJ567RffnYrmvdY5HwzB4UmDWsFAVUKsBwpbl22S2zL9/+yDIYdW6Jw7jXCQqFenSDD49PK1wb/Ciq6zRs3SsKYI/aXLD98m/My7s1E8+x35zwy3TxGU48HZCc4/hquYdml9LPahdGomyxTHiKTAgGPAynB9Ym+Hx4DRSmUINExRZWA9FEH/2F8B9BealgjydlNDB/+5HIhP59YU0tG0IgS5IrEJ49ESIPov1NiUQlalNPQp8xLyu+TmTIZ3n43bcdoJofb8AFawB2jkDCSdz8flikPlhdS336hWMrm6G38RsKu/XpXyyK05+UeLpeYu2YOutn7bUVKlyWLZsaS59kwaIibY= ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.6.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.6.crt deleted file mode 100644 index 31b29a598..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.6.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIH9zCCBd+gAwIBAgIUZ4GvxB1xSYD0tYMFVW6FuCrHaX8wDQYJKoZIhvcNAQENBQAwXzELMAkGA1UEBhMCUFQxKjAoBgNVBAoMIURpZ2l0YWxTaWduIENlcnRpZmljYWRvcmEgRGlnaXRhbDEkMCIGA1UEAwwbRElHSVRBTFNJR04gUVVBTElGSUVEIENBIEcxMB4XDTIxMDkyOTA5NDUzNFoXDTIzMDkyNjA5NDUzNFowggFTMQswCQYDVQQGEwJSTzE9MDsGA1UECww0Q2VydGlmaWNhdGUgUHJvZmlsZSAtIFF1YWxpZmllZCBDZXJ0aWZpY2F0ZSAtIE1lbWJlcjEjMCEGA1UEYQwaTEVJWEctMjU0OTAwWk5ZQTFGTFVROVUzOTMxHDAaBgNVBAoME0VVUk9QRUFOIENPTU1JU1NJT04xIjAgBgNVBAsMGUVudGl0bGVtZW50IC0gRUMgT0ZGSUNJQUwxKzApBgkqhkiG9w0BCQEWHGFkcmlhbi5jcm9pdG9ydUBlYy5ldXJvcGEuZXUxETAPBgNVBAQMCENST0lUT1JVMRowGAYDVQQqDBFDT05TVEFOVElOLUFEUklBTjEdMBsGA1UECwwUUmVtb3RlUVNDRE1hbmFnZW1lbnQxIzAhBgNVBAMMGkNPTlNUQU5USU4tQURSSUFOIENST0lUT1JVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAutg6RcTrmbtcPoxGSoMC1O5+151zAdaw21AklQOnkEMKC8aa5d4utJ3nfiQVIGRd6tFGu8hb8osuxzYEb6ycz5y/OiRVUkr96Gi7LzEv/lIFduIAQMmr+FATvolw+QBuId8WJJaVW04/h+DrEPmbXmx8AoNrrSTeJcQanm5gZy5jaDT/fD3cJYpedkAE9XaiLmfv4LnvOvnAHuIVeY+LXvrdLVFtSCn7Y37b0GwVWTUCkvhwY1xoJm1fgM/OLxfN0SFBHFihRPD2qPHdnu/CxH4/CLvEZM2IjJAPgUxIwbJy32IuiIfadTAeHavzNM1ND/sQnKypeDH1WiaeMPsw4QIDAQABo4ICszCCAq8wDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRzSfFAHBQEfJoSf/ovzVxnIxjpFDCBhAYIKwYBBQUHAQEEeDB2MEUGCCsGAQUFBzAChjlodHRwOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L0RJR0lUQUxTSUdOUVVBTElGSUVEQ0FHMS5wN2IwLQYIKwYBBQUHMAGGIWh0dHA6Ly9xY2EtZzEuZGlnaXRhbHNpZ24ucHQvb2NzcDAnBgNVHREEIDAegRxhZHJpYW4uY3JvaXRvcnVAZWMuZXVyb3BhLmV1MF4GA1UdIARXMFUwNgYLKwYBBAGBx3wEAQEwJzAlBggrBgEFBQcCARYZaHR0cDovL3BraS5kaWdpdGFsc2lnbi5wdDAQBg4rBgEEAYHHfAQCAQEBBDAJBgcEAIvsQAECMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vcWNhLWcxLmRpZ2l0YWxzaWduLnB0L0RJR0lUQUxTSUdOUVVBTElGSUVEQ0FHMS5jcmwwHQYDVR0OBBYEFEX0uDZwuEHxACmOXaqMx5LPtDckMA4GA1UdDwEB/wQEAwIGQDCB0wYIKwYBBQUHAQMEgcYwgcMwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGATBqBgYEAI5GAQUwYDAuFihodHRwczovL3FjYS1nMS5kaWdpdGFsc2lnbi5wdC9QRFNfcHQucGRmEwJwdDAuFihodHRwczovL3FjYS1nMS5kaWdpdGFsc2lnbi5wdC9QRFNfZW4ucGRmEwJlbjAVBggrBgEFBQcLAjAJBgcEAIvsSQEBMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwDQYJKoZIhvcNAQENBQADggIBAKF6Q6g4u86Hn82VaGln6rE2j+R99+suz9104deM187rlqKa5uU45QUmcYgE+3VoSDVucOMBzwRyYj3lqZvLbJe9fdJ+LNM4Si2U9X/Z0iyE4OHmMMzc+kr5ZtUCaUKZATkLKWqZpOHmi+ZT6LUXTHmZVBNv0hE45lMqg+JSeZsRPPBso4qhxHTqDDHDSoHYABtRnd4NYUCcwAZRI/rkiirfKUxZ5lHkTd19JkTfCNM3Fmgsu1Mpf8cvQkzqESyl19fJxcTJL6xjzAxJ+kfa1pE9DCIzRfZJso9CczJzo1ef/nLGamx6RN+FjMuG0jSIfoBqx/Niq7iUNuedxtlTpys65ZBPx4JuR5/bwFrv9ysLm2STx4QKENXA7Bg8o4hvVg23ktJ9n/nAhNe1WrjZfrotFenTO+w73o5S1iTZWGppW9/972fwlVUO6o5QHQ3b6IrPf2iYAcAlUI2GcC7hzZsqVQ6kd9WoZYrpf5BmLNQbXZMx5wfX5v0I6cckluoK7eb150+OIA3GgvDG8m7GT/g9wXYFSMzknyiwSiFM2rP3wtZc1MwzA2I8We0ypXWEBf4ArynJtXgy7y0BBvKu1kuaAJ6++O6z1oOW4wjJnQtOjNQcdzPzRcpPf9ewuoOQdGKETjejCGYwi6g2+JNgx4jTAlBEhhrA2ZDFgYmGitF4 ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.7.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.7.crt deleted file mode 100644 index ace457bbe..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.7.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIH4DCCBsigAwIBAgIQcuGOs8Fyv7YDW1ZyZ14GnzANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCUFQxLDAqBgNVBAoTI0RpZ2l0YWxTaWduIC0gQ2VydGlmaWNhZG9yYSBEaWdpdGFsMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTUwMwYDVQQLEyxDbGFzcyAyIE1hbmFnZWQgUEtJIEluZGl2aWR1YWwgU3Vic2NyaWJlciBDQTEmMCQGA1UEAxMdRGlnaXRhbFNpZ24gUXVhbGlmaWVkIENBIC0gRzMwHhcNMjAwNzA2MDAwMDAwWhcNMjMwNzA2MjM1OTU5WjCCAXoxCzAJBgNVBAYTAkdSMRwwGgYDVQQKFBNFVVJPUEVBTiBDT01NSVNTSU9OMRkwFwYDVQRhFBBWQVRCRS0wOTQ5MzgzMzQyMT0wOwYDVQQLEzRDZXJ0aWZpY2F0ZSBQcm9maWxlIC0gUXVhbGlmaWVkIENlcnRpZmljYXRlIC0gTWVtYmVyMUUwQwYDVQQLEzxUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9ycGExIjAgBgNVBAsUGUVudGl0bGVtZW50IC0gRUMgT0ZGSUNJQUwxKzApBgkqhkiG9w0BCQEWHGdlb3JnaW9zLmxhcHBhc0BlYy5ldXJvcGEuZXUxDzANBgNVBAQUBkxBUFBBUzERMA8GA1UEKhQIR0VPUkdJT1MxHTAbBgNVBAsUFFJlbW90ZVFTQ0RNYW5hZ2VtZW50MRgwFgYDVQQDFA9HRU9SR0lPUyBMQVBQQVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLmkGUsomW+QoxIwY+nH5XRW6DDvVXoDYJnM4a0R/sGmlAQgosfa8yrGmVSWxDRoXxUAlNKzXd1yGmPi6gSW6rMIWyZsxIldNAvYKTJdKDCSGRfScit0hrbkrCTydOfML7E+R5gTUTa02kRuwg08ZzwQ7B5rvOoIjVBCZM5Z2BrPpShB/8qZHINbfMEByPbw85ia70EPXhS8Xc64z6PE5X6ow5gok+WgH298lSEVuB9HJN1BtcBsyiGpVjZmRpwsprEzkYEcUoLxv1THXVdwVQIoq9yrG4HjXgxbv14LGE85vgUvl48wk3D5wb/RaVO8k0V9gle4aa0r4tOHekb/mdAgMBAAGjggMcMIIDGDAJBgNVHRMEAjAAMHMGA1UdHwRsMGowaKBmoGSGYmh0dHA6Ly9vbnNpdGVjcmwudHJ1c3R3aXNlLmNvbS9EaWdpdGFsU2lnbkNlcnRpZmljYWRvcmFEaWdpdGFsUXVhbGlmaWVkQ2VydGlmaWNhdGVHMy9MYXRlc3RDUkwuY3JsMA4GA1UdDwEB/wQEAwIGQDBuBgNVHSAEZzBlMEkGC2CGSAGG+EUBBxcCMDowOAYIKwYBBQUHAgEWLGh0dHBzOi8vd3d3LmRpZ2l0YWxzaWduLnB0L0VDRElHSVRBTFNJR04vY3BzMA0GC2CGSAGG+EUBBywCMAkGBwQAi+xAAQIwHQYDVR0OBBYEFI8V/EJXhRFSHE3lMSwoiF/2F2wMMB8GA1UdIwQYMBaAFPtejkKcI6h99BuMXHw7GKvZ2fdAMCcGA1UdEQQgMB6BHGdlb3JnaW9zLmxhcHBhc0BlYy5ldXJvcGEuZXUwgeYGCCsGAQUFBwEDBIHZMIHWMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQEwFQYIKwYBBQUHCwIwCQYHBACL7EkBAjAIBgYEAI5GAQEwCAYGBACORgEEMBMGBgQAjkYBBjAJBgcEAI5GAQYBMH0GBgQAjkYBBTBzMDYWMGh0dHBzOi8vd3d3LmRpZ2l0YWxzaWduLnB0L0VDRElHSVRBTFNJR04vY3BzL2RkcBMCUFQwORYzaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9jcHMvZGRwX2VuEwJFTjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwgaQGCCsGAQUFBwEBBIGXMIGUMCkGCCsGAQUFBzABhh1odHRwOi8vc3RkLW9jc3AudHJ1c3R3aXNlLmNvbTBnBggrBgEFBQcwAoZbaHR0cDovL29uc2l0ZWNybC50cnVzdHdpc2UuY29tL0RpZ2l0YWxTaWduQ2VydGlmaWNhZG9yYURpZ2l0YWxRdWFsaWZpZWRDZXJ0aWZpY2F0ZUczL2NhLmNydDANBgkqhkiG9w0BAQsFAAOCAQEAd9KFwXgDLoLNjXxhovrQ7KnzzwN1ywPINZqQ+TxSW+aHGsttR6jMI67pULkjQEkm7mKo3RdiGS+MmQ70HTSgWbOMq8IpbAXSb8B4JT8S8PXsKQ2qoEd2szbJ9UCPm+vJ0+C9PI7ISD+yOJtIz+q15qvMp4jOBLCmn1k/geTZC3hgK90b96HiDEcXhhpzGJgHOA1R3ScqJ7UKklUyt4xYuBAAbcSLUZ159tn0mAEXYUrYafjdgWTlLe7MEWIBwPNVcMK2Mnv8cuzibED99JKGevHnY6GrE+4vmqn4Y0NyrNu5MbPO12XweDACPzZQIzUbmJsy21LpjVbCWgFNI4PFJA== ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.8.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.8.crt deleted file mode 100644 index 33bc776b5..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.8.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIIBTCCBu2gAwIBAgIQG233GXjL5UvTeIT2PvwMkTANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCUFQxLDAqBgNVBAoTI0RpZ2l0YWxTaWduIC0gQ2VydGlmaWNhZG9yYSBEaWdpdGFsMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTUwMwYDVQQLEyxDbGFzcyAyIE1hbmFnZWQgUEtJIEluZGl2aWR1YWwgU3Vic2NyaWJlciBDQTEmMCQGA1UEAxMdRGlnaXRhbFNpZ24gUXVhbGlmaWVkIENBIC0gRzMwHhcNMjAwNDA4MDAwMDAwWhcNMjMwNDA4MjM1OTU5WjCCAaIxCzAJBgNVBAYTAkJFMRwwGgYDVQQKFBNFVVJPUEVBTiBDT01NSVNTSU9OMRkwFwYDVQRhFBBWQVRCRS0wOTQ5MzgzMzQyMT0wOwYDVQQLEzRDZXJ0aWZpY2F0ZSBQcm9maWxlIC0gUXVhbGlmaWVkIENlcnRpZmljYXRlIC0gTWVtYmVyMUUwQwYDVQQLEzxUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9ycGExIjAgBgNVBAsUGUVudGl0bGVtZW50IC0gRUMgT0ZGSUNJQUwxKDAmBgkqhkiG9w0BCQEWGWplcm9lbi5yYXRoZUBlYy5ldXJvcGEuZXUxHTAbBgNVBAUTFFBOT0JFLTU5Mi01NDQ0NzUwLTI3MQ4wDAYDVQQEFAVSQVRIRTEYMBYGA1UEKhQPSkVST0VOIEFSTk9MRCBMMR0wGwYDVQQLFBRSZW1vdGVRU0NETWFuYWdlbWVudDEeMBwGA1UEAxQVSkVST0VOIEFSTk9MRCBMIFJBVEhFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Xu4L2ZrE0heHhD4huf8MTgiMllyYIovFMV61b96MPAYELPRhaBIVHHF7w082rUdleHZ4zvmDVWtb0b9QGv+kx2KzXQMkOvsH7SvCUVrKZzzmwYFNynPMqEmO3XuCEbDY09Fvl5vaGjwn1US55T/CFA1354Gpa6cfn8KifOFyTLthjMwHPvbQOE4gmx07wW2CHwxt2PV/JPmD1aC4ZakkUNwgMCbG3igKRu8+pMVwWpmil3k1SSfxBLZ4gTchErFE5QyP6jC1iFkLJcX1r/Lgnv3quQrmaXKilLgYX6XnHajHp3Ay+VtXniMRp9mEjPAdYDMlrFZnqH5HtYaFPPI8wIDAQABo4IDGTCCAxUwCQYDVR0TBAIwADBzBgNVHR8EbDBqMGigZqBkhmJodHRwOi8vb25zaXRlY3JsLnRydXN0d2lzZS5jb20vRGlnaXRhbFNpZ25DZXJ0aWZpY2Fkb3JhRGlnaXRhbFF1YWxpZmllZENlcnRpZmljYXRlRzMvTGF0ZXN0Q1JMLmNybDAOBgNVHQ8BAf8EBAMCBkAwbgYDVR0gBGcwZTBJBgtghkgBhvhFAQcXAjA6MDgGCCsGAQUFBwIBFixodHRwczovL3d3dy5kaWdpdGFsc2lnbi5wdC9FQ0RJR0lUQUxTSUdOL2NwczANBgtghkgBhvhFAQcsAjAJBgcEAIvsQAECMB0GA1UdDgQWBBQEFGc7bat3ndIp+9HT8+pk18zbaTAfBgNVHSMEGDAWgBT7Xo5CnCOoffQbjFx8Oxir2dn3QDAkBgNVHREEHTAbgRlqZXJvZW4ucmF0aGVAZWMuZXVyb3BhLmV1MIHmBggrBgEFBQcBAwSB2TCB1jAVBggrBgEFBQcLAjAJBgcEAIvsSQEBMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGATB9BgYEAI5GAQUwczA2FjBodHRwczovL3d3dy5kaWdpdGFsc2lnbi5wdC9FQ0RJR0lUQUxTSUdOL2Nwcy9kZHATAlBUMDkWM2h0dHBzOi8vd3d3LmRpZ2l0YWxzaWduLnB0L0VDRElHSVRBTFNJR04vY3BzL2RkcF9lbhMCRU4wHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGkBggrBgEFBQcBAQSBlzCBlDApBggrBgEFBQcwAYYdaHR0cDovL3N0ZC1vY3NwLnRydXN0d2lzZS5jb20wZwYIKwYBBQUHMAKGW2h0dHA6Ly9vbnNpdGVjcmwudHJ1c3R3aXNlLmNvbS9EaWdpdGFsU2lnbkNlcnRpZmljYWRvcmFEaWdpdGFsUXVhbGlmaWVkQ2VydGlmaWNhdGVHMy9jYS5jcnQwDQYJKoZIhvcNAQELBQADggEBAHH5v7PtqFP0Nh5E1503NU9TTtnLHF2fzEfJ0xF14dpQ/90Shbn3F1/D7rwX6lyvRPIXvNmb0aN0xQ+y1rjB44znnLdGLFND9gx3Y8BR4edAR+2IxhznjT/6du0g2BKiOmJP/4bl65Cy9mJz5qeHzxXr9Y/W4FUy2m1IxQze9/nFdMtD2Yzj/fgsV9brikF5dIz2yIzE6E/FYaa85M4W770Ep6WlemeilUbDfjws2zDi0gR7sksNzMe3HWVtl0eNf5zj3HIXxGe9jTBG83jm4ppO13K7KEFLlnaJdoYDp6zY8x6KNjhFH0N8YoofsCG83cO8CUSHczD3PuBQVOl0Qu8= ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.9.crt b/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.9.crt deleted file mode 100644 index bc358757f..000000000 --- a/digidoc4j/src/main/resources/keystore/keystore_certs/ec.europa.eu.9.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIIBTCCBu2gAwIBAgIQMC0qZHRS96hQhJJbKgWexzANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCUFQxLDAqBgNVBAoTI0RpZ2l0YWxTaWduIC0gQ2VydGlmaWNhZG9yYSBEaWdpdGFsMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTUwMwYDVQQLEyxDbGFzcyAyIE1hbmFnZWQgUEtJIEluZGl2aWR1YWwgU3Vic2NyaWJlciBDQTEmMCQGA1UEAxMdRGlnaXRhbFNpZ24gUXVhbGlmaWVkIENBIC0gRzMwHhcNMTkxMjA2MDAwMDAwWhcNMjIxMjA1MjM1OTU5WjCCAZ0xCzAJBgNVBAYTAkdSMRwwGgYDVQQKFBNFVVJPUEVBTiBDT01NSVNTSU9OMRkwFwYDVQRhFBBWQVRCRS0wOTQ5MzgzMzQyMT0wOwYDVQQLEzRDZXJ0aWZpY2F0ZSBQcm9maWxlIC0gUXVhbGlmaWVkIENlcnRpZmljYXRlIC0gTWVtYmVyMUUwQwYDVQQLEzxUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9ycGExJTAjBgNVBAsUHEVudGl0bGVtZW50IC0gRElHSVQgT0ZGSUNJQUwxLTArBgkqhkiG9w0BCQEWHmFwb3N0b2xvcy5hcGxhZGFzQGVjLmV1cm9wYS5ldTEYMBYGA1UEBRMPUEFTR1ItQVAzMTQxMDQyMRAwDgYDVQQEFAdBUExBREFTMRIwEAYDVQQqFAlBUE9TVE9MT1MxHTAbBgNVBAsUFFJlbW90ZVFTQ0RNYW5hZ2VtZW50MRowGAYDVQQDFBFBUE9TVE9MT1MgQVBMQURBUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO6xZV6fwwUkP0n6VLZJzXBbznMQ8JWtefuAIOdmdJ6MoFY+iiXLwlNZpLr/EQ4Hhcx3i2H0P4RCSfKDtPn3SuCn+tkZPNmavpJ+UMkQ38RKMErQ9uQGHeHqCsvrnQsE+2OpIlT2aLaGf/A29FkFGuugrq1EEY47KMYhcBn68lUG5teE/eGg7sYhwV4pFlLff9TULLLcmugVSlFjZmVrAMKcqp5GMj5VXzRjNwYJINTApSki44VBxvLlkoBcuncIsSj7CZxNWiHIsUNAGd8U+lxGSr7Bdlq9rjEj9Wxq6jbc0Xakf4HmfWT2lngPsdDIEgstBKlKGofjMqtJZpS2DlsCAwEAAaOCAx4wggMaMAkGA1UdEwQCMAAwcwYDVR0fBGwwajBooGagZIZiaHR0cDovL29uc2l0ZWNybC50cnVzdHdpc2UuY29tL0RpZ2l0YWxTaWduQ2VydGlmaWNhZG9yYURpZ2l0YWxRdWFsaWZpZWRDZXJ0aWZpY2F0ZUczL0xhdGVzdENSTC5jcmwwDgYDVR0PAQH/BAQDAgZAMG4GA1UdIARnMGUwSQYLYIZIAYb4RQEHFwIwOjA4BggrBgEFBQcCARYsaHR0cHM6Ly93d3cuZGlnaXRhbHNpZ24ucHQvRUNESUdJVEFMU0lHTi9jcHMwDQYLYIZIAYb4RQEHLAIwCQYHBACL7EABAjAdBgNVHQ4EFgQU9XRI9OH2TD8LIbkA9yWDZwVh01gwHwYDVR0jBBgwFoAU+16OQpwjqH30G4xcfDsYq9nZ90AwKQYDVR0RBCIwIIEeYXBvc3RvbG9zLmFwbGFkYXNAZWMuZXVyb3BhLmV1MIHmBggrBgEFBQcBAwSB2TCB1jAVBggrBgEFBQcLAjAJBgcEAIvsSQEBMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwCAYGBACORgEBMAgGBgQAjkYBBDATBgYEAI5GAQYwCQYHBACORgEGATB9BgYEAI5GAQUwczA2FjBodHRwczovL3d3dy5kaWdpdGFsc2lnbi5wdC9FQ0RJR0lUQUxTSUdOL2Nwcy9kZHATAlBUMDkWM2h0dHBzOi8vd3d3LmRpZ2l0YWxzaWduLnB0L0VDRElHSVRBTFNJR04vY3BzL2RkcF9lbhMCRU4wHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGkBggrBgEFBQcBAQSBlzCBlDApBggrBgEFBQcwAYYdaHR0cDovL3N0ZC1vY3NwLnRydXN0d2lzZS5jb20wZwYIKwYBBQUHMAKGW2h0dHA6Ly9vbnNpdGVjcmwudHJ1c3R3aXNlLmNvbS9EaWdpdGFsU2lnbkNlcnRpZmljYWRvcmFEaWdpdGFsUXVhbGlmaWVkQ2VydGlmaWNhdGVHMy9jYS5jcnQwDQYJKoZIhvcNAQELBQADggEBAFRKyVFYQIs8kXxsuyQ47BeoyKJ0JZEPqcgJWyUg3pJSeKdS50q3fcP9nll4Nlt3wFrYQdK6dO12nFg6cuuY+SVDafhpGtJV5TEetvRK84BkWab2RdaaGh3MJdcSV0shxan8rmknWf87qUkDt+1QrqLA3qTRT6/g/O7GASxFMQ4p88Vw6KoV6P9zIbcvejYI7IE/JdEmKA30zwaAc6pJ270v6YLFnDKrr9Rgfs6RZ6mG27XSMKOvb2Ax4+eUGCv57FFAA3FGLphsTQ9mkD4ztZwaSTmaUzvY2M5K65JJIjLpKbzdUulHbQGDhX79GTsmDKsAYdKZe+UacNFl/5Tx7ko= ------END CERTIFICATE----- \ No newline at end of file diff --git a/digidoc4j/src/main/resources/keystore/test-keystore.jks b/digidoc4j/src/main/resources/keystore/test-keystore.jks deleted file mode 100644 index 752ebf252..000000000 Binary files a/digidoc4j/src/main/resources/keystore/test-keystore.jks and /dev/null differ diff --git a/digidoc4j/src/main/resources/ssl/tsl_truststore.p12 b/digidoc4j/src/main/resources/ssl/tsl_truststore.p12 deleted file mode 100644 index b6672d377..000000000 Binary files a/digidoc4j/src/main/resources/ssl/tsl_truststore.p12 and /dev/null differ diff --git a/digidoc4j/src/main/resources/truststores/lotl-truststore.p12 b/digidoc4j/src/main/resources/truststores/lotl-truststore.p12 new file mode 100644 index 000000000..bd250a548 Binary files /dev/null and b/digidoc4j/src/main/resources/truststores/lotl-truststore.p12 differ diff --git a/digidoc4j/src/main/resources/truststores/test-lotl-truststore.p12 b/digidoc4j/src/main/resources/truststores/test-lotl-truststore.p12 new file mode 100644 index 000000000..989e7585b Binary files /dev/null and b/digidoc4j/src/main/resources/truststores/test-lotl-truststore.p12 differ diff --git a/digidoc4j/src/test/java/org/digidoc4j/AbstractTest.java b/digidoc4j/src/test/java/org/digidoc4j/AbstractTest.java index 76218f915..dcdf2f34a 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/AbstractTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/AbstractTest.java @@ -1,10 +1,21 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j; import eu.europa.esig.dss.enumerations.ObjectIdentifierQualifier; import eu.europa.esig.dss.model.DSSDocument; -import eu.europa.esig.dss.spi.DSSUtils; +import eu.europa.esig.dss.model.MimeType; import eu.europa.esig.dss.model.Policy; import eu.europa.esig.dss.service.tsp.OnlineTSPSource; +import eu.europa.esig.dss.spi.DSSUtils; import eu.europa.esig.dss.spi.client.http.DataLoader; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FileUtils; @@ -57,6 +68,7 @@ import java.nio.file.Paths; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -237,6 +249,41 @@ protected T createEmptyContainerBy(Container.DocumentType type, Class cla return (T) ContainerBuilder.aContainer(type).build(); } + @SuppressWarnings("unchecked") + protected T createContainer(DataFile... dataFiles) { + ContainerBuilder containerBuilder = ContainerBuilder.aContainer(); + Arrays.asList(dataFiles).forEach(containerBuilder::withDataFile); + return (T) containerBuilder.build(); + } + + @SuppressWarnings("unchecked") + protected T createContainer(Configuration configuration, DataFile... dataFiles) { + ContainerBuilder containerBuilder = ContainerBuilder.aContainer().withConfiguration(configuration); + Arrays.asList(dataFiles).forEach(containerBuilder::withDataFile); + return (T) containerBuilder.build(); + } + + @SuppressWarnings("unchecked") + protected T createContainer(Class clazz, DataFile... dataFiles) { + ContainerBuilder containerBuilder = ContainerBuilder.aContainer(); + Arrays.asList(dataFiles).forEach(containerBuilder::withDataFile); + return (T) containerBuilder.build(); + } + + @SuppressWarnings("unchecked") + protected T createContainerBy(Container.DocumentType type, DataFile... dataFiles) { + ContainerBuilder containerBuilder = ContainerBuilder.aContainer(type); + Arrays.asList(dataFiles).forEach(containerBuilder::withDataFile); + return (T) containerBuilder.build(); + } + + @SuppressWarnings("unchecked") + protected T createContainerBy(Container.DocumentType type, Class clazz, DataFile... dataFiles) { + ContainerBuilder containerBuilder = ContainerBuilder.aContainer(type); + Arrays.asList(dataFiles).forEach(containerBuilder::withDataFile); + return (T) containerBuilder.build(); + } + protected Container createNonEmptyContainer() { return this.createNonEmptyContainerBy(Container.DocumentType.BDOC); } @@ -387,18 +434,18 @@ protected T createSignatureBy(DigestAlgorithm digestAlgorithm, SignatureToke } } - protected String createSignedContainerBy(String extension) { + protected String createSignedContainerBy(Container.DocumentType type, String extension) { String file = this.getFileBy(extension); - Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); - this.createSignatureBy(container, pkcs12SignatureToken); - container.save(file); + Container container = this.createNonEmptyContainerBy(type, Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); + SignatureProfile signatureProfile = (type == BDOC) ? SignatureProfile.LT_TM : SignatureProfile.LT; + createSignatureBy(container, signatureProfile, pkcs12SignatureToken); + container.saveAsFile(file); return file; } protected String createNonEmptyLargeContainer(long size) { String fileName = this.getFileBy("bdoc"); - try { - RandomAccessFile largeFile = new RandomAccessFile(fileName, "rw"); + try (RandomAccessFile largeFile = new RandomAccessFile(fileName, "rw")) { largeFile.setLength(size);// TODO: create large file correctly } catch (Exception e) { throw new RuntimeException(e); @@ -431,6 +478,14 @@ protected List createDataFilesToSign() { return Collections.singletonList(new DataFile("src/test/resources/testFiles/helper-files/test.txt", "plain/text")); } + protected DataFile createBinaryDataFile(String fileName, byte[] fileContent) { + return new DataFile(fileContent, fileName, MimeType.BINARY.getMimeTypeString()); + } + + protected DataFile createTextDataFile(String fileName, String fileContent) { + return new DataFile(fileContent.getBytes(StandardCharsets.UTF_8), fileName, MimeType.TEXT.getMimeTypeString()); + } + protected void evictTSLCache() { TestTSLUtil.evictCache(); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java b/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java index c14b3f354..6e96dc972 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java @@ -1,52 +1,31 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; -import static org.digidoc4j.Constant.BDOC_CONTAINER_TYPE; -import static org.hamcrest.core.IsCollectionContaining.hasItem; -import static org.junit.Assert.assertFalse; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.FileTime; -import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - +import eu.europa.esig.dss.enumerations.KeyUsageBit; +import eu.europa.esig.dss.model.x509.CertificateToken; import eu.europa.esig.dss.spi.tsl.ConditionForQualifiers; import eu.europa.esig.dss.spi.tsl.TrustProperties; import eu.europa.esig.dss.spi.tsl.TrustServiceStatusAndInformationExtensions; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.digidoc4j.exceptions.ConfigurationException; -import org.digidoc4j.exceptions.DigiDoc4JException; +import org.digidoc4j.exceptions.LotlTrustStoreNotFoundException; import org.digidoc4j.exceptions.TslCertificateSourceInitializationException; -import org.digidoc4j.exceptions.TslKeyStoreNotFoundException; +import org.digidoc4j.exceptions.TslRefreshException; import org.digidoc4j.impl.asic.asice.bdoc.BDocContainer; import org.digidoc4j.impl.asic.tsl.TSLCertificateSourceImpl; import org.digidoc4j.impl.asic.tsl.TslLoader; +import org.digidoc4j.test.MockTSLRefreshCallback; +import org.digidoc4j.test.TestAssert; import org.digidoc4j.test.util.TestCommonUtil; import org.digidoc4j.test.util.TestFileUtil; import org.digidoc4j.test.util.TestTSLUtil; @@ -58,9 +37,28 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.europa.esig.dss.spi.tsl.Condition; -import eu.europa.esig.dss.enumerations.KeyUsageBit; -import eu.europa.esig.dss.model.x509.CertificateToken; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.junit.Assert.assertFalse; public class ConfigurationTest extends AbstractTest { @@ -70,9 +68,22 @@ public class ConfigurationTest extends AbstractTest { private static final String OCSP_PKCS_12_PASSWD = "DIGIDOC_PKCS12_PASSWD"; @Test - public void getTSLLocationWhenNotFileURL() { - String tslLocation = "URL:test"; + public void getLotlLocationWhenNotFileURL() { + String lotlLocation = "URL:test"; + this.configuration.setLotlLocation(lotlLocation); + Assert.assertEquals(lotlLocation, this.configuration.getLotlLocation()); + Assert.assertEquals(lotlLocation, this.configuration.getTslLocation()); + } + + @Test + public void lotlLocationAndTslLocationReferToTheSameValue() { + String lotlLocation = "URL:test"; + this.configuration.setLotlLocation(lotlLocation); + Assert.assertEquals(lotlLocation, this.configuration.getLotlLocation()); + Assert.assertEquals(lotlLocation, this.configuration.getTslLocation()); + String tslLocation = "URL:test2"; this.configuration.setTslLocation(tslLocation); + Assert.assertEquals(tslLocation, this.configuration.getLotlLocation()); Assert.assertEquals(tslLocation, this.configuration.getTslLocation()); } @@ -91,7 +102,7 @@ public void addTSL() { } @Test - public void addingCertificateToTsl() throws Exception { + public void addingCertificateToTsl() { TSLCertificateSource source = new TSLCertificateSourceImpl(); this.addCertificateToTSL(Paths.get("src/test/resources/testFiles/certs/Juur-SK.pem.crt"), source); CertificateToken certificateToken = source.getCertificates().get(0); @@ -170,7 +181,7 @@ public void clearTSLCache() throws Exception { } @Test - public void getTsl_whenCacheIsNotExpired_shouldUseCachedTsl() throws Exception { + public void getTsl_whenCacheIsNotExpired_shouldUseCachedTsl() { TestTSLUtil.evictCache(); this.configuration.setTslCacheExpirationTime(10000L); TSLCertificateSource tsl1 = this.configuration.getTSL(); @@ -184,7 +195,7 @@ public void getTsl_whenCacheIsNotExpired_shouldUseCachedTsl() throws Exception { } @Test - public void getTsl_whenCacheIsExpired_shouldDownloadNewTsl() throws Exception { + public void getTsl_whenCacheIsExpired_shouldDownloadNewTsl() { TestTSLUtil.evictCache(); configuration.setTslCacheExpirationTime(500L); TSLCertificateSource tsl = configuration.getTSL(); @@ -199,9 +210,9 @@ public void getTsl_whenCacheIsExpired_shouldDownloadNewTsl() throws Exception { } @Test - public void lotlValidationFailsWithWrongCertsInKeystore() { + public void lotlValidationFailsWithWrongCertsInTruststore() { this.configuration = new Configuration(Configuration.Mode.PROD); - this.configuration.setTslKeyStoreLocation("keystore/test-keystore.jks"); + this.configuration.setLotlTruststorePath("truststores/test-lotl-truststore.p12"); try { this.configuration.getTSL(); } catch (TslCertificateSourceInitializationException e) { @@ -209,15 +220,24 @@ public void lotlValidationFailsWithWrongCertsInKeystore() { } } - @Test - public void lotlLoadingWithNoLotlSslCertificateInTruststore() { + @Test(expected = TslRefreshException.class) + public void lotlLoadingWithNoLotlSslCertificateInTruststoreUsingDefaultTslCallback() { configuration.setSslTruststorePath("classpath:testFiles/truststores/empty-truststore.p12"); configuration.setSslTruststorePassword("digidoc4j-password"); configuration.setSslTruststoreType("PKCS12"); evictTSLCache(); configuration.getTSL().refresh(); + } + + @Test + public void lotlLoadingWithNoLotlSslCertificateInTruststoreUsingCustomTslCallback() { + configuration.setSslTruststorePath("classpath:testFiles/truststores/empty-truststore.p12"); + configuration.setSslTruststorePassword("digidoc4j-password"); + configuration.setSslTruststoreType("PKCS12"); + evictTSLCache(); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); ValidationResult validationResult = ContainerOpener.open("src/test/resources/prodFiles/valid-containers/valid_prod_bdoc_eid.bdoc", configuration).validate(); - Assert.assertTrue(validationResult.getErrors().stream().anyMatch(e -> "The certificate chain for signature is not trusted, it does not contain a trust anchor.".equals(e.getMessage()))); + TestAssert.assertContainsErrors(validationResult.getErrors(), "The certificate chain for signature is not trusted, it does not contain a trust anchor."); } @Test @@ -226,6 +246,7 @@ public void eeTlLoadingFailsWithNoEeTlSslCertificateInTruststore() { configuration.setSslTruststorePathFor(ExternalConnectionType.TSL, "src/test/resources/testFiles/truststores/lotl-ssl-only-truststore.p12"); configuration.setSslTruststorePasswordFor(ExternalConnectionType.TSL, "digidoc4j-password"); configuration.setSslTruststoreTypeFor(ExternalConnectionType.TSL, "PKCS12"); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); evictTSLCache(); ValidationResult validationResult = ContainerOpener.open("src/test/resources/prodFiles/valid-containers/valid_prod_bdoc_eid.bdoc", configuration).validate(); Assert.assertTrue("Certificate path should not be trusted", validationResult.getErrors().stream() @@ -233,7 +254,7 @@ public void eeTlLoadingFailsWithNoEeTlSslCertificateInTruststore() { } @Test - public void addedTSLIsValid() throws IOException, CertificateException { + public void addedTSLIsValid() { TSLCertificateSource source = this.configuration.getTSL(); this.addCertificateToTSL(Paths.get("src/test/resources/testFiles/certs/Juur-SK.pem.crt"), source); this.addCertificateToTSL(Paths.get("src/test/resources/testFiles/certs/EE_Certification_Centre_Root_CA.pem.crt"), source); @@ -251,32 +272,31 @@ public void policyFileIsReadFromNonDefaultFileLocation() { } @Test - public void TSLIsLoadedAfterSettingNewTSLLocation() { - this.configuration.setTslLocation("https://open-eid.github.io/test-TL/tl-mp-test-EE.xml"); - BDocContainer container = (BDocContainer) ContainerBuilder.aContainer(BDOC_CONTAINER_TYPE) + public void TSLIsLoadedAfterSettingNewLOTLLocation() throws Exception { + this.configuration.setLotlLocation("https://open-eid.github.io/test-TL/tl-mp-test-EE.xml"); + BDocContainer container = (BDocContainer) ContainerBuilder.aContainer(Container.DocumentType.BDOC) .withConfiguration(this.configuration).build(); container.getConfiguration().getTSL(); Assert.assertEquals(15, container.getConfiguration().getTSL().getCertificates().size()); - try { - int tenSeconds = 10000; - String tslHost = "10.0.25.57"; - if (InetAddress.getByName(tslHost).isReachable(tenSeconds)) { - this.configuration.setTslLocation("http://" + tslHost + "/tsl/trusted-test-mp.xml"); - container = (BDocContainer) ContainerBuilder.aContainer(BDOC_CONTAINER_TYPE). - withConfiguration(this.configuration).build(); - Assert.assertNotEquals(5, container.getConfiguration().getTSL().getCertificates().size()); - } else { - this.log.error("Host <{}> is unreachable", tslHost); - } - } catch (Exception e) { + + int tenSeconds = 10000; + String lotlHost = "10.0.25.57"; + if (InetAddress.getByName(lotlHost).isReachable(tenSeconds)) { + this.configuration.setLotlLocation("http://" + lotlHost + "/tsl/trusted-test-mp.xml"); + container = (BDocContainer) ContainerBuilder.aContainer(Container.DocumentType.BDOC). + withConfiguration(this.configuration).build(); + Assert.assertNotEquals(5, container.getConfiguration().getTSL().getCertificates().size()); + } else { + this.log.error("Host <{}> is unreachable", lotlHost); } } @Test - public void TSLFileNotFoundThrowsNoException() { - this.configuration.setTslLocation("file:test-tsl/NotExisting.xml"); + public void LOTLFileNotFoundThrowsNoException() { + this.configuration.setLotlLocation("file:test-lotl/NotExisting.xml"); + this.configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); BDocContainer container = (BDocContainer) ContainerBuilder. - aContainer(BDOC_CONTAINER_TYPE). + aContainer(Container.DocumentType.BDOC). withConfiguration(this.configuration). build(); container.getConfiguration().getTSL().refresh(); @@ -284,10 +304,11 @@ public void TSLFileNotFoundThrowsNoException() { } @Test - public void TSLConnectionFailureThrowsNoException() { - this.configuration.setTslLocation("http://127.0.0.1/tsl/incorrect.xml"); + public void LOTLConnectionFailureThrowsNoException() { + this.configuration.setLotlLocation("http://127.0.0.1/lotl/incorrect.xml"); + this.configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); BDocContainer container = (BDocContainer) ContainerBuilder. - aContainer(BDOC_CONTAINER_TYPE). + aContainer(Container.DocumentType.BDOC). withConfiguration(this.configuration). build(); container.getConfiguration().getTSL().refresh(); @@ -295,73 +316,90 @@ public void TSLConnectionFailureThrowsNoException() { } @Test - public void testLoadConfiguration() throws Exception { + public void testLoadConfiguration() { BDocContainer container = (BDocContainer) ContainerBuilder. - aContainer(BDOC_CONTAINER_TYPE). + aContainer(Container.DocumentType.BDOC). withConfiguration(this.configuration). build(); - Assert.assertFalse(container.getConfiguration().isBigFilesSupportEnabled()); + Assert.assertTrue(container.getConfiguration().storeDataFilesOnlyInMemory()); container.getConfiguration().loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); - Assert.assertTrue(container.getConfiguration().isBigFilesSupportEnabled()); + Assert.assertFalse(container.getConfiguration().storeDataFilesOnlyInMemory()); Assert.assertEquals(8192, container.getConfiguration().getMaxDataFileCachedInMB()); } @Test - public void whenTSLLocationIsMalformedURLNoErrorIsRaisedAndThisSameValueIsReturned() throws Exception { - String tslLocation = "file://C:\\"; - this.configuration.setTslLocation(tslLocation); - Assert.assertEquals(tslLocation, configuration.getTslLocation()); + public void whenLOTLLocationIsMalformedURLNoErrorIsRaisedAndThisSameValueIsReturned() { + String lotlLocation = "file://C:\\"; + this.configuration.setLotlLocation(lotlLocation); + Assert.assertEquals(lotlLocation, configuration.getLotlLocation()); } @Test - public void getTSLLocationFileDoesNotExistReturnsUrlPath() { - String tslLocation = ("file:conf/does-not-exist.xml"); - this.configuration.setTslLocation(tslLocation); - Assert.assertEquals(this.configuration.getTslLocation(), tslLocation); + public void getLOTLLocationFileDoesNotExistReturnsUrlPath() { + String lotlLocation = ("file:conf/does-not-exist.xml"); + this.configuration.setLotlLocation(lotlLocation); + Assert.assertEquals(this.configuration.getLotlLocation(), lotlLocation); } @Test - public void setTslLocation() throws Exception { + public void setLotlLocation() { + this.configuration.setLotlLocation("lotlLocation"); + Assert.assertEquals("lotlLocation", this.configuration.getLotlLocation()); + Assert.assertEquals("lotlLocation", this.configuration.getTslLocation()); + } + + @Test + public void setTslLocation() { this.configuration.setTslLocation("tslLocation"); + Assert.assertEquals("tslLocation", this.configuration.getLotlLocation()); Assert.assertEquals("tslLocation", this.configuration.getTslLocation()); } @Test - public void getTslLocationFromConfigurationFile() throws Exception { - this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); + public void getLotlLocationFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + Assert.assertEquals("TEST_LOTL_LOCATION", this.configuration.getLotlLocation()); + Assert.assertEquals("TEST_LOTL_LOCATION", this.configuration.getTslLocation()); + } + + @Test + public void getTslLocationFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml"); + Assert.assertEquals("file:conf/test_TSLLocation", this.configuration.getLotlLocation()); Assert.assertEquals("file:conf/test_TSLLocation", this.configuration.getTslLocation()); } @Test - public void setTslLocationOverwritesConfigurationFile() throws Exception { - this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); - this.configuration.setTslLocation("tslLocation"); - Assert.assertEquals("tslLocation", this.configuration.getTslLocation()); + public void setLotlLocationOverwritesConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + this.configuration.setLotlLocation("lotlLocation"); + Assert.assertEquals("lotlLocation", this.configuration.getLotlLocation()); + Assert.assertEquals("lotlLocation", this.configuration.getTslLocation()); } @Test - public void setTspSource() throws Exception { + public void setTspSource() { this.configuration.setTspSource("tspSource"); Assert.assertEquals("tspSource", this.configuration.getTspSource()); } @Test - public void setValidationPolicy() throws Exception { + public void setValidationPolicy() { this.configuration.setValidationPolicy("policy"); Assert.assertEquals("policy", this.configuration.getValidationPolicy()); } @Test - public void setOcspSource() throws Exception { + public void setOcspSource() { this.configuration.setOcspSource("ocsp_source"); Assert.assertEquals("ocsp_source", this.configuration.getOcspSource()); } @Test - public void setUseOcspNonce() throws Exception { - Assert.assertEquals(true, this.configuration.isOcspNonceUsed()); + public void setUseOcspNonce() { + Assert.assertTrue(this.configuration.isOcspNonceUsed()); this.configuration.setUseOcspNonce(false); - Assert.assertEquals(false, this.configuration.isOcspNonceUsed()); + Assert.assertFalse(this.configuration.isOcspNonceUsed()); } @Test @@ -378,8 +416,10 @@ public void getOCSPAccessCertificateFileFromConfigurationFile() { } @Test - public void getOCSPAccessCertificateFileFromStream() throws FileNotFoundException { - this.configuration.loadConfiguration(new FileInputStream("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml")); + public void getOCSPAccessCertificateFileFromStream() throws Exception { + try (InputStream inputStream = new FileInputStream("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml")) { + this.configuration.loadConfiguration(inputStream); + } Assert.assertEquals("conf/OCSP_access_certificate_test_file_name", this.configuration.getOCSPAccessCertificateFileName()); Assert.assertEquals("conf/OCSP_access_certificate_test_file_name", this.getDDoc4JConfigurationValue(OCSP_PKCS12_CONTAINER)); } @@ -399,7 +439,7 @@ public void defaultOCSPAccessCertificatePassword() { } @Test - public void getOCSPAccessCertificatePasswordFromConfigurationFile() throws Exception { + public void getOCSPAccessCertificatePasswordFromConfigurationFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertArrayEquals("OCSP_test_password".toCharArray(), this.configuration.getOCSPAccessCertificatePassword()); Assert.assertEquals("OCSP_test_password", this.getDDoc4JConfigurationValue(OCSP_PKCS_12_PASSWD)); @@ -415,20 +455,20 @@ public void setOCSPAccessCertificatePasswordOverwritesConfigurationFile() { } @Test - public void signingOcspRequest_ShouldBeDisabled_InProdByDefault() throws Exception { + public void signingOcspRequest_ShouldBeDisabled_InProdByDefault() { this.configuration = Configuration.of(Configuration.Mode.PROD); Assert.assertFalse(this.configuration.hasToBeOCSPRequestSigned()); Assert.assertEquals("false", this.getDDoc4JConfigurationValue(SIGN_OCSP_REQUESTS)); } @Test - public void signingOcspRequest_ShouldBeDisabled_InTestByDefault() throws Exception { + public void signingOcspRequest_ShouldBeDisabled_InTestByDefault() { Assert.assertFalse(this.configuration.hasToBeOCSPRequestSigned()); Assert.assertEquals("false", this.getDDoc4JConfigurationValue(SIGN_OCSP_REQUESTS)); } @Test - public void disableSigningOcspRequestsInProd() throws Exception { + public void disableSigningOcspRequestsInProd() { this.configuration = Configuration.of(Configuration.Mode.PROD); this.configuration.setSignOCSPRequests(false); Assert.assertFalse(this.configuration.hasToBeOCSPRequestSigned()); @@ -436,14 +476,14 @@ public void disableSigningOcspRequestsInProd() throws Exception { } @Test - public void enableSigningOcspRequestsInTest() throws Exception { + public void enableSigningOcspRequestsInTest() { this.configuration.setSignOCSPRequests(true); Assert.assertTrue(this.configuration.hasToBeOCSPRequestSigned()); Assert.assertEquals("true", this.getDDoc4JConfigurationValue(SIGN_OCSP_REQUESTS)); } @Test - public void loadDisableSigningOcspRequestFromConfFileInProd() throws Exception { + public void loadDisableSigningOcspRequestFromConfFileInProd() { this.configuration = Configuration.of(Configuration.Mode.PROD); this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertFalse(this.configuration.hasToBeOCSPRequestSigned()); @@ -451,41 +491,41 @@ public void loadDisableSigningOcspRequestFromConfFileInProd() throws Exception { } @Test - public void loadDisableSigningOcspRequestFromConfFile() throws Exception { + public void loadDisableSigningOcspRequestFromConfFile() { this.configuration.loadConfiguration(this.generateConfigurationByParameter("SIGN_OCSP_REQUESTS: false").getPath()); Assert.assertFalse(this.configuration.hasToBeOCSPRequestSigned()); Assert.assertEquals("false", this.getDDoc4JConfigurationValue(SIGN_OCSP_REQUESTS)); } @Test - public void loadEnableSigningOcspRequestFromConfFile() throws Exception { + public void loadEnableSigningOcspRequestFromConfFile() { this.configuration.loadConfiguration(this.generateConfigurationByParameter("SIGN_OCSP_REQUESTS: true").getPath()); Assert.assertTrue(configuration.hasToBeOCSPRequestSigned()); Assert.assertEquals("true", this.getDDoc4JConfigurationValue(SIGN_OCSP_REQUESTS)); } @Test - public void defaultOcspSource() throws Exception { + public void defaultOcspSource() { Assert.assertEquals("http://demo.sk.ee/ocsp", this.configuration.getOcspSource()); } @Test - public void defaultProductionConfiguration() throws Exception { + public void defaultProductionConfiguration() { this.configuration = Configuration.of(Configuration.Mode.PROD); Assert.assertEquals("https://ec.europa.eu/tools/lotl/eu-lotl.xml", - this.configuration.getTslLocation()); + this.configuration.getLotlLocation()); } @Test - public void defaultConstructorWithSetSystemProperty() throws Exception { + public void defaultConstructorWithSetSystemProperty() { this.configuration = new Configuration(); - Assert.assertEquals("https://open-eid.github.io/test-TL/tl-mp-test-EE.xml", this.configuration.getTslLocation()); + Assert.assertEquals("https://open-eid.github.io/test-TL/tl-mp-test-EE.xml", this.configuration.getLotlLocation()); } @Test - public void setMaxDataFileCached() throws Exception { + public void setMaxDataFileCached() { long maxDataFileCached = 12345; - this.configuration.enableBigFilesSupport(maxDataFileCached); + this.configuration.setMaxFileSizeCachedInMemoryInMB(maxDataFileCached); Assert.assertEquals(maxDataFileCached, this.configuration.getMaxDataFileCachedInMB()); Assert.assertEquals(maxDataFileCached * Constant.ONE_MB_IN_BYTES, this.configuration.getMaxDataFileCachedInBytes()); } @@ -493,7 +533,7 @@ public void setMaxDataFileCached() throws Exception { @Test public void setMaxDataFileCachedToNoCaching() { long maxDataFileCached = Constant.CACHE_NO_DATA_FILES; - this.configuration.enableBigFilesSupport(maxDataFileCached); + this.configuration.setMaxFileSizeCachedInMemoryInMB(maxDataFileCached); Assert.assertEquals(Constant.CACHE_NO_DATA_FILES, this.configuration.getMaxDataFileCachedInMB()); Assert.assertEquals(Constant.CACHE_NO_DATA_FILES, this.configuration.getMaxDataFileCachedInBytes()); } @@ -501,7 +541,7 @@ public void setMaxDataFileCachedToNoCaching() { @Test public void setMaxDataFileCachedToAllCaching() { long maxDataFileCached = Constant.CACHE_ALL_DATA_FILES; - this.configuration.enableBigFilesSupport(maxDataFileCached); + this.configuration.setMaxFileSizeCachedInMemoryInMB(maxDataFileCached); Assert.assertEquals(Constant.CACHE_ALL_DATA_FILES, this.configuration.getMaxDataFileCachedInMB()); Assert.assertEquals(Constant.CACHE_ALL_DATA_FILES, this.configuration.getMaxDataFileCachedInBytes()); } @@ -509,8 +549,8 @@ public void setMaxDataFileCachedToAllCaching() { @Test public void maxDataFileCachedNotAllowedValue() { long oldValue = 4096; - this.configuration.enableBigFilesSupport(oldValue); - this.configuration.enableBigFilesSupport(-2); + this.configuration.setMaxFileSizeCachedInMemoryInMB(oldValue); + this.configuration.setMaxFileSizeCachedInMemoryInMB(-2); Assert.assertEquals(oldValue, this.configuration.getMaxDataFileCachedInMB()); } @@ -524,15 +564,15 @@ public void maxDataFileCachedNotAllowedValueFromFile() { } @Test - public void defaultConstructorWithUnSetSystemProperty() throws Exception { + public void defaultConstructorWithUnSetSystemProperty() { this.clearGlobalMode(); this.configuration = new Configuration(); Assert.assertEquals("https://ec.europa.eu/tools/lotl/eu-lotl.xml", - this.configuration.getTslLocation()); + this.configuration.getLotlLocation()); } @Test - public void generateDDoc4JConfig() throws Exception { + public void generateDDoc4JConfig() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/main/resources/digidoc4j.yaml"); this.configuration.getDDoc4JConfiguration(); Assert.assertEquals("jar://certs/ESTEID-SK.crt", ddoc4jConf.get("DIGIDOC_CA_1_CERT2")); @@ -549,27 +589,26 @@ public void generateDDoc4JConfig() throws Exception { } @Test - public void loadsDDoc4JSecurityProviderFromFile() throws Exception { + public void loadsDDoc4JSecurityProviderFromFile() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("org.bouncycastle.jce.provider.BouncyCastleProvider1", ddoc4jConf.get("DIGIDOC_SECURITY_PROVIDER")); } @Test - public void loadsDDoc4JCacheDirectoryFromFile() throws Exception { + public void loadsDDoc4JCacheDirectoryFromFile() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("/test_cache_dir", ddoc4jConf.get("DIGIDOC_DF_CACHE_DIR")); } @Test - public void defaultDDoc4JCacheDirectory() throws Exception { + public void defaultDDoc4JCacheDirectory() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_without_cache_dir.yaml"); Assert.assertNull(ddoc4jConf.get("DIGIDOC_DF_CACHE_DIR")); } - @SuppressWarnings("NumericOverflow") @Test - public void loadsMaxDataFileCachedFromFile() throws Exception { + public void loadsMaxDataFileCachedFromFile() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("8192", ddoc4jConf.get("DIGIDOC_MAX_DATAFILE_CACHED")); Assert.assertEquals(8192, this.configuration.getMaxDataFileCachedInMB()); @@ -577,32 +616,32 @@ public void loadsMaxDataFileCachedFromFile() throws Exception { } @Test - public void settingNonExistingConfigurationFileThrowsError() throws Exception { + public void settingNonExistingConfigurationFileThrowsError() { this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("File src/test/resources/testFiles/not_exists.yaml not found in classpath."); this.configuration.loadConfiguration("src/test/resources/testFiles/not_exists.yaml"); } @Test - public void digiDocSecurityProviderDefaultValue() throws Exception { + public void digiDocSecurityProviderDefaultValue() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/main/resources/digidoc4j.yaml"); Assert.assertEquals(Constant.DDoc4J.SECURITY_PROVIDER, ddoc4jConf.get("DIGIDOC_SECURITY_PROVIDER")); } @Test - public void digiDocSecurityProviderDefaultName() throws Exception { + public void digiDocSecurityProviderDefaultName() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/main/resources/digidoc4j.yaml"); Assert.assertEquals(Constant.DDoc4J.SECURITY_PROVIDER_NAME, ddoc4jConf.get("DIGIDOC_SECURITY_PROVIDER_NAME")); } @Test - public void asksValueOfNonExistingParameter() throws Exception { + public void asksValueOfNonExistingParameter() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/main/resources/digidoc4j.yaml"); Assert.assertNull(ddoc4jConf.get("DIGIDOC_PROXY_HOST")); } @Test - public void digidocMaxDataFileCachedParameterIsNotANumber() throws Exception { + public void digidocMaxDataFileCachedParameterIsNotANumber() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_max_data_file_cached.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter DIGIDOC_MAX_DATAFILE_CACHED" + @@ -611,7 +650,7 @@ public void digidocMaxDataFileCachedParameterIsNotANumber() throws Exception { } @Test - public void digidocSignOcspRequestIsNotABoolean() throws Exception { + public void digidocSignOcspRequestIsNotABoolean() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_sign_ocsp_request.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter SIGN_OCSP_REQUESTS should be set to true or false" + @@ -620,7 +659,7 @@ public void digidocSignOcspRequestIsNotABoolean() throws Exception { } @Test - public void digidocKeyUsageCheckIsNotABoolean() throws Exception { + public void digidocKeyUsageCheckIsNotABoolean() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_key_usage.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter KEY_USAGE_CHECK should be set to true or false" + @@ -629,7 +668,7 @@ public void digidocKeyUsageCheckIsNotABoolean() throws Exception { } @Test - public void digidocUseLocalTslIsNotABoolean() throws Exception { + public void digidocUseLocalTslIsNotABoolean() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_use_local_tsl.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter DIGIDOC_USE_LOCAL_TSL should be set to true or false" + @@ -638,7 +677,7 @@ public void digidocUseLocalTslIsNotABoolean() throws Exception { } @Test - public void digidocDataFileHashcodeModeIsNotABoolean() throws Exception { + public void digidocDataFileHashcodeModeIsNotABoolean() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_datafile_hashcode_mode.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter DATAFILE_HASHCODE_MODE should be set to true or false" + @@ -647,7 +686,7 @@ public void digidocDataFileHashcodeModeIsNotABoolean() throws Exception { } @Test - public void missingOCSPSEntryThrowsException() throws Exception { + public void missingOCSPSEntryThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_no_entry.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("No OCSPS entry found or OCSPS entry is empty. Configuration from: " + fileName); @@ -656,7 +695,7 @@ public void missingOCSPSEntryThrowsException() throws Exception { } @Test - public void emptyOCSPSEntryThrowsException() throws Exception { + public void emptyOCSPSEntryThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_empty.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("No OCSPS entry found or OCSPS entry is empty. Configuration from: " + fileName); @@ -665,7 +704,7 @@ public void emptyOCSPSEntryThrowsException() throws Exception { } @Test - public void OCSPWithoutCaCnValueThrowsException() throws Exception { + public void OCSPWithoutCaCnValueThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_no_ca_cn.yaml"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration from " + fileName + " contains error(s):\n" + @@ -675,7 +714,7 @@ public void OCSPWithoutCaCnValueThrowsException() throws Exception { } @Test - public void OCSPWithEmptySubEntriesThrowsException() throws Exception { + public void OCSPWithEmptySubEntriesThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_empty_sub_entries.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "OCSPS list entry 3 does not have an entry for CA_CN or the entry is empty\n" + @@ -689,7 +728,7 @@ public void OCSPWithEmptySubEntriesThrowsException() throws Exception { } @Test - public void OCSPWithMissingSubEntriesThrowsException() throws Exception { + public void OCSPWithMissingSubEntriesThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_missing_sub_entries.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "OCSPS list entry 3 does not have an entry for CN or the entry is empty\n" + @@ -703,7 +742,7 @@ public void OCSPWithMissingSubEntriesThrowsException() throws Exception { } @Test - public void OCSPWithMissingOcspsCertsEntryThrowsException() throws Exception { + public void OCSPWithMissingOcspsCertsEntryThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_missing_certs_entry.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "OCSPS list entry 3 does not have an entry for CERTS or the entry is empty\n"; @@ -714,7 +753,7 @@ public void OCSPWithMissingOcspsCertsEntryThrowsException() throws Exception { } @Test - public void OCSPWithEmptyOcspsCertsEntryThrowsException() throws Exception { + public void OCSPWithEmptyOcspsCertsEntryThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_ocsps_empty_certs_entry.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "OCSPS list entry 2 does not have an entry for CERTS or the entry is empty\n"; @@ -725,7 +764,7 @@ public void OCSPWithEmptyOcspsCertsEntryThrowsException() throws Exception { } @Test - public void configurationFileIsNotYamlFormatThrowsException() throws Exception { + public void configurationFileIsNotYamlFormatThrowsException() { String fileName = "src/test/resources/testFiles/helper-files/test.txt"; String expectedErrorMessage = "Configuration from " + fileName + " is not correctly formatted"; this.expectedException.expect(ConfigurationException.class); @@ -739,198 +778,269 @@ public void configurationStreamIsNotYamlFormatThrowsException() throws Exception String expectedErrorMessage = "Configuration from stream is not correctly formatted"; this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage(expectedErrorMessage); - this.configuration.loadConfiguration(new FileInputStream(fileName)); + try (InputStream inputStream = new FileInputStream(fileName)) { + this.configuration.loadConfiguration(inputStream); + } } @Test - public void isOCSPSigningConfigurationAvailableWhenItIsNotAvailable() throws Exception { + public void isOCSPSigningConfigurationAvailableWhenItIsNotAvailable() { assertFalse(this.configuration.isOCSPSigningConfigurationAvailable()); } @Test - public void isOCSPSigningConfigurationAvailableWhenItIsAvailable() throws Exception { + public void isOCSPSigningConfigurationAvailableWhenItIsAvailable() { this.configuration.setOCSPAccessCertificateFileName("test.p12"); this.configuration.setOCSPAccessCertificatePassword("aaa".toCharArray()); Assert.assertTrue(this.configuration.isOCSPSigningConfigurationAvailable()); } @Test - public void isOCSPSigningConfigurationAvailableWhenFileIsAvailable() throws Exception { + public void isOCSPSigningConfigurationAvailableWhenFileIsAvailable() { this.configuration.setOCSPAccessCertificateFileName("test.p12"); Assert.assertFalse(this.configuration.isOCSPSigningConfigurationAvailable()); } @Test - public void isOCSPSigningConfigurationAvailableWhenPasswordIsAvailable() throws Exception { + public void isOCSPSigningConfigurationAvailableWhenPasswordIsAvailable() { this.configuration.setOCSPAccessCertificatePassword("aaa".toCharArray()); Assert.assertFalse(this.configuration.isOCSPSigningConfigurationAvailable()); } @Test - public void getTspSourceFromConfigurationFile() throws Exception { + public void getTspSourceFromConfigurationFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("http://tsp.source.test/HttpTspServer", this.configuration.getTspSource()); } @Test - public void getValidationPolicyFromConfigurationFile() throws Exception { + public void getValidationPolicyFromConfigurationFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("conf/test_validation_policy.xml", this.configuration.getValidationPolicy()); } @Test - public void getOcspSourceFromConfigurationFile() throws Exception { + public void getOcspSourceFromConfigurationFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals("http://www.openxades.org/cgi-bin/test_ocsp_source.cgi", this.configuration.getOcspSource()); } @Test - public void getTslKeystoreLocationFromConfigurationFile() throws Exception { - this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); - Assert.assertEquals("keystore", this.configuration.getTslKeyStoreLocation()); + public void getLotlTruststorePathFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + Assert.assertEquals("TEST_LOTL_TRUSTSTORE_PATH", this.configuration.getLotlTruststorePath()); + Assert.assertEquals("TEST_LOTL_TRUSTSTORE_PATH", this.configuration.getTslKeyStoreLocation()); + } + + @Test + public void getTslKeystoreLocationFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml"); + Assert.assertEquals("file:conf/test_TSLKeyStore_location", this.configuration.getLotlTruststorePath()); + Assert.assertEquals("file:conf/test_TSLKeyStore_location", this.configuration.getTslKeyStoreLocation()); } - @Test(expected = TslKeyStoreNotFoundException.class) - public void exceptionIsThrownWhenTslKeystoreIsNotFound() throws IOException { + @Test(expected = LotlTrustStoreNotFoundException.class) + public void exceptionIsThrownWhenLotlTruststoreIsNotFound() throws IOException { this.configuration = Configuration.of(Configuration.Mode.PROD); - this.configuration.setTslKeyStoreLocation("not/existing/path"); + this.configuration.setLotlTruststorePath("not/existing/path"); this.configuration.getTSL().refresh(); } @Test - public void testDefaultTslKeystoreLocation() throws Exception { + public void testDefaultLotlTruststorePath() { this.configuration = Configuration.of(Configuration.Mode.PROD); - Assert.assertEquals("keystore/keystore.jks", this.configuration.getTslKeyStoreLocation()); + Assert.assertEquals("classpath:truststores/lotl-truststore.p12", this.configuration.getLotlTruststorePath()); + Assert.assertEquals("classpath:truststores/lotl-truststore.p12", this.configuration.getTslKeyStoreLocation()); } @Test - public void testDefaultTestTslKeystoreLocation() throws Exception { - Assert.assertEquals("keystore/test-keystore.jks", this.configuration.getTslKeyStoreLocation()); + public void testDefaultTestLotlTruststorePath() { + Assert.assertEquals("classpath:truststores/test-lotl-truststore.p12", this.configuration.getLotlTruststorePath()); + Assert.assertEquals("classpath:truststores/test-lotl-truststore.p12", this.configuration.getTslKeyStoreLocation()); } @Test - public void testDefaultTslKeystorePassword() throws Exception { + public void getLotlTruststoreTypeFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + Assert.assertEquals("TEST_LOTL_TRUSTSTORE_TYPE", this.configuration.getLotlTruststoreType()); + } + + @Test + public void testDefaultLotlTruststoreType() { this.configuration = Configuration.of(Configuration.Mode.PROD); + Assert.assertEquals("PKCS12", this.configuration.getLotlTruststoreType()); + } + + @Test + public void testDefaultLotlTruststorePassword() { + this.configuration = Configuration.of(Configuration.Mode.PROD); + Assert.assertEquals("digidoc4j-password", this.configuration.getLotlTruststorePassword()); Assert.assertEquals("digidoc4j-password", this.configuration.getTslKeyStorePassword()); } @Test - public void getTslKeystorePasswordFromConfigurationFile() throws Exception { - this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); - Assert.assertEquals("password", this.configuration.getTslKeyStorePassword()); + public void getLotlTruststorePasswordFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + Assert.assertEquals("TEST_LOTL_TRUSTSTORE_PASSWORD", this.configuration.getLotlTruststorePassword()); + Assert.assertEquals("TEST_LOTL_TRUSTSTORE_PASSWORD", this.configuration.getTslKeyStorePassword()); } @Test - public void setTslCacheExpirationTime() throws Exception { + public void getTslKeystorePasswordFromConfigurationFile() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml"); + Assert.assertEquals("test_TSLKeyStore_password", this.configuration.getLotlTruststorePassword()); + Assert.assertEquals("test_TSLKeyStore_password", this.configuration.getTslKeyStorePassword()); + } + + @Test + public void testDefaultLotlPivotSupportEnabled() { + this.configuration = Configuration.of(Configuration.Mode.PROD); + Assert.assertTrue(this.configuration.isLotlPivotSupportEnabled()); + } + + @Test + public void testDefaultTestLotlPivotSupportDisabled() { + this.configuration = Configuration.of(Configuration.Mode.TEST); + Assert.assertFalse(this.configuration.isLotlPivotSupportEnabled()); + } + + @Test + public void getLotlPivotSupportFromConfigurationFile() throws Exception { + this.configuration.setLotlPivotSupportEnabled(true); + Assert.assertTrue(this.configuration.isLotlPivotSupportEnabled()); + loadConfigurationFromString(this.configuration, "LOTL_PIVOT_SUPPORT_ENABLED: false"); + Assert.assertFalse(this.configuration.isLotlPivotSupportEnabled()); + loadConfigurationFromString(this.configuration, "LOTL_PIVOT_SUPPORT_ENABLED: true"); + Assert.assertTrue(this.configuration.isLotlPivotSupportEnabled()); + } + + @Test + public void setTslCacheExpirationTime() { this.configuration.setTslCacheExpirationTime(1337); Assert.assertEquals(1337, this.configuration.getTslCacheExpirationTime()); } @Test - public void defaultTslCacheExpirationTime_shouldBeOneDay() throws Exception { + public void defaultTslCacheExpirationTime_shouldBeOneDay() { long oneDayInMs = 1000 * 60 * 60 * 24; Assert.assertEquals(oneDayInMs, this.configuration.getTslCacheExpirationTime()); Assert.assertEquals(oneDayInMs, Configuration.of(Configuration.Mode.PROD).getTslCacheExpirationTime()); } @Test - public void getTslCacheExpirationTimeFromConfigurationFile() throws Exception { + public void getTslCacheExpirationTimeFromConfigurationFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml"); Assert.assertEquals(1776, this.configuration.getTslCacheExpirationTime()); } @Test - public void defaultProxyConfiguration_shouldNotBeSet() throws Exception { + public void defaultProxyConfiguration_shouldNotBeSet() { Assert.assertFalse(this.configuration.isNetworkProxyEnabled()); Assert.assertNull(this.configuration.getHttpProxyHost()); Assert.assertNull(this.configuration.getHttpProxyPort()); - Assert.assertNull(this.configuration.getHttpsProxyHost()); - Assert.assertNull(this.configuration.getHttpsProxyPort()); Assert.assertNull(this.configuration.getHttpProxyUser()); Assert.assertNull(this.configuration.getHttpProxyPassword()); + Assert.assertNull(this.configuration.getHttpsProxyHost()); + Assert.assertNull(this.configuration.getHttpsProxyPort()); + Assert.assertNull(this.configuration.getHttpsProxyUser()); + Assert.assertNull(this.configuration.getHttpsProxyPassword()); for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { Assert.assertFalse(this.configuration.isNetworkProxyEnabledFor(connectionType)); Assert.assertNull(this.configuration.getHttpProxyHostFor(connectionType)); Assert.assertNull(this.configuration.getHttpProxyPortFor(connectionType)); - Assert.assertNull(this.configuration.getHttpsProxyHostFor(connectionType)); - Assert.assertNull(this.configuration.getHttpsProxyPortFor(connectionType)); Assert.assertNull(this.configuration.getHttpProxyUserFor(connectionType)); Assert.assertNull(this.configuration.getHttpProxyPasswordFor(connectionType)); + Assert.assertNull(this.configuration.getHttpsProxyHostFor(connectionType)); + Assert.assertNull(this.configuration.getHttpsProxyPortFor(connectionType)); + Assert.assertNull(this.configuration.getHttpsProxyUserFor(connectionType)); + Assert.assertNull(this.configuration.getHttpsProxyPasswordFor(connectionType)); } } @Test - public void getProxyConfigurationFromConfigurationFile_allParametersSet() throws Exception { + public void getProxyConfigurationFromConfigurationFile_allParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertTrue(this.configuration.isNetworkProxyEnabled()); Assert.assertEquals("cache.noile.ee", this.configuration.getHttpProxyHost()); Assert.assertEquals(8080, this.configuration.getHttpProxyPort().longValue()); + Assert.assertEquals("plainProxyMan", this.configuration.getHttpProxyUser()); + Assert.assertEquals("plainProxyPass", this.configuration.getHttpProxyPassword()); Assert.assertEquals("secure.noile.ee", this.configuration.getHttpsProxyHost()); Assert.assertEquals(8443, this.configuration.getHttpsProxyPort().longValue()); - Assert.assertEquals("proxyMan", this.configuration.getHttpProxyUser()); - Assert.assertEquals("proxyPass", this.configuration.getHttpProxyPassword()); + Assert.assertEquals("secureProxyMan", this.configuration.getHttpsProxyUser()); + Assert.assertEquals("secureProxyPass", this.configuration.getHttpsProxyPassword()); for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { Assert.assertTrue(this.configuration.isNetworkProxyEnabledFor(connectionType)); Assert.assertEquals(connectionType + ".cache.noile.ee", this.configuration.getHttpProxyHostFor(connectionType)); Assert.assertEquals(80800 + connectionType.ordinal(), this.configuration.getHttpProxyPortFor(connectionType).longValue()); + Assert.assertEquals(connectionType + "-plainProxyMan", this.configuration.getHttpProxyUserFor(connectionType)); + Assert.assertEquals(connectionType + "-plainProxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); Assert.assertEquals(connectionType + ".secure.noile.ee", this.configuration.getHttpsProxyHostFor(connectionType)); Assert.assertEquals(84430 + connectionType.ordinal(), this.configuration.getHttpsProxyPortFor(connectionType).longValue()); - Assert.assertEquals(connectionType + "-proxyMan", this.configuration.getHttpProxyUserFor(connectionType)); - Assert.assertEquals(connectionType + "-proxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); + Assert.assertEquals(connectionType + "-secureProxyMan", this.configuration.getHttpsProxyUserFor(connectionType)); + Assert.assertEquals(connectionType + "-secureProxyPass", this.configuration.getHttpsProxyPasswordFor(connectionType)); } } @Test - public void getInvalidProxyConfigurationFromConfigurationFile() throws Exception { + public void getInvalidProxyConfigurationFromConfigurationFile() { this.expectedException.expect(ConfigurationException.class); this.expectedException.expectMessage("Configuration parameter HTTP_PROXY_PORT should have an integer value but the actual value is: notA_number."); this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_invalid_key_usage.yaml"); } @Test - public void getProxyConfigurationFromConfigurationFile_GenericParametersSet() throws Exception { + public void getProxyConfigurationFromConfigurationFile_GenericParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml"); Assert.assertTrue(this.configuration.isNetworkProxyEnabled()); Assert.assertEquals("cache.noile.ee", this.configuration.getHttpProxyHost()); Assert.assertEquals(8080, this.configuration.getHttpProxyPort().longValue()); + Assert.assertEquals("plainProxyMan", this.configuration.getHttpProxyUser()); + Assert.assertEquals("plainProxyPass", this.configuration.getHttpProxyPassword()); Assert.assertEquals("secure.noile.ee", this.configuration.getHttpsProxyHost()); Assert.assertEquals(8443, this.configuration.getHttpsProxyPort().longValue()); - Assert.assertEquals("proxyMan", this.configuration.getHttpProxyUser()); - Assert.assertEquals("proxyPass", this.configuration.getHttpProxyPassword()); + Assert.assertEquals("secureProxyMan", this.configuration.getHttpsProxyUser()); + Assert.assertEquals("secureProxyPass", this.configuration.getHttpsProxyPassword()); for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { Assert.assertTrue(this.configuration.isNetworkProxyEnabledFor(connectionType)); Assert.assertEquals("cache.noile.ee", this.configuration.getHttpProxyHostFor(connectionType)); Assert.assertEquals(8080, this.configuration.getHttpProxyPortFor(connectionType).longValue()); + Assert.assertEquals("plainProxyMan", this.configuration.getHttpProxyUserFor(connectionType)); + Assert.assertEquals("plainProxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); Assert.assertEquals("secure.noile.ee", this.configuration.getHttpsProxyHostFor(connectionType)); Assert.assertEquals(8443, this.configuration.getHttpsProxyPortFor(connectionType).longValue()); - Assert.assertEquals("proxyMan", this.configuration.getHttpProxyUserFor(connectionType)); - Assert.assertEquals("proxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); + Assert.assertEquals("secureProxyMan", this.configuration.getHttpsProxyUserFor(connectionType)); + Assert.assertEquals("secureProxyPass", this.configuration.getHttpsProxyPasswordFor(connectionType)); } } @Test - public void getProxyConfigurationFromConfigurationFile_specificParametersSet() throws Exception { + public void getProxyConfigurationFromConfigurationFile_specificParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml"); Assert.assertFalse(this.configuration.isNetworkProxyEnabled()); Assert.assertNull(this.configuration.getHttpProxyHost()); Assert.assertNull(this.configuration.getHttpProxyPort()); - Assert.assertNull(this.configuration.getHttpsProxyHost()); - Assert.assertNull(this.configuration.getHttpsProxyPort()); Assert.assertNull(this.configuration.getHttpProxyUser()); Assert.assertNull(this.configuration.getHttpProxyPassword()); + Assert.assertNull(this.configuration.getHttpsProxyHost()); + Assert.assertNull(this.configuration.getHttpsProxyPort()); + Assert.assertNull(this.configuration.getHttpsProxyUser()); + Assert.assertNull(this.configuration.getHttpsProxyPassword()); for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { Assert.assertTrue(this.configuration.isNetworkProxyEnabledFor(connectionType)); Assert.assertEquals(connectionType + ".cache.noile.ee", this.configuration.getHttpProxyHostFor(connectionType)); Assert.assertEquals(80800 + connectionType.ordinal(), this.configuration.getHttpProxyPortFor(connectionType).longValue()); + Assert.assertEquals(connectionType + "-plainProxyMan", this.configuration.getHttpProxyUserFor(connectionType)); + Assert.assertEquals(connectionType + "-plainProxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); Assert.assertEquals(connectionType + ".secure.noile.ee", this.configuration.getHttpsProxyHostFor(connectionType)); Assert.assertEquals(84430 + connectionType.ordinal(), this.configuration.getHttpsProxyPortFor(connectionType).longValue()); - Assert.assertEquals(connectionType + "-proxyMan", this.configuration.getHttpProxyUserFor(connectionType)); - Assert.assertEquals(connectionType + "-proxyPass", this.configuration.getHttpProxyPasswordFor(connectionType)); + Assert.assertEquals(connectionType + "-secureProxyMan", this.configuration.getHttpsProxyUserFor(connectionType)); + Assert.assertEquals(connectionType + "-secureProxyPass", this.configuration.getHttpsProxyPasswordFor(connectionType)); } } @Test - public void defaultSslConfiguration_shouldNotBeSet() throws Exception { + public void defaultSslConfiguration_shouldNotBeSet() { Assert.assertFalse(this.configuration.isSslConfigurationEnabled()); Assert.assertNull(this.configuration.getSslKeystorePath()); Assert.assertNull(this.configuration.getSslKeystoreType()); @@ -956,7 +1066,7 @@ public void defaultSslConfiguration_shouldNotBeSet() throws Exception { } @Test - public void getSslConfigurationFromConfigurationFile_allParametersSet() throws Exception { + public void getSslConfigurationFromConfigurationFile_allParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertTrue(configuration.isSslConfigurationEnabled()); Assert.assertEquals("sslKeystorePath", this.configuration.getSslKeystorePath()); @@ -978,16 +1088,16 @@ public void getSslConfigurationFromConfigurationFile_allParametersSet() throws E Assert.assertEquals(connectionType + "-sslTruststorePassword", this.configuration.getSslTruststorePasswordFor(connectionType)); Assert.assertEquals(connectionType + "-sslProtocol", this.configuration.getSslProtocolFor(connectionType)); Assert.assertEquals( - Arrays.asList("sslProtocol1", "sslProtocol2", "sslProtocol3").stream().map(p -> connectionType + "-" + p).collect(Collectors.toList()), + Stream.of("sslProtocol1", "sslProtocol2", "sslProtocol3").map(p -> connectionType + "-" + p).collect(Collectors.toList()), this.configuration.getSupportedSslProtocolsFor(connectionType)); Assert.assertEquals( - Arrays.asList("sslCipherSuite1", "sslCipherSuite2").stream().map(cs -> connectionType + "-" + cs).collect(Collectors.toList()), + Stream.of("sslCipherSuite1", "sslCipherSuite2").map(cs -> connectionType + "-" + cs).collect(Collectors.toList()), this.configuration.getSupportedSslCipherSuitesFor(connectionType)); } } @Test - public void getSslConfigurationFromConfigurationFile_genericParametersSet() throws Exception { + public void getSslConfigurationFromConfigurationFile_genericParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml"); Assert.assertTrue(configuration.isSslConfigurationEnabled()); Assert.assertEquals("sslKeystorePath", this.configuration.getSslKeystorePath()); @@ -1014,7 +1124,7 @@ public void getSslConfigurationFromConfigurationFile_genericParametersSet() thro } @Test - public void getSslConfigurationFromConfigurationFile_specificParametersSet() throws Exception { + public void getSslConfigurationFromConfigurationFile_specificParametersSet() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml"); Assert.assertFalse(this.configuration.isSslConfigurationEnabled()); Assert.assertNull(this.configuration.getSslKeystorePath()); @@ -1036,10 +1146,10 @@ public void getSslConfigurationFromConfigurationFile_specificParametersSet() thr Assert.assertEquals(connectionType + "-sslTruststorePassword", this.configuration.getSslTruststorePasswordFor(connectionType)); Assert.assertEquals(connectionType + "-sslProtocol", this.configuration.getSslProtocolFor(connectionType)); Assert.assertEquals( - Arrays.asList("sslProtocol1", "sslProtocol2", "sslProtocol3").stream().map(p -> connectionType + "-" + p).collect(Collectors.toList()), + Stream.of("sslProtocol1", "sslProtocol2", "sslProtocol3").map(p -> connectionType + "-" + p).collect(Collectors.toList()), this.configuration.getSupportedSslProtocolsFor(connectionType)); Assert.assertEquals( - Arrays.asList("sslCipherSuite1", "sslCipherSuite2").stream().map(cs -> connectionType + "-" + cs).collect(Collectors.toList()), + Stream.of("sslCipherSuite1", "sslCipherSuite2").map(cs -> connectionType + "-" + cs).collect(Collectors.toList()), this.configuration.getSupportedSslCipherSuitesFor(connectionType)); } } @@ -1077,7 +1187,7 @@ public void setMaxAllowedZipCompressionRatio() { } @Test - public void loadMultipleCAsFromConfigurationFile() throws Exception { + public void loadMultipleCAsFromConfigurationFile() { Hashtable ddoc4jConf = this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_two_cas.yaml"); this.configuration.getDDoc4JConfiguration(); Assert.assertEquals("AS Sertifitseerimiskeskus", ddoc4jConf.get("DIGIDOC_CA_1_NAME")); @@ -1088,12 +1198,12 @@ public void loadMultipleCAsFromConfigurationFile() throws Exception { } @Test - public void missingCA_shouldNotThrowException() throws Exception { + public void missingCA_shouldNotThrowException() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_no_ca.yaml"); } @Test - public void missingCA_shouldThrowException_whenUsingDDoc() throws Exception { + public void missingCA_shouldThrowException_whenUsingDDoc() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_no_ca.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "Empty or no DIGIDOC_CAS entry"; @@ -1104,7 +1214,7 @@ public void missingCA_shouldThrowException_whenUsingDDoc() throws Exception { } @Test - public void emptyCAThrowsException() throws Exception { + public void emptyCAThrowsException() { String fileName = "src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_empty_ca.yaml"; String expectedErrorMessage = "Configuration from " + fileName + " contains error(s):\n" + "Empty or no DIGIDOC_CA for entry 1"; @@ -1115,19 +1225,19 @@ public void emptyCAThrowsException() throws Exception { } @Test - public void isTestMode() throws Exception { + public void isTestMode() { Assert.assertTrue(this.configuration.isTest()); } @Test - public void isNotTestMode() throws Exception { + public void isNotTestMode() { this.configuration = Configuration.of(Configuration.Mode.PROD); Assert.assertFalse(this.configuration.isTest()); } @Test - public void verifyAllOptionalConfigurationSettingsAreLoadedFromFile() throws Exception { - this.configuration.setTslLocation("Set TSL location"); + public void verifyAllOptionalConfigurationSettingsAreLoadedFromFile() { + this.configuration.setLotlLocation("Set LOTL location"); this.configuration.setTspSource("Set TSP source"); this.configuration.setOCSPAccessCertificateFileName("Set OCSP access certificate file name"); this.configuration.setOCSPAccessCertificatePassword("Set password".toCharArray()); @@ -1152,18 +1262,18 @@ public void verifyAllOptionalConfigurationSettingsAreLoadedFromFile() throws Exc Assert.assertEquals("TEST_OCSP_SOURCE", this.configuration.getRegistry().get(ConfigurationParameter.OcspSource).get(0)); Assert.assertEquals("TEST_TSP_SOURCE", this.configuration.getRegistry().get(ConfigurationParameter.TspSource).get(0)); Assert.assertEquals("TEST_VALIDATION_POLICY", this.configuration.getRegistry().get(ConfigurationParameter.ValidationPolicy).get(0)); - Assert.assertEquals("TEST_TSL_LOCATION", this.configuration.getRegistry().get(ConfigurationParameter.TslLocation).get(0)); + Assert.assertEquals("TEST_LOTL_LOCATION", this.configuration.getRegistry().get(ConfigurationParameter.LotlLocation).get(0)); Assert.assertEquals("true", this.configuration.getRegistry().get(ConfigurationParameter.preferAiaOcsp).get(0)); Assert.assertEquals("73", this.configuration.getRegistry().get(ConfigurationParameter.ZipCompressionRatioCheckThreshold).get(0)); Assert.assertEquals("37", this.configuration.getRegistry().get(ConfigurationParameter.MaxAllowedZipCompressionRatio).get(0)); - this.configuration.setTslLocation("Set TSL location"); + this.configuration.setLotlLocation("Set LOTL location"); this.configuration.setTspSource("Set TSP source"); this.configuration.setOCSPAccessCertificateFileName("Set OCSP access certificate file name"); this.configuration.setOCSPAccessCertificatePassword("Set password".toCharArray()); this.configuration.setOcspSource("Set OCSP source"); this.configuration.setValidationPolicy("Set validation policy"); - Assert.assertEquals("Set TSL location", this.configuration.getTslLocation()); + Assert.assertEquals("Set LOTL location", this.configuration.getLotlLocation()); Assert.assertEquals("Set TSP source", this.configuration.getTspSource()); Assert.assertEquals("Set OCSP access certificate file name", this.configuration.getOCSPAccessCertificateFileName()); Assert.assertEquals("Set password", this.configuration.getRegistry().get(ConfigurationParameter.OcspAccessCertificatePassword).get(0)); @@ -1172,12 +1282,12 @@ public void verifyAllOptionalConfigurationSettingsAreLoadedFromFile() throws Exc } @Test - public void getDefaultTempFileMaxAge() throws Exception { + public void getDefaultTempFileMaxAge() { Assert.assertEquals(86400000, this.configuration.getTempFileMaxAge()); } @Test - public void loadTempFileMaxAgeFromFile() throws Exception { + public void loadTempFileMaxAgeFromFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_temp_file_max_age.yaml"); Assert.assertEquals(60, this.configuration.getTempFileMaxAge()); } @@ -1190,20 +1300,20 @@ public void setTempFileMaxAgeFromCode(){ } @Test - public void getDefaultConnectionTimeout() throws Exception { - Assert.assertEquals(1000, this.configuration.getConnectionTimeout()); - Assert.assertEquals(1000, this.configuration.getSocketTimeout()); + public void getDefaultConnectionTimeout() { + Assert.assertEquals(60000, this.configuration.getConnectionTimeout()); + Assert.assertEquals(60000, this.configuration.getSocketTimeout()); } @Test - public void loadConnectionTimeoutFromFile() throws Exception { + public void loadConnectionTimeoutFromFile() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_connection_timeout.yaml"); Assert.assertEquals(4000, this.configuration.getConnectionTimeout()); Assert.assertEquals(2000, this.configuration.getSocketTimeout()); } @Test - public void setConnectionTimeoutFromCode() throws Exception { + public void setConnectionTimeoutFromCode() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_connection_timeout.yaml"); this.configuration.setConnectionTimeout(2000); this.configuration.setSocketTimeout(5000); @@ -1212,20 +1322,20 @@ public void setConnectionTimeoutFromCode() throws Exception { } @Test - public void revocationAndTimestampDelta_shouldBeOneDay() throws Exception { + public void revocationAndTimestampDelta_shouldBeOneDay() { int oneDayInMinutes = 24 * 60; Assert.assertEquals(oneDayInMinutes, this.configuration.getRevocationAndTimestampDeltaInMinutes()); } @Test - public void testSettingRevocationAndTimestampDelta() throws Exception { + public void testSettingRevocationAndTimestampDelta() { int twoDaysInMinutes = 48 * 60; this.configuration.setRevocationAndTimestampDeltaInMinutes(twoDaysInMinutes); Assert.assertEquals(twoDaysInMinutes, this.configuration.getRevocationAndTimestampDeltaInMinutes()); } @Test - public void testLoadingRevocationAndTimestampDeltaFromConf() throws Exception { + public void testLoadingRevocationAndTimestampDeltaFromConf() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertEquals(1337, this.configuration.getRevocationAndTimestampDeltaInMinutes()); } @@ -1255,14 +1365,14 @@ public void setAllowedOcspProviders() { } @Test - public void getTrustedTerritories_defaultTesting_shouldBeNull() throws Exception { - Assert.assertEquals(new ArrayList<>(), this.configuration.getTrustedTerritories()); + public void getTrustedTerritories_defaultTesting_shouldBeNull() { + Assert.assertEquals(Collections.emptyList(), configuration.getTrustedTerritories()); } @Test - public void getTrustedTerritories_defaultProd() throws Exception { - this.configuration = Configuration.of(Configuration.Mode.PROD); - List trustedTerritories = this.configuration.getTrustedTerritories(); + public void getTrustedTerritories_defaultProd() { + configuration = Configuration.of(Configuration.Mode.PROD); + List trustedTerritories = configuration.getTrustedTerritories(); Assert.assertNotNull(trustedTerritories); Assert.assertTrue(trustedTerritories.contains("EE")); Assert.assertTrue(trustedTerritories.contains("BE")); @@ -1272,23 +1382,73 @@ public void getTrustedTerritories_defaultProd() throws Exception { } @Test - public void setTrustedTerritories() throws Exception { - this.configuration.setTrustedTerritories("AR", "US", "CA"); - List trustedTerritories = this.configuration.getTrustedTerritories(); - Assert.assertEquals(3, trustedTerritories.size()); - Assert.assertEquals("AR", trustedTerritories.get(0)); - Assert.assertEquals("US", trustedTerritories.get(1)); - Assert.assertEquals("CA", trustedTerritories.get(2)); + public void setTrustedTerritories() { + configuration.setTrustedTerritories("AR", "US", "CA"); + List trustedTerritories = configuration.getTrustedTerritories(); + Assert.assertEquals(Arrays.asList("AR", "US", "CA"), trustedTerritories); } @Test - public void loadTrustedTerritoriesFromConf() throws Exception { - this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); - List trustedTerritories = this.configuration.getTrustedTerritories(); - Assert.assertEquals(3, trustedTerritories.size()); - Assert.assertEquals("NZ", trustedTerritories.get(0)); - Assert.assertEquals("AU", trustedTerritories.get(1)); - Assert.assertEquals("BR", trustedTerritories.get(2)); + public void loadTrustedTerritoriesFromConf() { + configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + List trustedTerritories = configuration.getTrustedTerritories(); + Assert.assertEquals(Arrays.asList("NZ", "AU", "BR"), trustedTerritories); + } + + @Test + public void loadYamlTrustedTerritoriesFromConf() { + configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc4j_test_conf_territories_lists.yaml"); + List trustedTerritories = configuration.getTrustedTerritories(); + Assert.assertEquals(Arrays.asList("AU", "NZ", "AR"), trustedTerritories); + } + + @Test + public void loadEmptyTrustedTerritoriesFromConf() throws Exception { + configuration.setTrustedTerritories("EE"); + loadConfigurationFromString(configuration, "TRUSTED_TERRITORIES: []"); + List trustedTerritories = configuration.getTrustedTerritories(); + Assert.assertEquals(Collections.emptyList(), trustedTerritories); + } + + @Test + public void getRequiredTerritories_defaultTesting_shouldBeNull() { + Assert.assertEquals(Collections.emptyList(), configuration.getRequiredTerritories()); + } + + @Test + public void getRequiredTerritories_defaultProd() { + configuration = Configuration.of(Configuration.Mode.PROD); + List requiredTerritories = configuration.getRequiredTerritories(); + Assert.assertEquals(Collections.singletonList("EE"), requiredTerritories); + } + + @Test + public void setRequiredTerritories() { + configuration.setRequiredTerritories("CU", "LV"); + List requiredTerritories = configuration.getRequiredTerritories(); + Assert.assertEquals(Arrays.asList("CU", "LV"), requiredTerritories); + } + + @Test + public void loadRequiredTerritoriesFromConf() { + configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + List requiredTerritories = configuration.getRequiredTerritories(); + Assert.assertEquals(Arrays.asList("GB", "LT"), requiredTerritories); + } + + @Test + public void loadYamlRequiredTerritoriesFromConf() { + configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc4j_test_conf_territories_lists.yaml"); + List requiredTerritories = configuration.getRequiredTerritories(); + Assert.assertEquals(Arrays.asList("IE", "LV"), requiredTerritories); + } + + @Test + public void loadEmptyRequiredTerritoriesFromConf() throws Exception { + configuration.setRequiredTerritories("EE"); + loadConfigurationFromString(configuration, "REQUIRED_TERRITORIES: []"); + List requiredTerritories = configuration.getRequiredTerritories(); + Assert.assertEquals(Collections.emptyList(), requiredTerritories); } @Test @@ -1501,38 +1661,49 @@ public void testOpenBDocWithConfFromSetterWhenYamlParamPresented() { } @Test - public void loadAllowedTimestampAndOCSPResponseDelta() throws Exception { + public void loadAllowedTimestampAndOCSPResponseDelta() { Assert.assertEquals(15, this.configuration.getAllowedTimestampAndOCSPResponseDeltaInMinutes().longValue()); } @Test - public void loadAllowedTimestampAndOCSPResponseDeltaFromConf() throws Exception { + public void loadAllowedTimestampAndOCSPResponseDeltaFromConf() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertEquals(1, this.configuration.getAllowedTimestampAndOCSPResponseDeltaInMinutes().longValue()); } @Test - public void testLoadingSignatureProfile() throws Exception { - Assert.assertEquals(SignatureProfile.LT, this.configuration.getSignatureProfile()); + public void testLoadingSignatureProfile() { + Assert.assertNull(this.configuration.getSignatureProfile()); } @Test - public void testLoadingSignatureProfileFromConf() throws Exception { + public void testLoadingSignatureProfileFromConf() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertEquals(SignatureProfile.LT_TM, this.configuration.getSignatureProfile()); } @Test - public void testLoadingSignatureDigestAlgorithm() throws Exception { - Assert.assertEquals(DigestAlgorithm.SHA256, this.configuration.getSignatureDigestAlgorithm()); + public void testLoadingSignatureDigestAlgorithm() { + Assert.assertNull(this.configuration.getSignatureDigestAlgorithm()); } @Test - public void testLoadingSignatureDigestAlgorithmFromConf() throws Exception { + public void testLoadingSignatureDigestAlgorithmFromConf() { this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); Assert.assertEquals(DigestAlgorithm.SHA512, this.configuration.getSignatureDigestAlgorithm()); } + @Test + public void testLoadingDataFileDigestAlgorithm() { + Assert.assertNull(this.configuration.getDataFileDigestAlgorithm()); + } + + @Test + public void testLoadingDataFileDigestAlgorithmFromConf() { + this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml"); + Assert.assertEquals(DigestAlgorithm.SHA512, this.configuration.getDataFileDigestAlgorithm()); + } + @Test public void testConfigurationHasChanged() throws Exception { Configuration otherConfiguration = Configuration.of(Configuration.Mode.PROD); @@ -1567,7 +1738,7 @@ private boolean isConfigurationsDifferent(Configuration otherConfiguration) { return !this.configuration.getRegistry().getSealValue().equals(otherConfiguration.getRegistry().generateSealValue()); } - private File generateConfigurationByParameter(String parameter) throws IOException { + private File generateConfigurationByParameter(String parameter) { return this.createTemporaryFileBy(String.format("%s\n" + "DIGIDOC_CAS:\n" + "- DIGIDOC_CA:\n" + @@ -1586,7 +1757,7 @@ private File generateConfigurationByParameter(String parameter) throws IOExcepti } private static void loadConfigurationFromString(Configuration configuration, String... lines) throws Exception { - String concatenatedString = Arrays.stream(lines).collect(Collectors.joining("\n")); + String concatenatedString = String.join("\n", lines); try (InputStream in = new ByteArrayInputStream(concatenatedString.getBytes(StandardCharsets.UTF_8))) { configuration.loadConfiguration(in); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/ContainerTest.java b/digidoc4j/src/test/java/org/digidoc4j/ContainerTest.java index a179db510..d4696044a 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/ContainerTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/ContainerTest.java @@ -10,13 +10,10 @@ package org.digidoc4j; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.digidoc4j.exceptions.DataFileNotFoundException; import org.digidoc4j.exceptions.DigiDoc4JException; -import org.digidoc4j.exceptions.InvalidSignatureException; import org.digidoc4j.exceptions.NotSupportedException; import org.digidoc4j.exceptions.OCSPRequestFailedException; import org.digidoc4j.exceptions.RemovingDataFileException; @@ -25,13 +22,13 @@ import org.digidoc4j.impl.asic.manifest.AsicManifest; import org.digidoc4j.impl.ddoc.ConfigManagerInitializer; import org.digidoc4j.impl.ddoc.DDocContainer; +import org.digidoc4j.test.MockTSLRefreshCallback; import org.digidoc4j.test.TestAssert; import org.digidoc4j.test.util.TestDataBuilderUtil; import org.digidoc4j.utils.Helper; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import org.xml.sax.SAXException; import java.io.ByteArrayInputStream; import java.io.File; @@ -40,7 +37,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; -import java.security.cert.CertificateEncodingException; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -78,7 +74,10 @@ public void eIDASVersionFailPolicyConfigurationTest() { Paths.get("src/test/resources/testFiles/valid-containers/bdoc-tm-with-large-data-file.bdoc")); SignatureValidationResult result = container.validate(); Assert.assertFalse("Container is valid", result.isValid()); - Assert.assertEquals("No errors count match", 1, result.getErrors().size()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "No acceptable trusted lists has been found!", + "The trusted list does not have the expected version!" + ); } @Test @@ -99,7 +98,7 @@ public void defaultConfigurationTest() { Paths.get("src/test/resources/testFiles/valid-containers/bdoc-tm-with-large-data-file.bdoc")); SignatureValidationResult result = container.validate(); List errors = result.getErrors(); - Assert.assertTrue(errors.size() == 0); + Assert.assertEquals(0, errors.size()); Assert.assertTrue(result.isValid()); } @@ -131,7 +130,7 @@ public void openDDocContainerForAllOtherFiles() { } @Test - public void testAddOneFileToContainerForBDoc() throws Exception { + public void testAddOneFileToContainerForBDoc() { Container container = this.createEmptyContainer(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); List dataFiles = container.getDataFiles(); @@ -166,45 +165,6 @@ public void removeDataFileRemovesFileFromManifest() throws IOException { } } - @Test(expected = DataFileNotFoundException.class) - public void nameBasedDataFileRemovalFromEmptyContainer_shouldThrowDataFileNotFoundException() { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - Assert.assertSame(0, container.getDataFiles().size()); - container.removeDataFile("test.txt"); - } - - @Test(expected = DataFileNotFoundException.class) - public void wrongNameBasedDataFileRemovalFromNonEmptyContainer_shouldThrowDataFileNotFoundException() { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - Assert.assertSame(1, container.getDataFiles().size()); - container.removeDataFile("some_different_file_name.txt"); - } - - @Test - public void nameBasedDataFileRemovalFromCreatedNotSignedContainer_shouldSucceed() { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - Assert.assertSame(1, container.getDataFiles().size()); - container.removeDataFile("test.txt"); - Assert.assertSame(0, container.getDataFiles().size()); - } - - @Test - public void nameBasedDataFileRemovalFromOpenedNotSignedContainer_shouldSucceed() { - Container container = this.openContainerBy(Paths.get(ASIC_WITH_NO_SIG)); - Assert.assertSame(1, container.getDataFiles().size()); - container.removeDataFile("test.txt"); - Assert.assertSame(0, container.getDataFiles().size()); - } - - @Test(expected = RemovingDataFileException.class) - public void nameBasedDataFileRemovalFromSignedContainer_shouldThrowRemovingDataFileException() { - Container container = this.openContainerBy(Paths.get(ASICE_WITH_TS_SIG)); - Assert.assertSame(1, container.getDataFiles().size()); - container.removeDataFile(container.getDataFiles().get(0).getName()); - } - @Test(expected = DataFileNotFoundException.class) public void wrongObjectBasedDataFileRemovalFromNonEmptyContainer_shouldThrowDataFileNotFoundException() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); @@ -252,7 +212,7 @@ public void testCreateBDocContainerSpecifiedByDocumentTypeForBDoc() throws Excep container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); TestDataBuilderUtil.signContainer(container); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Assert.assertTrue(Helper.isZipFile(new File(file))); } @@ -268,47 +228,11 @@ public void DDocRemovingDataFile_throwsException() { } @Test(expected = NotSupportedException.class) - public void DDocPrepareSigning_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.prepareSigning(this.pkcs12SignatureToken.getCertificate()); - } - - @Test(expected = NotSupportedException.class) - public void DDocSign_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.sign(pkcs12SignatureToken); - } - - @Test(expected = NotSupportedException.class) - public void DDocSignRaw_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.signRaw(new byte[]{0}); - } - - @Test(expected = NotSupportedException.class) - public void DDocAddRawSignature_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.addRawSignature(new byte[]{0}); - } - - @Test(expected = NotSupportedException.class) - public void DDocAddRawSignatureAsStreamArray_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.addRawSignature(new ByteArrayInputStream(new byte[]{0})); - } - - @Test(expected = NotSupportedException.class) - public void DDocAddDataFile_throwsException() throws Exception { + public void DDocAddDataFile_throwsException() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); } - @Test(expected = NotSupportedException.class) - public void DDocExtendTo_throwsException() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - container.extendTo(SignatureProfile.LT_TM); - } - @Test(expected = NotSupportedException.class) public void DDocExtendSignatureProfile_throwsException() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); @@ -316,7 +240,7 @@ public void DDocExtendSignatureProfile_throwsException() { } @Test - public void addLargeFileToBDoc() throws Exception { + public void addLargeFileToBDoc() { DataFile dataFile = new LargeDataFile(new ByteArrayInputStream(new byte[]{0, 1, 2, 3}), "large-doc.txt", "text/plain"); Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); @@ -341,12 +265,12 @@ public void addingDataFileToAlreadySignedContainer_shouldThrowDigiDoc4JException } @Test - public void testOpenCreatedDDocFile() throws Exception { + public void testOpenCreatedDDocFile() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); String file = this.getFileBy("ddoc"); - container.save(file); + container.saveAsFile(file); Container containerForReading = ContainerOpener.open(file); - Assert.assertEquals(Container.DocumentType.DDOC, containerForReading.getDocumentType()); + Assert.assertEquals(Constant.DDOC_CONTAINER_TYPE, containerForReading.getType()); Assert.assertEquals(1, container.getDataFiles().size()); } @@ -356,7 +280,7 @@ public void testOpenInvalidFileReturnsError() { } @Test - public void testValidateDDoc() throws Exception { + public void testValidateDDoc() { this.configuration = Configuration.of(Configuration.Mode.TEST); ConfigManagerInitializer.forceInitConfigManager(this.configuration); Container container = ContainerOpener.open( @@ -368,7 +292,7 @@ public void testValidateDDoc() throws Exception { @Ignore //This test fails in Travis @Test - public void testValidateDDoc10() throws Exception { + public void testValidateDDoc10() { this.configuration = Configuration.of(Configuration.Mode.PROD); ConfigManagerInitializer.forceInitConfigManager(this.configuration); Container container = ContainerOpener.open("src/test/resources/prodFiles/valid-containers/SK-XML1.0.ddoc"); @@ -434,7 +358,7 @@ public void testFileTooShortToVerifyIfItIsZipFileThrowsException() { @Test(expected = DigiDoc4JException.class) public void testOpenFromStreamTooShortToVerifyIfIsZip() { try (FileInputStream stream = new FileInputStream( - new File("src/test/resources/testFiles/invalid-containers/tooShortToVerifyIfIsZip.ddoc"))) { + "src/test/resources/testFiles/invalid-containers/tooShortToVerifyIfIsZip.ddoc")) { ContainerOpener.open(stream, true); } catch (DigiDoc4JException e) { throw e; @@ -455,9 +379,9 @@ public void testAddFileFromStreamToDDoc() throws IOException { public void openContainerFromStreamAsBDoc() throws IOException { Container container = this.createEmptyContainer(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - Signature signature = this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); try (FileInputStream stream = new FileInputStream(file)) { Container containerToTest = ContainerOpener.open(stream, false); Assert.assertEquals(1, containerToTest.getSignatures().size()); @@ -481,7 +405,7 @@ public void testGetSignatureFromDDoc() { } @Test - public void testConfigurationIsKeptWithInDDoc() throws Exception { + public void testConfigurationIsKeptWithInDDoc() { DDocContainer container = (DDocContainer) ContainerBuilder.aContainer(Container.DocumentType.DDOC) .withConfiguration(Configuration.getInstance()) .fromExistingFile("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc") @@ -490,71 +414,33 @@ public void testConfigurationIsKeptWithInDDoc() throws Exception { } @Test - public void testExtendToForBDOC() { + public void testExtendSignatureProfileForBDOC() { Container container = this.createEmptyContainer(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); Signature signature = SignatureBuilder.aSignature(container).withSignatureProfile(SignatureProfile.B_BES). - withSignatureToken(this.pkcs12SignatureToken).invokeSigning(); + withSignatureToken(pkcs12SignatureToken).invokeSigning(); container.addSignature(signature); - container.extendTo(SignatureProfile.LT); + container.extendSignatureProfile(SignatureProfile.LT); Assert.assertNotNull(container.getSignatures().get(0).getOCSPCertificate()); } - @Test - public void addRawSignatureToBDocContainer() throws Exception { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - byte[] signatureBytes = FileUtils.readFileToByteArray( - new File("src/test/resources/testFiles/xades/valid-bdoc-tm.xml")); - container.addRawSignature(signatureBytes); - String file = this.getFileBy("bdoc"); - container.saveAsFile(file); - container = ContainerOpener.open(file); - Assert.assertEquals(1, container.getSignatures().size()); - Assert.assertTrue(container.validate().isValid()); - } - - @Test - public void addRawSignatureToExistingBDocContainer() throws Exception { - Container container = this.createNonEmptyContainerBy( - Paths.get("src/test/resources/testFiles/helper-files/test.txt")); - this.createSignatureBy(container, this.pkcs12SignatureToken); - byte[] signatureBytes = FileUtils.readFileToByteArray( - new File("src/test/resources/testFiles/xades/valid-bdoc-tm.xml")); - container.addRawSignature(signatureBytes); - String file = this.getFileBy("bdoc"); - container.saveAsFile(file); - container = ContainerOpener.open(file); - Assert.assertEquals(2, container.getSignatures().size()); - TestAssert.assertContainerIsValid(container); - } - - @Test(expected = InvalidSignatureException.class) - public void testAddRawSignatureAsByteArrayForBDoc() throws CertificateEncodingException, IOException, SAXException { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); - container.addRawSignature(Base64.decodeBase64("fo4aA1PVI//1agzBm2Vcxj7sk9pYQJt+9a7xLFSkfF10RocvGjVPBI65RMqyxGIsje" + - "LoeDERfTcjHdNojoK/gEdKtme4z6kvkZzjMjDuJu7krK/3DHBtW3XZleIaWZSWySahUiPNNIuk5ykACUolh+K/UK2aWL3Nh64EWvC8aznLV0" + - "M21s7GwTv7+iVXhR/6c3O22saWKWsteGT0/AqfcBRoj13H/NyuZOULqU0PFOhbJtV8RyZgC9n2uYBFsnutt5GPvhP+U93gkmFQ0+iC1a9Ktt" + - "j4QH5si35YmRIe0fp8tGDo6li63/tybb+kQ96AIaRe1NxpkKVDBGNi+VNVNA==")); - } - @Test(expected = DigiDoc4JException.class) public void testRemovingNotExistingSignatureThrowsException() { Container container = this.createEmptyContainerBy(Container.DocumentType.DDOC); - container.removeSignature(0); + Signature signature = SignatureBuilder.aSignature(container).withSignatureProfile(SignatureProfile.LT_TM). + withSignatureToken(pkcs12SignatureToken).invokeSigning(); + container.removeSignature(signature); } @Test - public void testSigningWithSignerInfo() throws Exception { + public void testSigningWithSignerInfo() { Container container = this.createEmptyContainer(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); Signature signature = SignatureBuilder.aSignature(container).withCity("myCity").withStateOrProvince( "myStateOrProvince"). withPostalCode("myPostalCode").withCountry("myCountry").withRoles("myRole / myResolution"). - withSignatureToken(this.pkcs12SignatureToken).invokeSigning(); + withSignatureToken(pkcs12SignatureToken).invokeSigning(); container.addSignature(signature); Assert.assertEquals("myCity", signature.getCity()); Assert.assertEquals("myStateOrProvince", signature.getStateOrProvince()); @@ -568,19 +454,20 @@ public void testSigningWithSignerInfo() throws Exception { public void testSetConfigurationForBDoc() { expectedException.expect(OCSPRequestFailedException.class); this.configuration = new Configuration(Configuration.Mode.TEST); - this.configuration.setTslLocation("pole"); + this.configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); + this.configuration.setLotlLocation("pole"); Container container = ContainerBuilder.aContainer(Container.DocumentType.BDOC).withConfiguration( this.configuration). withDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain").build(); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); } @Test - public void mustBePossibleToCreateAndVerifyContainerWhereDigestAlgorithmIsSHA224() throws Exception { + public void mustBePossibleToCreateAndVerifyContainerWhereDigestAlgorithmIsSHA224() { Container container = this.createEmptyContainer(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); Signature signature = SignatureBuilder.aSignature(container).withSignatureDigestAlgorithm(DigestAlgorithm.SHA224). - withSignatureToken(this.pkcs12SignatureToken).invokeSigning(); + withSignatureToken(pkcs12SignatureToken).invokeSigning(); container.addSignature(signature); String file = this.getFileBy("bdoc"); container.saveAsFile(file); @@ -590,38 +477,41 @@ public void mustBePossibleToCreateAndVerifyContainerWhereDigestAlgorithmIsSHA224 } @Test - public void constructorWithConfigurationParameter() throws Exception { + public void constructorWithConfigurationParameter() { Container container = ContainerBuilder.aContainer(). withConfiguration(Configuration.getInstance()).build(); Assert.assertEquals("ASICE", container.getType()); } @Test - @Ignore // Fails on Jenkins - need to verify - public void createContainerWhenAttachmentNameContainsEstonianCharacters() throws Exception { + public void createContainerWhenAttachmentNameContainsEstonianCharacters() { Container container = this.createEmptyContainer(); - String s = "src/test/resources/testFiles/test_o\u0303a\u0308o\u0308u\u0308.txt"; - container.addDataFile(s, "text/plain"); - container.sign(this.pkcs12SignatureToken); + String s = "\u0303a\u0308o\u0308u\u0308"; + container.addDataFile(new DataFile( + s.getBytes(StandardCharsets.UTF_8), + s + ".txt", + "text/plain" + )); + createSignatureBy(container, pkcs12SignatureToken); Assert.assertEquals(1, container.getDataFiles().size()); TestAssert.assertContainerIsValid(container); } @Test - public void containerTypeStringValueForBDOC() throws Exception { + public void containerTypeStringValueForBDOC() { Assert.assertEquals("application/vnd.etsi.asic-e+zip", - this.createEmptyContainer(Container.class).getDocumentType().toString()); + Container.DocumentType.BDOC.toString()); } @Test - public void testSigningMultipleFilesInContainer() throws Exception { + public void testSigningMultipleFilesInContainer() { Container container = this.createEmptyContainer(); container.addDataFile(new ByteArrayInputStream(new byte[]{1, 2, 3}), "1.txt", "text/plain"); container.addDataFile(new ByteArrayInputStream(new byte[]{1, 2, 3}), "2.txt", "text/plain"); container.addDataFile(new ByteArrayInputStream(new byte[]{1, 2, 3}), "3.txt", "text/plain"); TestDataBuilderUtil.signContainer(container); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Assert.assertEquals(3, container.getDataFiles().size()); this.assertContainsDataFile("1.txt", container); this.assertContainsDataFile("2.txt", container); @@ -644,7 +534,7 @@ private void assertContainsDataFile(String fileName, Container container) { return; } } - Assert.assertFalse("Data file '" + fileName + "' was not found in the container", true); + Assert.fail("Data file '" + fileName + "' was not found in the container"); } } diff --git a/digidoc4j/src/test/java/org/digidoc4j/DataFileTest.java b/digidoc4j/src/test/java/org/digidoc4j/DataFileTest.java index fdcd2e2ef..a1c97cbd5 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/DataFileTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/DataFileTest.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j; @@ -87,6 +87,24 @@ public void testCalculateDigest() { ); } + @Test + public void testCalculateDigestWithEnumTypeSHA1() { + DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); + Assert.assertArrayEquals( + Base64.decodeBase64("OQj17m9Rt2vPXYrry+v/KHpf98Q="), + dataFile.calculateDigest(DigestAlgorithm.SHA1) + ); + } + + @Test + public void testCalculateDigestWithEnumTypeSHA224() { + DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); + Assert.assertArrayEquals( + Base64.decodeBase64("w/fpCafC/Rcn3uKW2ExwxyzTW42KAhfU8eljcQ=="), + dataFile.calculateDigest(DigestAlgorithm.SHA224) + ); + } + @Test public void testCalculateDigestWithEnumTypeSHA256() { DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); @@ -97,11 +115,20 @@ public void testCalculateDigestWithEnumTypeSHA256() { } @Test - public void testCalculateDigestWithEnumTypeSHA1() { + public void testCalculateDigestWithEnumTypeSHA384() { DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); Assert.assertArrayEquals( - Base64.decodeBase64("OQj17m9Rt2vPXYrry+v/KHpf98Q="), - dataFile.calculateDigest(DigestAlgorithm.SHA1) + Base64.decodeBase64("i6PjAerb6Wuzt21+fISlv2SngAxfFfh+ZxrZDhdtwv0x8t8zXAPrtW/mi5aqpFig"), + dataFile.calculateDigest(DigestAlgorithm.SHA384) + ); + } + + @Test + public void testCalculateDigestWithEnumTypeSHA512() { + DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); + Assert.assertArrayEquals( + Base64.decodeBase64("ucUB3sbDkP0cjlo+T0PSLMfICMQm9P6pHq+byFo7Ytw0cG9uiA1QoAPQihQKDsBoInbgFpFZftPvghS3AgsM+A=="), + dataFile.calculateDigest(DigestAlgorithm.SHA512) ); } @@ -212,13 +239,6 @@ public void calculateSizeForStreamedFile() throws Exception { } } - @Test - public void testDigestIsCalculatedOnlyOnce() throws Exception { - DataFile dataFile = new DataFile(TEST_FILE_PATH, TEST_FILE_MIMETYPE); - byte[] digest = dataFile.calculateDigest(); - Assert.assertEquals(digest, dataFile.calculateDigest(new URL("http://NonExisting.test"))); - } - /* * RESTRICTED METHODS */ diff --git a/digidoc4j/src/test/java/org/digidoc4j/DetachedXadesSignatureBuilderTest.java b/digidoc4j/src/test/java/org/digidoc4j/DetachedXadesSignatureBuilderTest.java index 86db296ac..a8a1fd604 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/DetachedXadesSignatureBuilderTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/DetachedXadesSignatureBuilderTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j; import java.io.File; @@ -12,6 +22,7 @@ import org.digidoc4j.exceptions.SignatureTokenMissingException; import org.digidoc4j.exceptions.SignerCertificateRequiredException; import org.digidoc4j.impl.asic.asice.bdoc.BDocSignature; +import org.digidoc4j.test.TestAssert; import org.junit.Assert; import org.junit.Test; @@ -165,11 +176,14 @@ public void signWithB_EPESProfile() throws Exception { assertBEpesSignature(signature); ValidationResult validationResult = signature.validateSignature(); Assert.assertFalse(validationResult.isValid()); - Assert.assertEquals(1, validationResult.getWarnings().size()); - Assert.assertEquals("The signature/seal is an INDETERMINATE AdES digital signature!", validationResult.getWarnings().get(0).getMessage()); - Assert.assertEquals(2, validationResult.getErrors().size()); - Assert.assertEquals("The result of the LTV validation process is not acceptable to continue the process!", validationResult.getErrors().get(0).getMessage()); - Assert.assertEquals("No acceptable revocation data for the certificate!", validationResult.getErrors().get(1).getMessage()); + TestAssert.assertContainsExactSetOfErrors(validationResult.getWarnings(), + "The signature/seal is an INDETERMINATE AdES digital signature!" + ); + TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), + "The certificate validation is not conclusive!", + "No revocation data found for the certificate!", + "No acceptable revocation data for the certificate!" + ); } @@ -187,17 +201,16 @@ public void signWithLTProfile() throws Exception { assertValidSignature(signature); } - @Test + @Test(expected = IllegalArgumentException.class) public void signWithLTAProfile() throws Exception { byte[] digest = MessageDigest.getInstance("SHA-256").digest("hello".getBytes()); DigestDataFile digestDataFile = new DigestDataFile("hello.txt", DigestAlgorithm.SHA256, digest, "text/plain"); - Signature signature = DetachedXadesSignatureBuilder.withConfiguration(new Configuration()) + DetachedXadesSignatureBuilder.withConfiguration(new Configuration()) .withDataFile(digestDataFile) .withSignatureToken(pkcs12EccSignatureToken) .withSignatureProfile(SignatureProfile.LTA) .invokeSigningProcess(); - Assert.assertNull(signature); } @Test @@ -316,10 +329,9 @@ public void customSignaturePolicyNotAllowedForLTSignatureProfile() { } @Test - public void signWithoutAssigningProfile_profileTakenFromConfiguration_shouldSucceedWithTimestampSignature() { + public void signWithoutAssigningProfile_defaultPofileIsUsed_shouldSucceedWithTimestampSignature() { DataFile dataFile = new DataFile("something".getBytes(StandardCharsets.UTF_8), "filename", "text/plain"); Configuration configuration = new Configuration(); - Assert.assertSame(SignatureProfile.LT, configuration.getSignatureProfile()); DataToSign dataToSign = DetachedXadesSignatureBuilder.withConfiguration(configuration) .withDataFile(dataFile) @@ -328,22 +340,57 @@ public void signWithoutAssigningProfile_profileTakenFromConfiguration_shouldSucc .buildDataToSign(); Signature signature = dataToSign.finalize(pkcs12SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertSame(Constant.Default.SIGNATURE_PROFILE, signature.getProfile()); assertTimestampSignature(signature); assertValidSignature(signature); } @Test - public void mimeTypeValueNotInitialized() throws Exception{ - byte[] digest = MessageDigest.getInstance("SHA-256").digest("hello".getBytes()); - DigestDataFile digestDataFile = new DigestDataFile("hello.txt", DigestAlgorithm.SHA256, digest); + public void signWith256EcKey_withoutAssigningSignatureDigestAlgo_sha256SignatureDigestAlgoIsUsed() { + DataFile dataFile = new DataFile("something".getBytes(StandardCharsets.UTF_8), "filename", "text/plain"); + Configuration configuration = new Configuration(); - Signature signature = DetachedXadesSignatureBuilder - .withConfiguration(new Configuration()) - .withDataFile(digestDataFile) - .withSignatureToken(pkcs12EccSignatureToken) - .invokeSigningProcess(); + DataToSign dataToSign = DetachedXadesSignatureBuilder.withConfiguration(configuration) + .withDataFile(dataFile) + .withSigningCertificate(pkcs12EccSignatureToken.getCertificate()) + .buildDataToSign(); - assertTimestampSignature(signature); + Signature signature = dataToSign.finalize(pkcs12EccSignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals(DigestAlgorithm.SHA256, dataToSign.getSignatureParameters().getSignatureDigestAlgorithm()); + assertValidSignature(signature); + } + + @Test + public void signWith384EcKey_withoutAssigningSignatureDigestAlgo_sha384SignatureDigestAlgoIsUsed() { + DataFile dataFile = new DataFile("something".getBytes(StandardCharsets.UTF_8), "filename", "text/plain"); + Configuration configuration = new Configuration(); + + DataToSign dataToSign = DetachedXadesSignatureBuilder.withConfiguration(configuration) + .withDataFile(dataFile) + .withSigningCertificate(pkcs12Esteid2018SignatureToken.getCertificate()) + .buildDataToSign(); + + Signature signature = dataToSign.finalize(pkcs12Esteid2018SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals(DigestAlgorithm.SHA384, dataToSign.getSignatureParameters().getSignatureDigestAlgorithm()); + assertValidSignature(signature); + } + + @Test + public void signWithDifferentDataFileAndSignatureDigestAlgorithm() { + DataFile dataFile = new DataFile("something".getBytes(StandardCharsets.UTF_8), "filename", "text/plain"); + Configuration configuration = new Configuration(); + + DataToSign dataToSign = DetachedXadesSignatureBuilder.withConfiguration(configuration) + .withSignatureDigestAlgorithm(DigestAlgorithm.SHA384) + .withDataFileDigestAlgorithm(DigestAlgorithm.SHA512) + .withDataFile(dataFile) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) + .buildDataToSign(); + SignatureParameters signatureParameters = dataToSign.getSignatureParameters(); + Assert.assertEquals(DigestAlgorithm.SHA384, signatureParameters.getSignatureDigestAlgorithm()); + Assert.assertEquals(DigestAlgorithm.SHA512, signatureParameters.getDataFileDigestAlgorithm()); + Signature signature = dataToSign.finalize(pkcs12SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", signature.getSignatureMethod()); assertValidSignature(signature); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/DigestAlgorithmTest.java b/digidoc4j/src/test/java/org/digidoc4j/DigestAlgorithmTest.java new file mode 100644 index 000000000..a45fc2645 --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/DigestAlgorithmTest.java @@ -0,0 +1,52 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j; + +import org.digidoc4j.exceptions.TechnicalException; +import org.junit.Assert; +import org.junit.Test; + +import java.net.URL; +import java.util.Objects; +import java.util.stream.Stream; + +public class DigestAlgorithmTest { + + @Test + public void testGetDigestAlgorithmUriFromDssDigestAlgorithmSucceeds() { + Stream.of(eu.europa.esig.dss.enumerations.DigestAlgorithm.values()) + .filter(dssDigestAlgorithm -> Objects.nonNull(dssDigestAlgorithm.getUri())) + .forEach(dssDigestAlgorithm -> { + URL digestAlgorithmUri = DigestAlgorithm.getDigestAlgorithmUri(dssDigestAlgorithm); + + Assert.assertNotNull(digestAlgorithmUri); + Assert.assertEquals(dssDigestAlgorithm.getUri(), digestAlgorithmUri.toString()); + }); + } + + @Test + public void testGetDigestAlgorithmUriFromDssDigestAlgorithmFailsWhenNoUriSpecified() { + Stream.of(eu.europa.esig.dss.enumerations.DigestAlgorithm.values()) + .filter(dssDigestAlgorithm -> Objects.isNull(dssDigestAlgorithm.getUri())) + .forEach(dssDigestAlgorithm -> { + TechnicalException caughtException = Assert.assertThrows( + TechnicalException.class, + () -> DigestAlgorithm.getDigestAlgorithmUri(dssDigestAlgorithm) + ); + + Assert.assertEquals( + "No digest algorithm URI specified for " + dssDigestAlgorithm.getName(), + caughtException.getMessage() + ); + }); + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/SignatureBuilderTest.java b/digidoc4j/src/test/java/org/digidoc4j/SignatureBuilderTest.java index e08791bcd..0bdde6494 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/SignatureBuilderTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/SignatureBuilderTest.java @@ -25,6 +25,7 @@ import org.digidoc4j.signers.PKCS12SignatureToken; import org.digidoc4j.test.CustomContainer; import org.digidoc4j.test.MockSignatureBuilder; +import org.digidoc4j.test.TestAssert; import org.digidoc4j.test.util.TestDataBuilderUtil; import org.digidoc4j.test.util.TestSigningUtil; import org.digidoc4j.utils.TokenAlgorithmSupport; @@ -76,7 +77,7 @@ public void buildingDataToSign_shouldContainSignatureParameters() throws Excepti Assert.assertEquals("13456", parameters.getPostalCode()); Assert.assertEquals("Val Verde", parameters.getCountry()); Assert.assertEquals("Manager", parameters.getRoles().get(0)); - Assert.assertEquals(DigestAlgorithm.SHA256, parameters.getDigestAlgorithm()); + Assert.assertEquals(DigestAlgorithm.SHA256, parameters.getSignatureDigestAlgorithm()); Assert.assertEquals(SignatureProfile.LT_TM, parameters.getSignatureProfile()); Assert.assertEquals("S0", parameters.getSignatureId()); Assert.assertSame(pkcs12SignatureToken.getCertificate(), parameters.getSigningCertificate()); @@ -224,7 +225,7 @@ public void signWithDeterminedSignatureDigestAlgorithm() throws Exception { withSignatureDigestAlgorithm(digestAlgorithm).withSigningCertificate(pkcs12SignatureToken.getCertificate()). buildDataToSign(); SignatureParameters signatureParameters = dataToSign.getSignatureParameters(); - Assert.assertEquals(DigestAlgorithm.SHA256, signatureParameters.getDigestAlgorithm()); + Assert.assertEquals(DigestAlgorithm.SHA256, signatureParameters.getSignatureDigestAlgorithm()); Signature signature = TestDataBuilderUtil.makeSignature(container, dataToSign); Assert.assertEquals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", signature.getSignatureMethod()); Assert.assertTrue(container.validate().isValid()); @@ -262,7 +263,9 @@ public void openSignature_withDataFilesMismatch_shouldBeInvalid() throws Excepti Signature signature = this.openAdESSignature(container); ValidationResult result = signature.validateSignature(); Assert.assertFalse(result.isValid()); - Assert.assertEquals("The result of the LTV validation process is not acceptable to continue the process!", result.getErrors().get(0).getMessage()); + TestAssert.assertContainsErrors(result.getErrors(), + "The reference data object has not been found!" + ); } @Test @@ -580,19 +583,18 @@ public void bDocContainerWithTMAndTSSignature_signWithArchiveTimestampSignature_ } @Test - public void bDocContainerWithoutSignatures_signWithoutAssignedProfile_profileTakenFromConf_shouldSucceedWithTimestampSignature() { + public void bDocContainerWithoutSignatures_signWithoutAssignedProfile_defaultPofileIsUsed_shouldSucceedWithTimestampSignature() { Container container = buildContainer(BDOC, ASIC_WITH_NO_SIG); assertBDocContainer(container); Assert.assertTrue(container.getSignatures().isEmpty()); - Assert.assertSame(SignatureProfile.LT, container.getConfiguration().getSignatureProfile()); - DataToSign dataToSign = SignatureBuilder.aSignature(container) .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureDigestAlgorithm(DigestAlgorithm.SHA256) .buildDataToSign(); Signature signature = dataToSign.finalize(pkcs12SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertSame(Constant.Default.SIGNATURE_PROFILE, signature.getProfile()); assertTimestampSignature(signature); assertValidSignature(signature); @@ -635,19 +637,18 @@ public void bDocContainerWithoutSignatures_signWithTimemarkSignature_shouldSucce } @Test - public void asiceContainerWithoutSignatures_signWithoutAssignedProfile_profileTakenFromConf_shouldSucceedWithTimestampSignature() { + public void asiceContainerWithoutSignatures_signWithoutAssignedProfile_defaultPofileIsUsed_shouldSucceedWithTimestampSignature() { Container container = buildContainer(ASICE, ASIC_WITH_NO_SIG); assertAsicEContainer(container); Assert.assertTrue(container.getSignatures().isEmpty()); - Assert.assertSame(SignatureProfile.LT, container.getConfiguration().getSignatureProfile()); - DataToSign dataToSign = SignatureBuilder.aSignature(container) .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureDigestAlgorithm(DigestAlgorithm.SHA256) .buildDataToSign(); Signature signature = dataToSign.finalize(pkcs12SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertSame(Constant.Default.SIGNATURE_PROFILE, signature.getProfile()); assertTimestampSignature(signature); assertValidSignature(signature); @@ -657,6 +658,52 @@ public void asiceContainerWithoutSignatures_signWithoutAssignedProfile_profileTa assertTimestampSignature(container.getSignatures().get(0)); } + @Test + public void signWith256EcKey_withoutAssigningSignatureDigestAlgo_sha256SignatureDigestAlgoIsUsed() { + Container container = buildContainer(ASICE, ASIC_WITH_NO_SIG); + assertAsicEContainer(container); + Assert.assertTrue(container.getSignatures().isEmpty()); + + DataToSign dataToSign = SignatureBuilder.aSignature(container) + .withSigningCertificate(pkcs12EccSignatureToken.getCertificate()) + .buildDataToSign(); + + Signature signature = dataToSign.finalize(pkcs12EccSignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals(DigestAlgorithm.SHA256, dataToSign.getSignatureParameters().getSignatureDigestAlgorithm()); + assertValidSignature(signature); + } + + @Test + public void signWith384EcKey_withoutAssigningSignatureDigestAlgo_sha384SignatureDigestAlgoIsUsed() { + Container container = buildContainer(ASICE, ASIC_WITH_NO_SIG); + assertAsicEContainer(container); + Assert.assertTrue(container.getSignatures().isEmpty()); + + DataToSign dataToSign = SignatureBuilder.aSignature(container) + .withSigningCertificate(pkcs12Esteid2018SignatureToken.getCertificate()) + .buildDataToSign(); + + Signature signature = dataToSign.finalize(pkcs12Esteid2018SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals(DigestAlgorithm.SHA384, dataToSign.getSignatureParameters().getSignatureDigestAlgorithm()); + assertValidSignature(signature); + } + + @Test + public void signWithDifferentDataFileAndSignatureDigestAlgorithm() throws Exception { + Container container = this.createNonEmptyContainer(); + DataToSign dataToSign = SignatureBuilder.aSignature(container) + .withSignatureDigestAlgorithm(DigestAlgorithm.SHA384) + .withDataFileDigestAlgorithm(DigestAlgorithm.SHA512) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) + .buildDataToSign(); + SignatureParameters signatureParameters = dataToSign.getSignatureParameters(); + Assert.assertEquals(DigestAlgorithm.SHA384, signatureParameters.getSignatureDigestAlgorithm()); + Assert.assertEquals(DigestAlgorithm.SHA512, signatureParameters.getDataFileDigestAlgorithm()); + Signature signature = dataToSign.finalize(pkcs12SignatureToken.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDataToSign())); + Assert.assertEquals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", signature.getSignatureMethod()); + Assert.assertTrue(container.validate().isValid()); + } + @Test public void asiceContainerWithoutSignatures_signWithTimestampSignature_shouldSucceed() { Container container = buildContainer(ASICE, ASIC_WITH_NO_SIG); diff --git a/digidoc4j/src/test/java/org/digidoc4j/SignatureTest.java b/digidoc4j/src/test/java/org/digidoc4j/SignatureTest.java index 6821402aa..036306b2f 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/SignatureTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/SignatureTest.java @@ -10,25 +10,17 @@ package org.digidoc4j; -import java.io.IOException; -import java.net.URI; -import java.nio.file.Paths; -import java.security.cert.CertificateEncodingException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; - +import eu.europa.esig.dss.enumerations.Indication; +import eu.europa.esig.dss.enumerations.SignatureQualification; +import eu.europa.esig.dss.enumerations.SubIndication; +import eu.europa.esig.dss.simplereport.SimpleReport; import org.apache.commons.codec.binary.Base64; import org.custommonkey.xmlunit.XMLAssert; import org.digidoc4j.exceptions.CertificateNotFoundException; import org.digidoc4j.exceptions.DigiDoc4JException; import org.digidoc4j.exceptions.NotYetImplementedException; import org.digidoc4j.impl.Certificates; -import org.digidoc4j.impl.asic.SKCommonCertificateVerifier; import org.digidoc4j.impl.asic.tsl.TSLCertificateSourceImpl; -import org.digidoc4j.impl.asic.tsl.TslManager; import org.digidoc4j.impl.ddoc.ConfigManagerInitializer; import org.digidoc4j.impl.ddoc.DDocOpener; import org.digidoc4j.test.TestAssert; @@ -37,24 +29,20 @@ import org.digidoc4j.utils.DateUtils; import org.digidoc4j.utils.Helper; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; -import eu.europa.esig.dss.model.DSSDocument; -import eu.europa.esig.dss.model.FileDocument; -import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; -import eu.europa.esig.dss.enumerations.SignatureQualification; -import eu.europa.esig.dss.validation.SignedDocumentValidator; -import eu.europa.esig.dss.enumerations.Indication; -import eu.europa.esig.dss.enumerations.SubIndication; -import eu.europa.esig.dss.validation.reports.Reports; -import eu.europa.esig.dss.simplereport.SimpleReport; -import eu.europa.esig.dss.spi.x509.revocation.ocsp.OCSPSource; +import java.nio.file.Paths; +import java.security.cert.CertificateEncodingException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; public class SignatureTest extends AbstractTest { @Test - public void findOcspCertificateByHashkey() throws Exception { + public void findOcspCertificateByHashkey() { Container container = this.openContainerByConfiguration( Paths.get("src/test/resources/testFiles/valid-containers/OCSPRigaTest.asice"), this.configuration); Signature signature = container.getSignatures().get(0); @@ -78,19 +66,10 @@ public void testTimeStampCreationTimeForBDoc() throws ParseException { Assert.assertEquals(dateFormat.parse("Nov 17 2014 16:11:46"), timeStampCreationTime); } - @Test(expected = DigiDoc4JException.class) - public void testTimeStampCreationTimeForDDoc() throws ParseException { - Container container = this.createEmptyContainerBy(Container.DocumentType.DDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - container.sign(this.pkcs12SignatureToken); - container.getSignatures().get(0).getTimeStampCreationTime(); - container.getSignatures().get(0).getTimeStampCreationTime(); - } - @Test - public void testTimeStampCreationTimeForBDocWhereNotOCSP() throws ParseException, IOException { + public void testTimeStampCreationTimeForBDocWhereNotOCSP() { Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_BES, - this.pkcs12SignatureToken); + pkcs12SignatureToken); Assert.assertNull(signature.getTimeStampCreationTime()); } @@ -103,7 +82,7 @@ public void testGetTimeStampTokenCertificateForBDoc() throws Exception { } @Test - public void testGetTimeStampTokenCertificateForBDocNoTimeStampExists() throws Exception { + public void testGetTimeStampTokenCertificateForBDocNoTimeStampExists() { Signature signature = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/asics_for_testing.bdoc").getSignatures().get(0); Assert.assertNull(signature.getTimeStampTokenCertificate()); @@ -126,7 +105,7 @@ public void testGetSigningTimeForDDOC() { @Test public void testGetSigningTimeForBDoc() { - Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, this.pkcs12SignatureToken); + Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, pkcs12SignatureToken); Assert.assertTrue(DateUtils.isAlmostNow(signature.getClaimedSigningTime())); } @@ -174,30 +153,18 @@ public void testGetOCSPCertificateForDDoc() throws CertificateEncodingException @Test public void testGetOCSPCertificateForBDoc() throws CertificateEncodingException { - Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, this.pkcs12SignatureToken); + Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, pkcs12SignatureToken); byte[] encoded = signature.getOCSPCertificate().getX509Certificate().getEncoded(); Assert.assertEquals(Certificates.OCSP_CERTIFICATE_2020, Base64.encodeBase64String(encoded)); } - @Test - public void testGetSignaturePolicyForDDoc() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - Assert.assertEquals("", container.getSignatures().get(0).getPolicy()); - } - - @Test(expected = NotYetImplementedException.class) - public void testGetSignaturePolicyForBDoc() throws Exception { - Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, this.pkcs12SignatureToken); - Assert.assertEquals("", signature.getPolicy()); - } - @Test public void testGetProducedAtForDDoc() { this.configuration = Configuration.of(Configuration.Mode.TEST); ConfigManagerInitializer.forceInitConfigManager(this.configuration); Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); Signature signature = container.getSignatures().get(0); - Assert.assertNotNull(signature.getProducedAt()); + Assert.assertNotNull(signature.getOCSPResponseCreationTime()); } @Test @@ -205,7 +172,7 @@ public void testGetProducedAtForBDoc() throws ParseException { Container container = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/ocsp_cert_is_not_in_tsl.bdoc"); Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse("2014-07-08 12:51:16 +0000"); - Assert.assertEquals(date, container.getSignatures().get(0).getProducedAt()); + Assert.assertEquals(date, container.getSignatures().get(0).getOCSPResponseCreationTime()); } @Test @@ -217,7 +184,7 @@ public void testValidationForDDoc() { } @Test - public void testValidationForBDocDefaultValidation() throws Exception { + public void testValidationForBDocDefaultValidation() { this.configuration = new Configuration(Configuration.Mode.TEST); TestTSLUtil.addSkTsaCertificateToTsl(this.configuration); Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/two_signatures.bdoc", @@ -229,7 +196,7 @@ public void testValidationForBDocDefaultValidation() throws Exception { } @Test - public void testValidationForBDocDefaultValidationWithFailure() throws Exception { + public void testValidationForBDocDefaultValidationWithFailure() { Signature signature = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/ocsp_cert_is_not_in_tsl.bdoc").getSignatures().get(0); List errors = signature.validateSignature().getErrors(); @@ -238,15 +205,15 @@ public void testValidationForBDocDefaultValidationWithFailure() throws Exception } @Test - public void testValidationForBDocDefaultValidationWithOneFailing() throws Exception { + public void testValidationForBDocDefaultValidationWithOneFailing() { Container container = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/two_signatures_one_invalid.bdoc"); Signature signature = container.getSignatures().get(0); Assert.assertEquals(0, signature.validateSignature().getErrors().size()); signature = container.getSignatures().get(1); - Assert.assertEquals(2, signature.validateSignature().getErrors().size()); + Assert.assertEquals(4, signature.validateSignature().getErrors().size()); SignatureValidationResult validate = container.validate(); - Assert.assertEquals(2, validate.getErrors().size()); + Assert.assertEquals(4, validate.getErrors().size()); String report = validate.getReport(); Assert.assertTrue(report.contains("SignatureFormat=\"XAdES-BASELINE-LT\" Id=\"S0\"")); Assert.assertTrue(report.contains("SignatureFormat=\"XAdES-BASELINE-LT\" Id=\"S1\"")); @@ -261,19 +228,6 @@ public void testValidationWithInvalidDDoc() { Assert.assertEquals(4, signature.validateSignature().getErrors().size()); } - @Test - public void testGetSignaturePolicyURIForDDoc() { - Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); - Assert.assertNull(container.getSignatures().get(0).getSignaturePolicyURI()); - } - - @Test(expected = NotYetImplementedException.class) - public void testGetSignaturePolicyURIForBDoc() throws Exception { - Container container = ContainerOpener.open( - "src/test/resources/testFiles/invalid-containers/ocsp_cert_is_not_in_tsl.bdoc"); - Assert.assertEquals(new URI(""), container.getSignatures().get(0).getSignaturePolicyURI()); - } - @Test public void testGetSignatureMethodDDoc() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); @@ -296,14 +250,14 @@ public void testGetProfileForDDoc() { } @Test - public void testGetProfileForBDoc_TS() throws Exception { + public void testGetProfileForBDoc_TS() { Container container = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/ocsp_cert_is_not_in_tsl.bdoc"); Assert.assertEquals(SignatureProfile.LT, container.getSignatures().get(0).getProfile()); } @Test - public void testGetProfileForBDoc_None() throws Exception { + public void testGetProfileForBDoc_None() { Container container = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/asics_for_testing.bdoc"); Assert.assertEquals(SignatureProfile.B_BES, container.getSignatures().get(0).getProfile()); @@ -329,14 +283,14 @@ public void testGetNonceForAsiceWithoutNonce() { } @Test - public void testGetSignaturesWhereNoSignaturePresent() throws Exception { + public void testGetSignaturesWhereNoSignaturePresent() { Container container = new DDocOpener().open( "src/test/resources/testFiles/invalid-containers/empty_container_no_signature.ddoc"); Assert.assertTrue(container.getSignatures().isEmpty()); } @Test - public void testGetSignaturesWhereSignatureDoesNotHaveLastCertificate() throws Exception { + public void testGetSignaturesWhereSignatureDoesNotHaveLastCertificate() { Container container = new DDocOpener().open( "src/test/resources/testFiles/invalid-containers/signature_without_last_certificate.ddoc"); Assert.assertEquals(0, container.getSignatures().size()); @@ -345,7 +299,7 @@ public void testGetSignaturesWhereSignatureDoesNotHaveLastCertificate() throws E @Test public void getSignatureXMLForBDOC() throws Exception { Container container = this.createNonEmptyContainer(); - Signature signature = this.createSignatureBy(container, this.pkcs12SignatureToken); + Signature signature = this.createSignatureBy(container, pkcs12SignatureToken); container.saveAsFile("getSignatureXMLForBDOC.bdoc"); String signatureFromContainer = Helper.extractSignature("getSignatureXMLForBDOC.bdoc", 0); Helper.deleteFile("getSignatureXMLForBDOC.bdoc"); @@ -353,35 +307,35 @@ public void getSignatureXMLForBDOC() throws Exception { } @Test - public void signature_withoutProductionPlace_shouldNotThrowException() throws Exception { + public void signature_withoutProductionPlace_shouldNotThrowException() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); this.assertProductionPlaceIsNull(container.getSignatures().get(0)); } @Test - public void bDocBESSignature_TrustedSigningTime_shouldReturnNull() throws Exception { + public void bDocBESSignature_TrustedSigningTime_shouldReturnNull() { Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_BES, - this.pkcs12SignatureToken); + pkcs12SignatureToken); Assert.assertNull(signature.getTrustedSigningTime()); } @Test - public void dDocBESSignature_TrustedSigningTime_shouldReturnNull() throws Exception { + public void dDocBESSignature_TrustedSigningTime_shouldReturnNull() { Container container = ContainerOpener.open( "src/test/resources/testFiles/invalid-containers/B_BES-signature-profile.ddoc"); Assert.assertNull(container.getSignatures().get(0).getTrustedSigningTime()); } @Test - public void bDocTimeMarkSignature_TrustedSigningTime_shouldReturnOCSPResponseCreationTime() throws Exception { + public void bDocTimeMarkSignature_TrustedSigningTime_shouldReturnOCSPResponseCreationTime() { Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT_TM, - this.pkcs12SignatureToken); + pkcs12SignatureToken); Assert.assertNotNull(signature.getTrustedSigningTime()); Assert.assertEquals(signature.getOCSPResponseCreationTime(), signature.getTrustedSigningTime()); } @Test - public void dDocTimeMarkSignature_TrustedSigningTime_shouldReturnOCSPResponseCreationTime() throws Exception { + public void dDocTimeMarkSignature_TrustedSigningTime_shouldReturnOCSPResponseCreationTime() { this.configuration = Configuration.of(Configuration.Mode.TEST); ConfigManagerInitializer.forceInitConfigManager(this.configuration); Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/ddoc_for_testing.ddoc"); @@ -391,23 +345,23 @@ public void dDocTimeMarkSignature_TrustedSigningTime_shouldReturnOCSPResponseCre } @Test - public void bDocTimeStampSignature_TrustedSigningTime_shouldReturnTimeStampCreationTime() throws Exception { + public void bDocTimeStampSignature_TrustedSigningTime_shouldReturnTimeStampCreationTime() { Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT, - this.pkcs12SignatureToken); + pkcs12SignatureToken); Assert.assertNotNull(signature.getTrustedSigningTime()); Assert.assertEquals(signature.getTimeStampCreationTime(), signature.getTrustedSigningTime()); } @Test - public void bDocLTASignature_TrustedSigningTime_shouldReturnTimeStampCreationTime() throws Exception { + public void bDocLTASignature_TrustedSigningTime_shouldReturnTimeStampCreationTime() { Signature signature = this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LTA, - this.pkcs12SignatureToken); + pkcs12SignatureToken); Assert.assertNotNull(signature.getTrustedSigningTime()); Assert.assertEquals(signature.getTimeStampCreationTime(), signature.getTrustedSigningTime()); } @Test - public void getSignatureSigningCertificateDetails() throws Exception { + public void getSignatureSigningCertificateDetails() { Container container = TestDataBuilderUtil.open("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc"); Signature signature = container.getSignatures().get(0); X509Cert cert = signature.getSigningCertificate(); @@ -417,7 +371,7 @@ public void getSignatureSigningCertificateDetails() throws Exception { } @Test - public void gettingOcspCertificate_whenTslIsNotLoaded() throws Exception { + public void gettingOcspCertificate_whenTslIsNotLoaded() { this.configuration = new Configuration(Configuration.Mode.TEST); TSLCertificateSource certificateSource = new TSLCertificateSourceImpl(); this.configuration.setTSL(certificateSource); @@ -437,7 +391,7 @@ public void certificateContainsNotSupportedTssQcQualifier() { } @Test - public void signatureReportForTwoSignature() throws Exception { + public void signatureReportForTwoSignature() { this.configuration = new Configuration(Configuration.Mode.PROD); Container container = this.openContainerByConfiguration( Paths.get("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"), @@ -455,7 +409,7 @@ public void signatureReportForTwoSignature() throws Exception { } @Test - public void signatureReportForOneSignature() throws Exception { + public void signatureReportForOneSignature() { this.configuration = new Configuration(Configuration.Mode.TEST); Container container = this.openContainerByConfiguration( Paths.get("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc"), this.configuration); @@ -464,32 +418,32 @@ public void signatureReportForOneSignature() throws Exception { for (String id : signatureSimpleReport.getSignatureIdList()) { //"id-6a5d6671af7a9e0ab9a5e4d49d69800d" Assert.assertEquals(Indication.TOTAL_PASSED, result.getIndication(id)); - Assert.assertEquals(null, result.getSubIndication(id)); + Assert.assertNull(result.getSubIndication(id)); Assert.assertEquals(SignatureQualification.QESIG.getLabel(), result.getSignatureQualification(id).getLabel()); } } Assert.assertEquals(Indication.TOTAL_PASSED, result.getIndication(null)); - Assert.assertEquals(null, result.getSubIndication(null)); + Assert.assertNull(result.getSubIndication(null)); Assert.assertEquals(SignatureQualification.QESIG.getLabel(), result.getSignatureQualification(null).getLabel()); } @Test - public void signatureReportNoSignature() throws Exception { + public void signatureReportNoSignature() { this.configuration = new Configuration(Configuration.Mode.TEST); Container container = this.openContainerByConfiguration( Paths.get("src/test/resources/testFiles/valid-containers/container_without_signatures.bdoc"), this.configuration); SignatureValidationResult result = container.validate(); - Assert.assertEquals(null, result.getIndication("S0")); - Assert.assertEquals(null, result.getSubIndication("S0")); - Assert.assertEquals(null, result.getSignatureQualification("S0")); - Assert.assertEquals(null, result.getIndication(null)); - Assert.assertEquals(null, result.getSubIndication(null)); - Assert.assertEquals(null, result.getSignatureQualification(null)); + Assert.assertNull(result.getIndication("S0")); + Assert.assertNull(result.getSubIndication("S0")); + Assert.assertNull(result.getSignatureQualification("S0")); + Assert.assertNull(result.getIndication(null)); + Assert.assertNull(result.getSubIndication(null)); + Assert.assertNull(result.getSignatureQualification(null)); } @Test - public void signatureReportOnlyOneSignatureValid() throws Exception { + public void signatureReportOnlyOneSignatureValid() { this.configuration = new Configuration(Configuration.Mode.TEST); Container container = this.openContainerByConfiguration( Paths.get("src/test/resources/testFiles/invalid-containers/two_signatures_one_invalid.bdoc"), @@ -501,7 +455,7 @@ public void signatureReportOnlyOneSignatureValid() throws Exception { Assert.assertEquals(SignatureQualification.INDETERMINATE_QESIG.getLabel(), result.getSignatureQualification("S1").getLabel()); //Signature with id "S0" is valid Assert.assertEquals(Indication.TOTAL_PASSED, result.getIndication(null)); - Assert.assertEquals(null, result.getSubIndication(null)); + Assert.assertNull(result.getSubIndication(null)); Assert.assertEquals(SignatureQualification.QESIG.getLabel(), result.getSignatureQualification(null).getLabel()); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/ContainerSigningWithOutDataToSignSerializationTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/ContainerSigningWithOutDataToSignSerializationTest.java index 77d3a0361..6d44f3c86 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/ContainerSigningWithOutDataToSignSerializationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/ContainerSigningWithOutDataToSignSerializationTest.java @@ -88,7 +88,7 @@ public void emptyAsicETwoStepSigning() { Container container = createEmptyContainerBy(ASICE); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); DataToSign dataToSign = SignatureBuilder.aSignature(container) - .withSigningCertificate(this.pkcs12SignatureToken.getCertificate()) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureProfile(SignatureProfile.LT) .buildDataToSign(); @@ -122,7 +122,7 @@ public void emptyAsicETwoStepSigning() { public void signedBDocTwoStepSigning() { Container container = this.openContainerBy(Paths.get("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc")); DataToSign dataToSign = SignatureBuilder.aSignature(container) - .withSigningCertificate(this.pkcs12SignatureToken.getCertificate()) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureProfile(SignatureProfile.LT_TM) .buildDataToSign(); @@ -153,7 +153,7 @@ public void signedBDocTwoStepSigning() { public void signedAsicETwoStepSigning() { Container container = this.openContainerBy(Paths.get("src/test/resources/testFiles/valid-containers/valid-asice.asice")); DataToSign dataToSign = SignatureBuilder.aSignature(container) - .withSigningCertificate(this.pkcs12SignatureToken.getCertificate()) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureProfile(SignatureProfile.LT) .buildDataToSign(); @@ -187,7 +187,7 @@ public void twoStepSigningSigningTimeAssertion() throws InterruptedException { // Signature object returned signing dates have milliseconds removed, truncated also from test data long claimedSigningTimeLowerBound = new Date().getTime() / 1000 * 1000; DataToSign dataToSign = SignatureBuilder.aSignature(container) - .withSigningCertificate(this.pkcs12SignatureToken.getCertificate()) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureProfile(SignatureProfile.LT_TM) .buildDataToSign(); long claimedSigningTimeUpperBound = new Date().getTime() + 1000; @@ -201,14 +201,14 @@ public void twoStepSigningSigningTimeAssertion() throws InterruptedException { // Artificial delay to make claimed signing time and actual signing time differ Thread.sleep(1000); - long signingTimeLowerBound = new Date().getTime() / 1000 * 1000; + long trustedSigningTimeLowerBound = new Date().getTime() / 1000 * 1000; Signature signature = SignatureFinalizerBuilder.aFinalizer(container, dataToSign.getSignatureParameters()) .finalizeSignature(signatureValue); - long signingTimeUpperBound = new Date().getTime() + 1000; + long trustedSigningTimeUpperBound = new Date().getTime() + 1000; - long signingTime = signature.getSigningTime().getTime(); - assertTrue(signingTime >= signingTimeLowerBound); - assertTrue(signingTime <= signingTimeUpperBound); + long trustedSigningTime = signature.getTrustedSigningTime().getTime(); + assertTrue(trustedSigningTime >= trustedSigningTimeLowerBound); + assertTrue(trustedSigningTime <= trustedSigningTimeUpperBound); long claimedSigningTime = signature.getClaimedSigningTime().getTime(); assertTrue(claimedSigningTime >= claimedSigningTimeLowerBound); diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/DataToSignSerializationTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/DataToSignSerializationTest.java index 94fed99b7..cde371ee9 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/DataToSignSerializationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/DataToSignSerializationTest.java @@ -255,9 +255,9 @@ private Signature finalizeAndValidateSignature(DataToSign dataToSign, int dataFi byte[] signatureValue = pkcs12SignatureToken.sign(dataToSignDeserialized.getDigestAlgorithm(), dataToSignDeserialized.getDataToSign()); assertEquals(SIGNATURE_SIZE, signatureValue.length); - long signingTimeLowerBound = new Date().getTime() / 1000 * 1000; + long trustedSigningTimeLowerBound = new Date().getTime() / 1000 * 1000; Signature signature = dataToSignDeserialized.finalize(signatureValue); - assertSigningTime(signature.getSigningTime(), signingTimeLowerBound); + assertSigningTime(signature.getTrustedSigningTime(), trustedSigningTimeLowerBound); assertValidSignature(signature); return signature; diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/ServiceAccessScopeTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/ServiceAccessScopeTest.java index e9e684da1..a87098abe 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/ServiceAccessScopeTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/ServiceAccessScopeTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl; import org.digidoc4j.ServiceType; @@ -20,134 +30,134 @@ @RunWith(MockitoJUnitRunner.class) public class ServiceAccessScopeTest { - @Mock - private ServiceAccessEvent mockedEvent; - @Mock - private ServiceAccessListener mockedListener; - @Mock - private Supplier mockedEventSupplier; - - @Before - public void setUpMockedEventSupplier() { - Mockito.doReturn(mockedEvent).when(mockedEventSupplier).get(); + @Mock + private ServiceAccessEvent mockedEvent; + @Mock + private ServiceAccessListener mockedListener; + @Mock + private Supplier mockedEventSupplier; + + @Before + public void setUpMockedEventSupplier() { + Mockito.doReturn(mockedEvent).when(mockedEventSupplier).get(); + } + + @Test + public void listenerShouldBeNotifiedFromInsideServiceAccessScope() { + try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); } - - @Test - public void listenerShouldBeNotifiedFromInsideServiceAccessScope() { - try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); - } - Mockito.verify(mockedEventSupplier, Mockito.times(1)).get(); - Mockito.verify(mockedListener, Mockito.times(1)).accept(mockedEvent); - Mockito.verifyNoMoreInteractions(mockedEventSupplier, mockedListener); - Mockito.verifyZeroInteractions(mockedEvent); + Mockito.verify(mockedEventSupplier, Mockito.times(1)).get(); + Mockito.verify(mockedListener, Mockito.times(1)).accept(mockedEvent); + Mockito.verifyNoMoreInteractions(mockedEventSupplier, mockedListener); + Mockito.verifyNoInteractions(mockedEvent); + } + + @Test + public void listenerShouldNotBeNotifiedBeforeEnteringServiceAccessScope() { + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); + try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { } + Mockito.verifyNoInteractions(mockedEventSupplier, mockedListener, mockedEvent); + } - @Test - public void listenerShouldNotBeNotifiedBeforeEnteringServiceAccessScope() { - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); - try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { - } - Mockito.verifyZeroInteractions(mockedEventSupplier, mockedListener, mockedEvent); + @Test + public void listenerShouldNotBeNotifiedAfterLeavingServiceAccessScope() { + try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { } - - @Test - public void listenerShouldNotBeNotifiedAfterLeavingServiceAccessScope() { - try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { - } - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); - Mockito.verifyZeroInteractions(mockedEventSupplier, mockedListener, mockedEvent); + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); + Mockito.verifyNoInteractions(mockedEventSupplier, mockedListener, mockedEvent); + } + + @Test + public void listenerShouldNotBeNotifiedAfterManuallyClosingServiceAccessScope() { + try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { + scope.close(); + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); } - - @Test - public void listenerShouldNotBeNotifiedAfterManuallyClosingServiceAccessScope() { - try (ServiceAccessScope scope = new ServiceAccessScope(mockedListener)) { - scope.close(); - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(mockedEventSupplier); - } - Mockito.verifyZeroInteractions(mockedEventSupplier, mockedListener, mockedEvent); + Mockito.verifyNoInteractions(mockedEventSupplier, mockedListener, mockedEvent); + } + + @Test + public void eventsShouldBeCaughtOnlyInTheSameThreadTheyWerePublishedIn() throws Exception { + ThreadSafeListener threadSafeListener = new ThreadSafeListener(); + ExecutorService executorService = Executors.newFixedThreadPool(4); + + try (ServiceAccessScope scope = new ServiceAccessScope(threadSafeListener)) { + executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(ServiceType.TSP)); + executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(ServiceType.OCSP)); + executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); + + Future result = executorService.submit(() -> notifyExternalServiceAccessListenerInLocalScope(ServiceType.AIA_OCSP)); + Assert.assertEquals(1, result.get().getReceivedEvents().size()); + + executorService.shutdown(); + Assert.assertTrue( + "Abnormal termination of " + executorService.getClass().getSimpleName(), + executorService.awaitTermination(10L, TimeUnit.SECONDS) + ); + } finally { + executorService.shutdownNow(); } - @Test - public void eventsShouldBeCaughtOnlyInTheSameThreadTheyWerePublishedIn() throws Exception { - ThreadSafeListener threadSafeListener = new ThreadSafeListener(); - ExecutorService executorService = Executors.newFixedThreadPool(4); - - try (ServiceAccessScope scope = new ServiceAccessScope(threadSafeListener)) { - executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(ServiceType.TSP)); - executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(ServiceType.OCSP)); - executorService.submit(() -> notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType.AIA_OCSP)); - - Future result = executorService.submit(() -> notifyExternalServiceAccessListenerInLocalScope(ServiceType.AIA_OCSP)); - Assert.assertEquals(1, result.get().getReceivedEvents().size()); - - executorService.shutdown(); - Assert.assertTrue( - "Abnormal termination of " + executorService.getClass().getSimpleName(), - executorService.awaitTermination(10L, TimeUnit.SECONDS) - ); - } finally { - executorService.shutdownNow(); - } - - List receivedEvents = threadSafeListener.getReceivedEvents(); - Assert.assertEquals(2, receivedEvents.size()); - - assertEventFromCurrentThread(ServiceType.TSP, receivedEvents.get(0)); - assertEventFromCurrentThread(ServiceType.OCSP, receivedEvents.get(1)); - } + List receivedEvents = threadSafeListener.getReceivedEvents(); + Assert.assertEquals(2, receivedEvents.size()); - static void notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType serviceType) { - ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(serviceType)); - } + assertEventFromCurrentThread(ServiceType.TSP, receivedEvents.get(0)); + assertEventFromCurrentThread(ServiceType.OCSP, receivedEvents.get(1)); + } - static ThreadSafeListener notifyExternalServiceAccessListenerInLocalScope(ServiceType serviceType) { - ThreadSafeListener threadSafeListener = new ThreadSafeListener(); - try (ServiceAccessScope scope = new ServiceAccessScope(threadSafeListener)) { - notifyExternalServiceAccessListenerWithoutExplicitScope(serviceType); - } - List receivedEvents = threadSafeListener.getReceivedEvents(); - Assert.assertEquals(1, receivedEvents.size()); - assertEventFromCurrentThread(serviceType, receivedEvents.get(0)); - return threadSafeListener; - } + static void notifyExternalServiceAccessListenerWithoutExplicitScope(ServiceType serviceType) { + ServiceAccessScope.notifyExternalServiceAccessListenerIfPresent(new ThreadBasedEventSupplier(serviceType)); + } - static void assertEventFromCurrentThread(ServiceType expectedServiceType, ServiceAccessEvent actualEvent) { - Assert.assertEquals(Thread.currentThread().getName() + "/" + expectedServiceType, actualEvent.getServiceUrl()); - Assert.assertEquals(expectedServiceType, actualEvent.getServiceType()); + static ThreadSafeListener notifyExternalServiceAccessListenerInLocalScope(ServiceType serviceType) { + ThreadSafeListener threadSafeListener = new ThreadSafeListener(); + try (ServiceAccessScope scope = new ServiceAccessScope(threadSafeListener)) { + notifyExternalServiceAccessListenerWithoutExplicitScope(serviceType); } + List receivedEvents = threadSafeListener.getReceivedEvents(); + Assert.assertEquals(1, receivedEvents.size()); + assertEventFromCurrentThread(serviceType, receivedEvents.get(0)); + return threadSafeListener; + } - static class ThreadSafeListener implements ServiceAccessListener { + static void assertEventFromCurrentThread(ServiceType expectedServiceType, ServiceAccessEvent actualEvent) { + Assert.assertEquals(Thread.currentThread().getName() + "/" + expectedServiceType, actualEvent.getServiceUrl()); + Assert.assertEquals(expectedServiceType, actualEvent.getServiceType()); + } - private final ArrayList receivedEvents = new ArrayList<>(); + static class ThreadSafeListener implements ServiceAccessListener { - @Override - public synchronized void accept(ServiceAccessEvent serviceAccessEvent) { - receivedEvents.add(serviceAccessEvent); - } + private final ArrayList receivedEvents = new ArrayList<>(); - public synchronized List getReceivedEvents() { - return new ArrayList<>(receivedEvents); - } + @Override + public synchronized void accept(ServiceAccessEvent serviceAccessEvent) { + receivedEvents.add(serviceAccessEvent); + } + public synchronized List getReceivedEvents() { + return new ArrayList<>(receivedEvents); } - static class ThreadBasedEventSupplier implements Supplier { + } - private final ServiceType serviceType; + static class ThreadBasedEventSupplier implements Supplier { - public ThreadBasedEventSupplier(ServiceType serviceType) { - this.serviceType = serviceType; - } + private final ServiceType serviceType; - @Override - public ServiceAccessEvent get() { - String serviceUrl = Thread.currentThread().getName() + "/" + serviceType; - return new ServiceAccessEvent(serviceUrl, serviceType, true); - } + public ThreadBasedEventSupplier(ServiceType serviceType) { + this.serviceType = serviceType; + } + @Override + public ServiceAccessEvent get() { + String serviceUrl = Thread.currentThread().getName() + "/" + serviceType; + return new ServiceAccessEvent(serviceUrl, serviceType, true); } + } + } \ No newline at end of file diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/StreamDocumentTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/StreamDocumentTest.java index c9fe9575c..56fc2419e 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/StreamDocumentTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/StreamDocumentTest.java @@ -27,6 +27,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; @@ -107,7 +108,7 @@ public void getName() throws Exception { @Test public void getAbsolutePath() throws Exception { - Assert.assertTrue(this.document.getAbsolutePath(), this.document.getAbsolutePath().matches(".*digidoc4j.*.\\.tmp")); + Assert.assertTrue(this.document.temporaryFile.getAbsolutePath(), this.document.temporaryFile.getAbsolutePath().matches(".*digidoc4j.*.\\.tmp")); } @Test @@ -168,7 +169,7 @@ public void getDigest() throws Exception { /* NB! If this test fails then ensure that directory testFiles/tmp/readonly is read-only! */ - @Test(expected = DSSException.class) + @Test(expected = FileNotFoundException.class) public void saveWhenNoAccessRights() throws Exception { File tmp = StreamDocumentTest.readOnlyPath.toFile(); String dataFileName = tmp.getAbsolutePath() + File.separator + "no_access.txt"; diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/UncompressedAsicEntryTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/UncompressedAsicEntryTest.java index 1d8023217..3853eba25 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/UncompressedAsicEntryTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/UncompressedAsicEntryTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl; import org.digidoc4j.impl.asic.AsicEntry; @@ -58,7 +68,7 @@ public void updatingMetadataDoesNotFetchContentBytesNorOverrideMetadataIfPresent ZipEntry derivedZipEntry = asicEntry.getZipEntry(); assertZipEntry(derivedZipEntry, 3L, 345L); - Mockito.verifyZeroInteractions(supplierMock); + Mockito.verifyNoInteractions(supplierMock); } @Test diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/DataLoaderDecoratorTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/DataLoaderDecoratorTest.java index 6529c2cb5..959107a33 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/DataLoaderDecoratorTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/DataLoaderDecoratorTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl.asic; import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; @@ -19,6 +29,7 @@ @RunWith(MockitoJUnitRunner.class) public class DataLoaderDecoratorTest { + private static final String KEYSTORE_PATH = "classpath:testFiles/keystores/keystore.jks"; private static final String TRUSTSTORE_PATH = "classpath:testFiles/keystores/truststore.p12"; @@ -336,9 +347,11 @@ public void decorateWithProxySettingsForShouldDoNothingWhenNetworkProxyNotEnable public void decorateWithProxySettingsShouldApplyNullConfigIfHostIsNotConfigured() { Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); Mockito.doReturn(8073).when(configuration).getHttpProxyPort(); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUser(); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPassword(); Mockito.doReturn(473).when(configuration).getHttpsProxyPort(); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUser(); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUser(); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPassword(); DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -350,9 +363,11 @@ public void decorateWithProxySettingsForShouldApplyNullConfigIfHostIsNotConfigur for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); Mockito.doReturn(8073).when(configuration).getHttpProxyPortFor(connectionType); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUserFor(connectionType); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); Mockito.doReturn(473).when(configuration).getHttpsProxyPortFor(connectionType); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUserFor(connectionType); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUserFor(connectionType); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPasswordFor(connectionType); DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -367,10 +382,12 @@ public void decorateWithProxySettingsShouldApplyNullConfigIfPortIsNotConfigured( Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); Mockito.doReturn(null).when(configuration).getHttpProxyPort(); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHost(); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUser(); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPassword(); Mockito.doReturn(null).when(configuration).getHttpsProxyPort(); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHost(); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUser(); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUser(); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPassword(); DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -383,10 +400,12 @@ public void decorateWithProxySettingsForShouldApplyNullConfigIfPortIsNotConfigur Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); Mockito.doReturn(null).when(configuration).getHttpProxyPortFor(connectionType); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHostFor(connectionType); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUserFor(connectionType); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); Mockito.doReturn(null).when(configuration).getHttpsProxyPortFor(connectionType); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHostFor(connectionType); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUserFor(connectionType); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUserFor(connectionType); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPasswordFor(connectionType); DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -481,8 +500,8 @@ public void decorateWithProxySettingsShouldApplyHttpUserAndPasswordIfConfigured( Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); Mockito.doReturn(8073).when(configuration).getHttpProxyPort(); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHost(); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUser(); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUser(); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPassword(); DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -492,8 +511,8 @@ public void decorateWithProxySettingsShouldApplyHttpUserAndPasswordIfConfigured( Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); } @Test @@ -502,8 +521,8 @@ public void decorateWithProxySettingsForShouldApplyHttpUserAndPasswordIfConfigur Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); Mockito.doReturn(8073).when(configuration).getHttpProxyPortFor(connectionType); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHostFor(connectionType); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUserFor(connectionType); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUserFor(connectionType); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -513,8 +532,8 @@ public void decorateWithProxySettingsForShouldApplyHttpUserAndPasswordIfConfigur Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); Mockito.reset(configuration, dataLoader); } @@ -525,8 +544,8 @@ public void decorateWithProxySettingsShouldApplyHttpsUserAndPasswordIfConfigured Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); Mockito.doReturn(473).when(configuration).getHttpsProxyPort(); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHost(); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUser(); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUser(); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPassword(); DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -536,8 +555,8 @@ public void decorateWithProxySettingsShouldApplyHttpsUserAndPasswordIfConfigured Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpsProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); } @Test @@ -546,8 +565,8 @@ public void decorateWithProxySettingsForShouldApplyHttpsUserAndPasswordIfConfigu Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); Mockito.doReturn(473).when(configuration).getHttpsProxyPortFor(connectionType); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHostFor(connectionType); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUserFor(connectionType); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUserFor(connectionType); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPasswordFor(connectionType); DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -557,8 +576,128 @@ public void decorateWithProxySettingsForShouldApplyHttpsUserAndPasswordIfConfigu Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpsProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + + Mockito.reset(configuration, dataLoader); + } + } + + @Test + public void decorateWithProxySettingsShouldApplyAllButHttpUserAndPasswordIfNotConfigured() { + Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); + Mockito.doReturn(8073).when(configuration).getHttpProxyPort(); + Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHost(); + Mockito.doReturn(473).when(configuration).getHttpsProxyPort(); + Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHost(); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUser(); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPassword(); + + DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); + ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); + Assert.assertNotNull(capturedProxyConfig.getHttpProperties()); + Assert.assertNotNull(capturedProxyConfig.getHttpsProperties()); + + Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); + Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getPassword()); + + Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); + Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + } + + @Test + public void decorateWithProxySettingsForShouldApplyAllButHttpUserAndPasswordIfNotConfigured() { + for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { + Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); + Mockito.doReturn(8073).when(configuration).getHttpProxyPortFor(connectionType); + Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHostFor(connectionType); + Mockito.doReturn(473).when(configuration).getHttpsProxyPortFor(connectionType); + Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHostFor(connectionType); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUserFor(connectionType); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPasswordFor(connectionType); + + DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); + ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); + Assert.assertNotNull(capturedProxyConfig.getHttpProperties()); + Assert.assertNotNull(capturedProxyConfig.getHttpsProperties()); + + Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); + Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getPassword()); + + Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); + Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + + Mockito.reset(configuration, dataLoader); + } + } + + @Test + public void decorateWithProxySettingsShouldApplyAllButHttpsUserAndPasswordIfNotConfigured() { + Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); + Mockito.doReturn(8073).when(configuration).getHttpProxyPort(); + Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHost(); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUser(); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn(473).when(configuration).getHttpsProxyPort(); + Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHost(); + + DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); + ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); + Assert.assertNotNull(capturedProxyConfig.getHttpProperties()); + Assert.assertNotNull(capturedProxyConfig.getHttpsProperties()); + + Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); + Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + + Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); + Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getPassword()); + } + + @Test + public void decorateWithProxySettingsForShouldApplyAllButHttpsUserAndPasswordIfNotConfigured() { + for (final ExternalConnectionType connectionType : ExternalConnectionType.values()) { + Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); + Mockito.doReturn(8073).when(configuration).getHttpProxyPortFor(connectionType); + Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHostFor(connectionType); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUserFor(connectionType); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn(473).when(configuration).getHttpsProxyPortFor(connectionType); + Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHostFor(connectionType); + + DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); + ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); + Assert.assertNotNull(capturedProxyConfig.getHttpProperties()); + Assert.assertNotNull(capturedProxyConfig.getHttpsProperties()); + + Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); + Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + + Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); + Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertNull(capturedProxyConfig.getHttpsProperties().getPassword()); Mockito.reset(configuration, dataLoader); } @@ -569,10 +708,12 @@ public void decorateWithProxySettingsShouldApplyAllConfiguredProxySettings() { Mockito.doReturn(true).when(configuration).isNetworkProxyEnabled(); Mockito.doReturn(8073).when(configuration).getHttpProxyPort(); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHost(); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUser(); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPassword(); Mockito.doReturn(473).when(configuration).getHttpsProxyPort(); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHost(); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUser(); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPassword(); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUser(); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPassword(); DataLoaderDecorator.decorateWithProxySettings(dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -582,14 +723,14 @@ public void decorateWithProxySettingsShouldApplyAllConfiguredProxySettings() { Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpsProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); } @Test @@ -598,10 +739,12 @@ public void decorateWithProxySettingsForShouldApplyAllConfiguredProxySettings() Mockito.doReturn(true).when(configuration).isNetworkProxyEnabledFor(connectionType); Mockito.doReturn(8073).when(configuration).getHttpProxyPortFor(connectionType); Mockito.doReturn("httpProxyHost").when(configuration).getHttpProxyHostFor(connectionType); + Mockito.doReturn("httpProxyUser").when(configuration).getHttpProxyUserFor(connectionType); + Mockito.doReturn("httpProxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); Mockito.doReturn(473).when(configuration).getHttpsProxyPortFor(connectionType); Mockito.doReturn("httpsProxyHost").when(configuration).getHttpsProxyHostFor(connectionType); - Mockito.doReturn("proxyUser").when(configuration).getHttpProxyUserFor(connectionType); - Mockito.doReturn("proxyPassword").when(configuration).getHttpProxyPasswordFor(connectionType); + Mockito.doReturn("httpsProxyUser").when(configuration).getHttpsProxyUserFor(connectionType); + Mockito.doReturn("httpsProxyPassword").when(configuration).getHttpsProxyPasswordFor(connectionType); DataLoaderDecorator.decorateWithProxySettingsFor(connectionType, dataLoader, configuration); ProxyConfig capturedProxyConfig = verifyDataLoaderProxyConfigSetAndCaptureProxyConfig(); @@ -611,14 +754,14 @@ public void decorateWithProxySettingsForShouldApplyAllConfiguredProxySettings() Assert.assertEquals(8073, capturedProxyConfig.getHttpProperties().getPort()); Assert.assertEquals("httpProxyHost", capturedProxyConfig.getHttpProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); + Assert.assertEquals("httpProxyUser", capturedProxyConfig.getHttpProperties().getUser()); + Assert.assertEquals("httpProxyPassword", capturedProxyConfig.getHttpProperties().getPassword()); Assert.assertEquals(473, capturedProxyConfig.getHttpsProperties().getPort()); Assert.assertEquals("httpsProxyHost", capturedProxyConfig.getHttpsProperties().getHost()); Assert.assertNull(capturedProxyConfig.getHttpsProperties().getExcludedHosts()); - Assert.assertEquals("proxyUser", capturedProxyConfig.getHttpsProperties().getUser()); - Assert.assertEquals("proxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); + Assert.assertEquals("httpsProxyUser", capturedProxyConfig.getHttpsProperties().getUser()); + Assert.assertEquals("httpsProxyPassword", capturedProxyConfig.getHttpsProperties().getPassword()); Mockito.reset(configuration, dataLoader); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallbackTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallbackTest.java new file mode 100644 index 000000000..72ea03def --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/DefaultTSLRefreshCallbackTest.java @@ -0,0 +1,1275 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.impl.asic.tsl; + +import eu.europa.esig.dss.enumerations.Indication; +import eu.europa.esig.dss.enumerations.SubIndication; +import eu.europa.esig.dss.spi.tsl.DownloadInfoRecord; +import eu.europa.esig.dss.spi.tsl.LOTLInfo; +import eu.europa.esig.dss.spi.tsl.ParsingInfoRecord; +import eu.europa.esig.dss.spi.tsl.TLInfo; +import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; +import eu.europa.esig.dss.spi.tsl.ValidationInfoRecord; +import eu.europa.esig.dss.tsl.cache.state.CacheStateEnum; +import eu.europa.esig.dss.tsl.dto.AbstractCacheDTO; +import eu.europa.esig.dss.tsl.dto.DownloadCacheDTO; +import eu.europa.esig.dss.tsl.dto.ParsingCacheDTO; +import eu.europa.esig.dss.tsl.dto.ValidationCacheDTO; +import org.digidoc4j.AbstractTest; +import org.digidoc4j.Configuration; +import org.digidoc4j.exceptions.TslDownloadException; +import org.digidoc4j.exceptions.TslParsingException; +import org.digidoc4j.exceptions.TslRefreshException; +import org.digidoc4j.exceptions.TslValidationException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultTSLRefreshCallbackTest extends AbstractTest { + + private static final String LOTL_URL_1 = "http://lotl.host.first"; + + private static final String TL_URL_1 = "http://tl.host.first"; + private static final String TL_URL_2 = "http://tl.host.second"; + private static final String TL_URL_3 = "http://tl.host.third"; + private static final String TL_URL_4 = "http://tl.host.fourth"; + + private static final String TERRITORY_1 = "T1"; + private static final String TERRITORY_2 = "T2"; + private static final String TERRITORY_3 = "T3"; + private static final String TERRITORY_4 = "T4"; + + @Mock + private Configuration configuration; + @InjectMocks + private DefaultTSLRefreshCallback tslRefreshCallback; + + @Test + public void testSummaryWithNullLOTLInfos() { + testSummaryWithNoLOTLInfos(null); + } + + @Test + public void testSummaryWithEmptyLOTLInfos() { + testSummaryWithNoLOTLInfos(Collections.emptyList()); + } + + private void testSummaryWithNoLOTLInfos(List lotlInfos) { + TLValidationJobSummary summary = new TLValidationJobSummary(lotlInfos, null); + + TslRefreshException caughtException = Assert.assertThrows( + TslRefreshException.class, + () -> tslRefreshCallback.ensureTSLState(summary) + ); + + Assert.assertEquals("No TSL refresh info found!", caughtException.getMessage()); + Mockito.verifyNoInteractions(configuration); + } + + @Test + public void testSingleLOTLInfoWithNoDownloadInfo() { + TslDownloadException caughtException = testSingleLOTLInfoThrowingDownloadException(null); + Assert.assertEquals( + String.format("No download info found for <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithDownloadError() { + TslDownloadException caughtException = testSingleLOTLInfoThrowingDownloadException( + withErrorState(new DownloadCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to download <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithDownloadRefreshNeeded() { + TslDownloadException caughtException = testSingleLOTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)download needed for <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithUnexpectedDownloadStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslDownloadException caughtException = testSingleLOTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected download status '%s' for <%s> LoTL: %s", cacheState, TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslDownloadException testSingleLOTLInfoThrowingDownloadException(DownloadInfoRecord downloadInfo) { + LOTLInfo lotlInfo = new LOTLInfo( + downloadInfo, + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_1), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + LOTL_URL_1 + ); + + TslDownloadException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslDownloadException.class); + + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + return caughtException; + } + + @Test + public void testSingleLOTLInfoWithNoParsingInfo() { + TslParsingException caughtException = testSingleLOTLInfoThrowingParsingException(null); + Assert.assertEquals( + String.format("No parsing info found for LoTL: %s", LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithParsingError() { + TslParsingException caughtException = testSingleLOTLInfoThrowingParsingException( + withErrorState(new ParsingCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to parse LoTL: %s", LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithParsingRefreshNeeded() { + TslParsingException caughtException = testSingleLOTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)parsing needed for LoTL: %s", LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithUnexpectedParsingStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslParsingException caughtException = testSingleLOTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected parsing status '%s' for LoTL: %s", cacheState, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslParsingException testSingleLOTLInfoThrowingParsingException(ParsingInfoRecord parsingInfo) { + LOTLInfo lotlInfo = new LOTLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + parsingInfo, + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + LOTL_URL_1 + ); + + TslParsingException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslParsingException.class); + + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + return caughtException; + } + + @Test + public void testSingleLOTLInfoWithNoValidationInfo() { + TslValidationException caughtException = testSingleLOTLInfoThrowingValidationException(null); + Assert.assertEquals( + String.format("No validation info found for <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithValidationError() { + TslValidationException caughtException = testSingleLOTLInfoThrowingValidationException( + withErrorState(new ValidationCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to validate <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithValidationNotTotalPassed() { + for (Indication indication : nonValidIndications()) { + TslValidationException caughtException = testSingleLOTLInfoThrowingValidationException( + withSynchronizedState(new ValidationCacheDTO(), indication) + ); + Assert.assertEquals( + String.format("Failed to validate <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals( + String.format("<%s> LoTL validation failed; indication: %s", TERRITORY_1, indication), + caughtException.getCause().getMessage() + ); + Mockito.reset(configuration); + } + } + + @Test + public void testSingleLOTLInfoWithValidationRefreshNeeded() { + TslValidationException caughtException = testSingleLOTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)validation needed for <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithUnexpectedValidationStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslValidationException caughtException = testSingleLOTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected validation status '%s' for <%s> LoTL: %s", cacheState, TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslValidationException testSingleLOTLInfoThrowingValidationException(ValidationInfoRecord validationInfo) { + LOTLInfo lotlInfo = new LOTLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_1), + validationInfo, + LOTL_URL_1 + ); + + TslValidationException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslValidationException.class); + + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + return caughtException; + } + + @Test + public void testSingleLOTLInfoWithDownloadErrorAndParsingRefreshNeededAndValidationRefreshNeeded() { + LOTLInfo lotlInfo = new LOTLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message"), + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + LOTL_URL_1 + ); + + TslDownloadException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslDownloadException.class); + + Assert.assertEquals( + String.format("Failed to download LoTL: %s", LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(2, caughtException.getSuppressed().length); + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslParsingException); + Assert.assertEquals( + String.format("(Re)parsing needed for LoTL: %s", LOTL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for LoTL: %s", LOTL_URL_1), + caughtException.getSuppressed()[1].getMessage() + ); + Mockito.verifyNoInteractions(configuration); + } + + @Test + public void testSingleLOTLInfoWithParsingErrorAndValidationRefreshNeeded() { + LOTLInfo lotlInfo = new LOTLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withErrorState(new ParsingCacheDTO(), "Exception message"), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + LOTL_URL_1 + ); + + TslParsingException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslParsingException.class); + + Assert.assertEquals( + String.format("Failed to parse LoTL: %s", LOTL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(1, caughtException.getSuppressed().length); + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for LoTL: %s", LOTL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Mockito.verifyNoInteractions(configuration); + } + + private E testSingleLOTLInfoThrowingException(LOTLInfo lotlInfo, Class exceptionType) { + TLValidationJobSummary summary = new TLValidationJobSummary(Collections.singletonList(lotlInfo), null); + return Assert.assertThrows(exceptionType, () -> tslRefreshCallback.ensureTSLState(summary)); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithNoDownloadInfo() { + TslDownloadException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingDownloadException(null); + Assert.assertEquals( + String.format("No download info found for <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithDownloadError() { + TslDownloadException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingDownloadException( + withErrorState(new DownloadCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to download <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithDownloadRefreshNeeded() { + TslDownloadException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)download needed for <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithUnexpectedDownloadStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslDownloadException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected download status '%s' for <%s> TL: %s", cacheState, TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslDownloadException testSingleLOTLInfoWithSingleTLInfoThrowingDownloadException(DownloadInfoRecord downloadInfo) { + TLInfo tlInfo = new TLInfo( + downloadInfo, + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_2), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingException(tlInfo); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + + TslDownloadException downloadException = (TslDownloadException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], downloadException.getSuppressed()); + return downloadException; + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithNoParsingInfo() { + TslParsingException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingParsingException(null); + Assert.assertEquals( + String.format("No parsing info found for TL: %s", TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithParsingError() { + TslParsingException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingParsingException( + withErrorState(new ParsingCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to parse TL: %s", TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithParsingRefreshNeeded() { + TslParsingException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)parsing needed for TL: %s", TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoInfoWithUnexpectedParsingStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslParsingException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected parsing status '%s' for TL: %s", cacheState, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslParsingException testSingleLOTLInfoWithSingleTLInfoThrowingParsingException(ParsingInfoRecord parsingInfo) { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + parsingInfo, + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingException(tlInfo); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + + TslParsingException parsingException = (TslParsingException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], parsingException.getSuppressed()); + return parsingException; + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithNoValidationInfo() { + TslValidationException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingValidationException(null); + Assert.assertEquals( + String.format("No validation info found for <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithValidationError() { + TslValidationException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingValidationException( + withErrorState(new ValidationCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithValidationNotTotalPassed() { + for (Indication indication : nonValidIndications()) { + TslValidationException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingValidationException( + withSynchronizedState(new ValidationCacheDTO(), indication) + ); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals( + String.format("<%s> TL validation failed; indication: %s", TERRITORY_2, indication), + caughtException.getCause().getMessage() + ); + Mockito.reset(configuration); + } + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithValidationRefreshNeeded() { + TslValidationException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)validation needed for <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithUnexpectedValidationStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslValidationException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected validation status '%s' for <%s> TL: %s", cacheState, TERRITORY_2, TL_URL_1), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslValidationException testSingleLOTLInfoWithSingleTLInfoThrowingValidationException(ValidationInfoRecord validationInfo) { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_2), + validationInfo, + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingException(tlInfo); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + Mockito.verifyNoInteractions(configuration); + + TslValidationException validationException = (TslValidationException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], validationException.getSuppressed()); + return validationException; + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithDownloadErrorAndParsingRefreshNeededAndValidationRefreshNeeded() { + TLInfo tlInfo = new TLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message"), + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingException(tlInfo); + + Assert.assertNull(caughtException.getCause()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(3, caughtException.getSuppressed().length); + + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslDownloadException); + Assert.assertEquals( + String.format("Failed to download TL: %s", TL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[0].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[0].getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getSuppressed()[0].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[0].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslParsingException); + Assert.assertEquals( + String.format("(Re)parsing needed for TL: %s", TL_URL_1), + caughtException.getSuppressed()[1].getMessage() + ); + + Assert.assertTrue(caughtException.getSuppressed()[2] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for TL: %s", TL_URL_1), + caughtException.getSuppressed()[2].getMessage() + ); + Mockito.verifyNoInteractions(configuration); + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoWithParsingErrorAndValidationRefreshNeeded() { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withErrorState(new ParsingCacheDTO(), "Exception message"), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithSingleTLInfoThrowingException(tlInfo); + + Assert.assertNull(caughtException.getCause()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(2, caughtException.getSuppressed().length); + + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslParsingException); + Assert.assertEquals( + String.format("Failed to parse TL: %s", TL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[0].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[0].getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getSuppressed()[0].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[0].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for TL: %s", TL_URL_1), + caughtException.getSuppressed()[1].getMessage() + ); + Mockito.verifyNoInteractions(configuration); + } + + private TslRefreshException testSingleLOTLInfoWithSingleTLInfoThrowingException(TLInfo tlInfo) { + return testSingleLOTLInfoWithAllTLInfosThrowingException(Collections.singletonList(tlInfo)); + } + + @Test + public void testSingleLOTLInfoWithMultipleTLInfosAllFail() { + TslRefreshException caughtException = testSingleLOTLInfoWithAllTLInfosThrowingException(Arrays.asList( + new TLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message 1"), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_2), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_1 + ), + new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withErrorState(new ParsingCacheDTO(), "Exception message 2"), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_2 + ), + new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_3), + withErrorState(new ValidationCacheDTO(), "Exception message 3"), + TL_URL_3 + ), + new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_4), + withSynchronizedState(new ValidationCacheDTO(), Indication.INDETERMINATE, SubIndication.TRY_LATER), + TL_URL_4 + ) + )); + + Assert.assertNull(caughtException.getCause()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(4, caughtException.getSuppressed().length); + + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslDownloadException); + Assert.assertEquals( + String.format("Failed to download <%s> TL: %s", TERRITORY_2, TL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[0].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[0].getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message 1", caughtException.getSuppressed()[0].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[0].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslParsingException); + Assert.assertEquals( + String.format("Failed to parse TL: %s", TL_URL_2), + caughtException.getSuppressed()[1].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[1].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[1].getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message 2", caughtException.getSuppressed()[1].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[1].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[2] instanceof TslValidationException); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_3, TL_URL_3), + caughtException.getSuppressed()[2].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[2].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[2].getCause() instanceof TslValidationException); + Assert.assertEquals("Exception message 3", caughtException.getSuppressed()[2].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[2].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[3] instanceof TslValidationException); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_4, TL_URL_4), + caughtException.getSuppressed()[3].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[3].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[3].getCause() instanceof TslValidationException); + Assert.assertEquals( + String.format("<%s> TL validation failed; indication: INDETERMINATE; sub-indication: TRY_LATER", TERRITORY_4), + caughtException.getSuppressed()[3].getCause().getMessage() + ); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[3].getSuppressed()); + + Mockito.verifyNoInteractions(configuration); + } + + private TslRefreshException testSingleLOTLInfoWithAllTLInfosThrowingException(List tlInfos) { + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(tlInfos); + + TslRefreshException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslRefreshException.class); + + Assert.assertEquals( + String.format("Failed to load any trusted lists for <%s> LoTL: %s", TERRITORY_1, LOTL_URL_1), + caughtException.getMessage() + ); + return caughtException; + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithNoDownloadInfo() { + TslDownloadException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingDownloadException(null); + Assert.assertEquals( + String.format("No download info found for <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithDownloadError() { + TslDownloadException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingDownloadException( + withErrorState(new DownloadCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to download <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithDownloadRefreshNeeded() { + TslDownloadException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)download needed for <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithUnexpectedDownloadStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslDownloadException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingDownloadException( + withState(new DownloadCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected download status '%s' for <%s> TL: %s", cacheState, TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslDownloadException testSingleLOTLInfoWithRequiredTLInfoThrowingDownloadException(DownloadInfoRecord downloadInfo) { + TLInfo tlInfo = new TLInfo( + downloadInfo, + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_3), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_2 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingException(tlInfo, TERRITORY_3); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslDownloadException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + + TslDownloadException downloadException = (TslDownloadException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], downloadException.getSuppressed()); + return downloadException; + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithNoParsingInfo() { + TslParsingException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingParsingException(null); + Assert.assertEquals( + String.format("No parsing info found for TL: %s", TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithParsingError() { + TslParsingException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingParsingException( + withErrorState(new ParsingCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to parse TL: %s", TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithParsingRefreshNeeded() { + TslParsingException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)parsing needed for TL: %s", TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoInfoWithUnexpectedParsingStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslParsingException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingParsingException( + withState(new ParsingCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected parsing status '%s' for TL: %s", cacheState, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslParsingException testSingleLOTLInfoWithRequiredTLInfoThrowingParsingException(ParsingInfoRecord parsingInfo) { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + parsingInfo, + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + TL_URL_2 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingException(tlInfo, TERRITORY_3); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslParsingException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + + TslParsingException parsingException = (TslParsingException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], parsingException.getSuppressed()); + return parsingException; + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithNoValidationInfo() { + TslValidationException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException(null); + Assert.assertEquals( + String.format("No validation info found for <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithValidationError() { + TslValidationException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException( + withErrorState(new ValidationCacheDTO(), "Exception message") + ); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals("Exception message", caughtException.getCause().getMessage()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithValidationNotTotalPassed() { + for (Indication indication : nonValidIndications()) { + TslValidationException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException( + withSynchronizedState(new ValidationCacheDTO(), indication) + ); + Assert.assertEquals( + String.format("Failed to validate <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertEquals( + String.format("<%s> TL validation failed; indication: %s", TERRITORY_3, indication), + caughtException.getCause().getMessage() + ); + Mockito.reset(configuration); + } + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithValidationRefreshNeeded() { + TslValidationException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED) + ); + Assert.assertEquals( + String.format("(Re)validation needed for <%s> TL: %s", TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithUnexpectedValidationStatus() { + for (CacheStateEnum cacheState : unexpectedCacheStates()) { + TslValidationException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException( + withState(new ValidationCacheDTO(), cacheState) + ); + Assert.assertEquals( + String.format("Unexpected validation status '%s' for <%s> TL: %s", cacheState, TERRITORY_3, TL_URL_2), + caughtException.getMessage() + ); + Assert.assertNull(caughtException.getCause()); + Mockito.reset(configuration); + } + } + + private TslValidationException testSingleLOTLInfoWithRequiredTLInfoThrowingValidationException(ValidationInfoRecord validationInfo) { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), TERRITORY_3), + validationInfo, + TL_URL_2 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingException(tlInfo, TERRITORY_3); + + Assert.assertNotNull(caughtException.getCause()); + Assert.assertTrue(caughtException.getCause() instanceof TslValidationException); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()); + + TslValidationException validationException = (TslValidationException) caughtException.getCause(); + Assert.assertArrayEquals(new Throwable[0], validationException.getSuppressed()); + return validationException; + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithDownloadErrorAndParsingRefreshNeededAndValidationRefreshNeeded() { + TLInfo tlInfo = new TLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message"), + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_1 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingException(tlInfo, TERRITORY_2); + + Assert.assertNull(caughtException.getCause()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(3, caughtException.getSuppressed().length); + + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslDownloadException); + Assert.assertEquals( + String.format("Failed to download TL: %s", TL_URL_1), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[0].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[0].getCause() instanceof TslDownloadException); + Assert.assertEquals("Exception message", caughtException.getSuppressed()[0].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[0].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslParsingException); + Assert.assertEquals( + String.format("(Re)parsing needed for TL: %s", TL_URL_1), + caughtException.getSuppressed()[1].getMessage() + ); + + Assert.assertTrue(caughtException.getSuppressed()[2] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for TL: %s", TL_URL_1), + caughtException.getSuppressed()[2].getMessage() + ); + } + + @Test + public void testSingleLOTLInfoWithRequiredTLInfoWithParsingErrorAndValidationRefreshNeeded() { + TLInfo tlInfo = new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withErrorState(new ParsingCacheDTO(), "Exception message"), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_3 + ); + + TslRefreshException caughtException = testSingleLOTLInfoWithRequiredTLInfoThrowingException(tlInfo, TERRITORY_4); + + Assert.assertNull(caughtException.getCause()); + Assert.assertNotNull(caughtException.getSuppressed()); + Assert.assertEquals(2, caughtException.getSuppressed().length); + + Assert.assertTrue(caughtException.getSuppressed()[0] instanceof TslParsingException); + Assert.assertEquals( + String.format("Failed to parse TL: %s", TL_URL_3), + caughtException.getSuppressed()[0].getMessage() + ); + Assert.assertNotNull(caughtException.getSuppressed()[0].getCause()); + Assert.assertTrue(caughtException.getSuppressed()[0].getCause() instanceof TslParsingException); + Assert.assertEquals("Exception message", caughtException.getSuppressed()[0].getCause().getMessage()); + Assert.assertArrayEquals(new Throwable[0], caughtException.getSuppressed()[0].getSuppressed()); + + Assert.assertTrue(caughtException.getSuppressed()[1] instanceof TslValidationException); + Assert.assertEquals( + String.format("(Re)validation needed for TL: %s", TL_URL_3), + caughtException.getSuppressed()[1].getMessage() + ); + } + + private TslRefreshException testSingleLOTLInfoWithRequiredTLInfoThrowingException(TLInfo tlInfo, String requiredTerritory) { + Mockito.doReturn(Collections.singletonList(requiredTerritory)).when(configuration).getRequiredTerritories(); + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo("UNRELATED_TERRITORY_1", "http://unrelated.tl.1"), + tlInfo, + createValidTLInfo("UNRELATED_TERRITORY_1", "http://unrelated.tl.2") + )); + + TslRefreshException caughtException = testSingleLOTLInfoThrowingException(lotlInfo, TslRefreshException.class); + + Assert.assertEquals( + String.format("Failed to load trusted lists for required territories: %s", requiredTerritory), + caughtException.getMessage() + ); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verify(configuration).getTrustedTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + + return caughtException; + } + + @Test + public void testSingleLOTLInfoWithSingleTLInfoSucceeds() { + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Collections.singletonList( + createValidTLInfo(TERRITORY_2, TL_URL_1) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testSingleLOTLInfoWithMultipleTLInfosSucceeds() { + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + createValidTLInfo(TERRITORY_3, TL_URL_2) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testSingleLOTLInfoWithMultipleTLInfosAtLeastOneSucceeds() { + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + new TLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message"), + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_2 + ) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testMatchingRequiredTerritoriesWithoutTrustedTerritoriesSucceeds() { + Mockito.doReturn(Arrays.asList(TERRITORY_2, TERRITORY_3)).when(configuration).getRequiredTerritories(); + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + createValidTLInfo(TERRITORY_3, TL_URL_2) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verify(configuration).getTrustedTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testOnlyTLInfosWithMatchingRequiredTerritoriesSucceeds() { + Mockito.doReturn(Collections.singletonList(TERRITORY_2)).when(configuration).getRequiredTerritories(); + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + new TLInfo( + withErrorState(new DownloadCacheDTO(), "Exception message"), + withState(new ParsingCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + withState(new ValidationCacheDTO(), CacheStateEnum.REFRESH_NEEDED), + TL_URL_2 + ) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verify(configuration).getTrustedTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testMatchingRequiredTerritoriesAndMatchingTrustedTerritoriesSucceeds() { + Mockito.doReturn(Arrays.asList(TERRITORY_2, TERRITORY_3)).when(configuration).getRequiredTerritories(); + Mockito.doReturn(Arrays.asList(TERRITORY_2, TERRITORY_3)).when(configuration).getTrustedTerritories(); + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + createValidTLInfo(TERRITORY_3, TL_URL_2) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verify(configuration).getTrustedTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + @Test + public void testNonMatchingRequiredTerritoriesAndMatchingTrustedTerritoriesSucceeds() { + Mockito.doReturn(Collections.singletonList("NO")).when(configuration).getRequiredTerritories(); + Mockito.doReturn(Arrays.asList(TERRITORY_2, TERRITORY_3)).when(configuration).getTrustedTerritories(); + LOTLInfo lotlInfo = createValidLOTLInfo(TERRITORY_1, LOTL_URL_1); + lotlInfo.setTlInfos(Arrays.asList( + createValidTLInfo(TERRITORY_2, TL_URL_1), + createValidTLInfo(TERRITORY_3, TL_URL_2) + )); + + testSummaryWithValidLOTLInfos(Collections.singletonList(lotlInfo)); + + Mockito.verify(configuration).getRequiredTerritories(); + Mockito.verify(configuration).getTrustedTerritories(); + Mockito.verifyNoMoreInteractions(configuration); + } + + private void testSummaryWithValidLOTLInfos(List lotlInfos) { + TLValidationJobSummary summary = new TLValidationJobSummary(lotlInfos, null); + tslRefreshCallback.ensureTSLState(summary); + } + + private static LOTLInfo createValidLOTLInfo(String territory, String url) { + return new LOTLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), territory), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + url + ); + } + + private static TLInfo createValidTLInfo(String territory, String url) { + return new TLInfo( + withState(new DownloadCacheDTO(), CacheStateEnum.SYNCHRONIZED), + withSynchronizedState(new ParsingCacheDTO(), territory), + withSynchronizedState(new ValidationCacheDTO(), Indication.TOTAL_PASSED), + url + ); + } + + private static T withState(T cacheInfo, CacheStateEnum state) { + cacheInfo.setCacheState(state); + return cacheInfo; + } + + private static T withErrorState(T cacheInfo, String exceptionMessage) { + cacheInfo.setExceptionMessage(exceptionMessage); + return withState(cacheInfo, CacheStateEnum.ERROR); + } + + private static ParsingCacheDTO withSynchronizedState(ParsingCacheDTO cacheInfo, String territory) { + cacheInfo.setTerritory(territory); + return withState(cacheInfo, CacheStateEnum.SYNCHRONIZED); + } + + private static ValidationCacheDTO withSynchronizedState(ValidationCacheDTO cacheInfo, Indication indication, SubIndication subIndication) { + cacheInfo.setIndication(indication); + cacheInfo.setSubIndication(subIndication); + return withState(cacheInfo, CacheStateEnum.SYNCHRONIZED); + } + + private static ValidationCacheDTO withSynchronizedState(ValidationCacheDTO cacheInfo, Indication indication) { + return withSynchronizedState(cacheInfo, indication, null); + } + + private static List unexpectedCacheStates() { + return Stream.of(CacheStateEnum.values()) + .filter(state -> !CacheStateEnum.ERROR.equals(state)) + .filter(state -> !CacheStateEnum.REFRESH_NEEDED.equals(state)) + .filter(state -> !CacheStateEnum.SYNCHRONIZED.equals(state)) + .collect(Collectors.toList()); + } + + private static List nonValidIndications() { + return Stream.of(Indication.values()) + .filter(indication -> !Indication.TOTAL_PASSED.equals(indication)) + .collect(Collectors.toList()); + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactoryTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactoryTest.java deleted file mode 100644 index 7d2261f6b..000000000 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslDataLoaderFactoryTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.digidoc4j.impl.asic.tsl; - -import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; -import eu.europa.esig.dss.service.http.commons.FileCacheDataLoader; -import eu.europa.esig.dss.spi.client.http.DataLoader; -import org.digidoc4j.AbstractTest; -import org.digidoc4j.Configuration; -import org.digidoc4j.DataLoaderFactory; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.File; -import java.util.Arrays; - -public class TslDataLoaderFactoryTest extends AbstractTest { - - private static final File MOCK_FILE_CACHE_DIRECTORY = new File("/mock/file/cache/dir"); - - private static final int MOCK_TIMEOUT_CONNECTION = 273; - private static final int MOCK_TIMEOUT_SOCKET = 84; - - @Test - public void testDefaultFileCacheDataLoaderCreatedWhenNoCustomDataLoaderFactoryConfiguredAndTslLocationIsHttpUrl() { - configuration.setTslLocation("http://tsl.host:8080/path"); - configuration.setConnectionTimeout(MOCK_TIMEOUT_CONNECTION); - configuration.setSocketTimeout(MOCK_TIMEOUT_SOCKET); - - DataLoader dataLoader = new TslDataLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); - Assert.assertTrue("Data loader should be of type " + FileCacheDataLoader.class.getSimpleName(), dataLoader instanceof FileCacheDataLoader); - - DataLoader nestedDataLoader = ((FileCacheDataLoader) dataLoader).getDataLoader(); - Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); - Assert.assertEquals(MOCK_TIMEOUT_CONNECTION, ((CommonsDataLoader) nestedDataLoader).getTimeoutConnection()); - Assert.assertEquals(MOCK_TIMEOUT_SOCKET, ((CommonsDataLoader) nestedDataLoader).getTimeoutSocket()); - - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getProxyConfig()); - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLCipherSuites()); - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLProtocols()); - } - - @Test - public void testDefaultFileCacheDataLoaderWithProxyConfigCreatedWhenNoCustomDataLoaderFactoryConfiguredAndTslLocationIsHttpUrl() { - configuration.setTslLocation("http://tsl.host:8080/path"); - configuration.setHttpProxyHost("http://proxy.host"); - configuration.setHttpProxyPort(8080); - configuration.setHttpsProxyHost("https://proxy.host"); - configuration.setHttpsProxyPort(8443); - configuration.setHttpProxyUser("proxy-user"); - configuration.setHttpProxyPassword("proxy-password"); - - DataLoader dataLoader = new TslDataLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); - Assert.assertTrue("Data loader should be of type " + FileCacheDataLoader.class.getSimpleName(), dataLoader instanceof FileCacheDataLoader); - - DataLoader nestedDataLoader = ((FileCacheDataLoader) dataLoader).getDataLoader(); - Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); - - Assert.assertNotNull(((CommonsDataLoader) nestedDataLoader).getProxyConfig()); - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLCipherSuites()); - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLProtocols()); - } - - @Test - public void testDefaultFileCacheDataLoaderWithSslConfigCreatedWhenNoCustomDataLoaderFactoryConfiguredAndTslLocationIsHttpUrl() { - configuration.setTslLocation("http://tsl.host:8080/path"); - configuration.setSslTruststorePath("classpath:testFiles/truststores/empty-truststore.p12"); - configuration.setSslTruststorePassword("digidoc4j-password"); - configuration.setSslTruststoreType("PKCS12"); - configuration.setSupportedSslCipherSuites(Arrays.asList("supported_cipher_suite")); - configuration.setSupportedSslProtocols(Arrays.asList("supported_ssl_protocol")); - - DataLoader dataLoader = new TslDataLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); - Assert.assertTrue("Data loader should be of type " + FileCacheDataLoader.class.getSimpleName(), dataLoader instanceof FileCacheDataLoader); - - DataLoader nestedDataLoader = ((FileCacheDataLoader) dataLoader).getDataLoader(); - Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); - - Assert.assertNotNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLCipherSuites()); - Assert.assertNotNull(((CommonsDataLoader) nestedDataLoader).getSupportedSSLProtocols()); - Assert.assertNull(((CommonsDataLoader) nestedDataLoader).getProxyConfig()); - } - - @Test - public void testDefaultCommonsDataLoaderCreatedWhenNoCustomDataLoaderFactoryConfiguredAndTslLocationNotHttpUrl() { - configuration.setTslLocation("/not/http/url"); - - DataLoader dataLoader = new TslDataLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); - Assert.assertTrue("Data loader should be of type " + CommonsDataLoader.class.getSimpleName(), dataLoader instanceof CommonsDataLoader); - } - - @Test - public void testCustomDataLoaderCreatedWhenCustomDataLoaderFactoryConfigured() { - DataLoader mockDataLoader = Mockito.mock(DataLoader.class); - DataLoaderFactory mockDataLoaderFactory = Mockito.mock(DataLoaderFactory.class); - Mockito.doReturn(mockDataLoader).when(mockDataLoaderFactory).create(); - - configuration.setTslDataLoaderFactory(mockDataLoaderFactory); - DataLoader dataLoader = new TslDataLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); - Assert.assertSame(mockDataLoader, dataLoader); - - Mockito.verify(mockDataLoaderFactory, Mockito.times(1)).create(); - Mockito.verifyNoMoreInteractions(mockDataLoaderFactory, mockDataLoader); - } - - @Override - protected void before() { - configuration = Configuration.of(Configuration.Mode.TEST); - } - -} \ No newline at end of file diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactoryTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactoryTest.java new file mode 100644 index 000000000..cda24684e --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslFileLoaderFactoryTest.java @@ -0,0 +1,170 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.impl.asic.tsl; + +import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; +import eu.europa.esig.dss.service.http.commons.FileCacheDataLoader; +import eu.europa.esig.dss.spi.client.http.DSSFileLoader; +import eu.europa.esig.dss.spi.client.http.DataLoader; +import org.digidoc4j.AbstractTest; +import org.digidoc4j.Configuration; +import org.digidoc4j.DSSFileLoaderFactory; +import org.digidoc4j.DataLoaderFactory; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.File; +import java.util.Collections; + +public class TslFileLoaderFactoryTest extends AbstractTest { + + private static final File MOCK_FILE_CACHE_DIRECTORY = new File("/mock/file/cache/dir"); + + private static final int MOCK_TIMEOUT_CONNECTION = 273; + private static final int MOCK_TIMEOUT_SOCKET = 84; + + @Test + public void testDefaultFileCacheDataLoaderCreatedWhenNoCustomLoaderFactoriesConfigured() { + configuration.setConnectionTimeout(MOCK_TIMEOUT_CONNECTION); + configuration.setSocketTimeout(MOCK_TIMEOUT_SOCKET); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertTrue("File loader should be of type " + FileCacheDataLoader.class.getSimpleName(), fileLoader instanceof FileCacheDataLoader); + FileCacheDataLoader fileCacheDataLoader = (FileCacheDataLoader) fileLoader; + + DataLoader nestedDataLoader = fileCacheDataLoader.getDataLoader(); + Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); + CommonsDataLoader nestedCommonsDataLoader = (CommonsDataLoader) nestedDataLoader; + + Assert.assertEquals(MOCK_TIMEOUT_CONNECTION, nestedCommonsDataLoader.getTimeoutConnection()); + Assert.assertEquals(MOCK_TIMEOUT_SOCKET, nestedCommonsDataLoader.getTimeoutSocket()); + + Assert.assertNull(nestedCommonsDataLoader.getProxyConfig()); + Assert.assertNull(nestedCommonsDataLoader.getSupportedSSLCipherSuites()); + Assert.assertNull(nestedCommonsDataLoader.getSupportedSSLProtocols()); + } + + @Test + public void testDefaultFileCacheDataLoaderWithProxyConfigCreatedWhenNoCustomLoaderFactoriesConfigured() { + configuration.setHttpProxyHost("http://proxy.host"); + configuration.setHttpProxyPort(8080); + configuration.setHttpsProxyHost("https://proxy.host"); + configuration.setHttpsProxyPort(8443); + configuration.setHttpProxyUser("proxy-user"); + configuration.setHttpProxyPassword("proxy-password"); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertTrue("File loader should be of type " + FileCacheDataLoader.class.getSimpleName(), fileLoader instanceof FileCacheDataLoader); + FileCacheDataLoader fileCacheDataLoader = (FileCacheDataLoader) fileLoader; + + DataLoader nestedDataLoader = fileCacheDataLoader.getDataLoader(); + Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); + CommonsDataLoader nestedCommonsDataLoader = (CommonsDataLoader) nestedDataLoader; + + Assert.assertNotNull(nestedCommonsDataLoader.getProxyConfig()); + Assert.assertNull(nestedCommonsDataLoader.getSupportedSSLCipherSuites()); + Assert.assertNull(nestedCommonsDataLoader.getSupportedSSLProtocols()); + } + + @Test + public void testDefaultFileCacheDataLoaderWithSslConfigCreatedWhenNoCustomLoaderFactoriesConfigured() { + configuration.setLotlLocation("http://lotl.host:8080/path"); + configuration.setSslTruststorePath("classpath:testFiles/truststores/empty-truststore.p12"); + configuration.setSslTruststorePassword("digidoc4j-password"); + configuration.setSslTruststoreType("PKCS12"); + configuration.setSupportedSslCipherSuites(Collections.singletonList("supported_cipher_suite")); + configuration.setSupportedSslProtocols(Collections.singletonList("supported_ssl_protocol")); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertTrue("File loader should be of type " + FileCacheDataLoader.class.getSimpleName(), fileLoader instanceof FileCacheDataLoader); + FileCacheDataLoader fileCacheDataLoader = (FileCacheDataLoader) fileLoader; + + DataLoader nestedDataLoader = fileCacheDataLoader.getDataLoader(); + Assert.assertTrue("Nested data loader should be of type " + CommonsDataLoader.class.getSimpleName(), nestedDataLoader instanceof CommonsDataLoader); + CommonsDataLoader nestedCommonsDataLoader = (CommonsDataLoader) nestedDataLoader; + + Assert.assertNotNull(nestedCommonsDataLoader.getSupportedSSLCipherSuites()); + Assert.assertNotNull(nestedCommonsDataLoader.getSupportedSSLProtocols()); + Assert.assertNull(nestedCommonsDataLoader.getProxyConfig()); + } + + @Test + public void testCustomFileLoaderCreatedWhenCustomFileLoaderFactoryConfigured() { + DSSFileLoader mockFileLoader = Mockito.mock(DSSFileLoader.class); + DSSFileLoaderFactory mockFileLoaderFactory = Mockito.mock(DSSFileLoaderFactory.class); + Mockito.doReturn(mockFileLoader).when(mockFileLoaderFactory).create(); + configuration.setTslFileLoaderFactory(mockFileLoaderFactory); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertSame(mockFileLoader, fileLoader); + + Mockito.verify(mockFileLoaderFactory).create(); + Mockito.verifyNoMoreInteractions(mockFileLoaderFactory, mockFileLoader); + } + + @Test + public void testCustomFileLoaderCreatedWhenCustomFileLoaderFactoryAndCustomDataLoaderFactoryConfigured() { + DSSFileLoader mockFileLoader = Mockito.mock(DSSFileLoader.class); + DSSFileLoaderFactory mockFileLoaderFactory = Mockito.mock(DSSFileLoaderFactory.class); + Mockito.doReturn(mockFileLoader).when(mockFileLoaderFactory).create(); + configuration.setTslFileLoaderFactory(mockFileLoaderFactory); + + DataLoaderFactory mockDataLoaderFactory = Mockito.mock(DataLoaderFactory.class); + configuration.setTslDataLoaderFactory(mockDataLoaderFactory); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertSame(mockFileLoader, fileLoader); + + Mockito.verify(mockFileLoaderFactory).create(); + Mockito.verifyNoMoreInteractions(mockFileLoaderFactory, mockFileLoader, mockDataLoaderFactory); + } + + @Test + public void testCustomFileLoaderCreatedWhenCustomDataLoaderFactoryConfiguredWhichCreatesDataLoadersImplementingFileLoaderInterface() { + DataLoader mockDataAndFileLoader = Mockito.mock(DataLoaderWithFileLoaderInterface.class); + DataLoaderFactory mockDataLoaderFactory = Mockito.mock(DataLoaderFactory.class); + Mockito.doReturn(mockDataAndFileLoader).when(mockDataLoaderFactory).create(); + configuration.setTslDataLoaderFactory(mockDataLoaderFactory); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertSame(mockDataAndFileLoader, fileLoader); + + Mockito.verify(mockDataLoaderFactory).create(); + Mockito.verifyNoMoreInteractions(mockDataAndFileLoader, mockDataAndFileLoader); + } + + @Test + public void testFileCacheDataLoaderWrappingCustomDataLoaderCreatedWhenCustomDataLoaderFactoryConfigured() { + DataLoader mockDataLoader = Mockito.mock(DataLoader.class); + DataLoaderFactory mockDataLoaderFactory = Mockito.mock(DataLoaderFactory.class); + Mockito.doReturn(mockDataLoader).when(mockDataLoaderFactory).create(); + configuration.setTslDataLoaderFactory(mockDataLoaderFactory); + + DSSFileLoader fileLoader = new TslFileLoaderFactory(configuration, MOCK_FILE_CACHE_DIRECTORY).create(); + Assert.assertTrue("File loader should be of type " + FileCacheDataLoader.class.getSimpleName(), fileLoader instanceof FileCacheDataLoader); + FileCacheDataLoader fileCacheDataLoader = (FileCacheDataLoader) fileLoader; + + DataLoader nestedDataLoader = fileCacheDataLoader.getDataLoader(); + Assert.assertSame(mockDataLoader, nestedDataLoader); + + Mockito.verify(mockDataLoaderFactory).create(); + Mockito.verifyNoMoreInteractions(mockDataLoaderFactory, mockDataLoader); + } + + @Override + protected void before() { + configuration = Configuration.of(Configuration.Mode.TEST); + } + + interface DataLoaderWithFileLoaderInterface extends DataLoader, DSSFileLoader {} + +} \ No newline at end of file diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslRefreshCallbackInteractionTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslRefreshCallbackInteractionTest.java new file mode 100644 index 000000000..2067db0ee --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/asic/tsl/TslRefreshCallbackInteractionTest.java @@ -0,0 +1,189 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.impl.asic.tsl; + +import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; +import org.digidoc4j.AbstractTest; +import org.digidoc4j.Container; +import org.digidoc4j.ContainerOpener; +import org.digidoc4j.ContainerValidationResult; +import org.digidoc4j.TSLRefreshCallback; +import org.digidoc4j.exceptions.TechnicalException; +import org.digidoc4j.exceptions.TslRefreshException; +import org.digidoc4j.impl.ConfigurationSingeltonHolder; +import org.digidoc4j.test.TestAssert; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TslRefreshCallbackInteractionTest extends AbstractTest { + + @Mock + private TSLRefreshCallback tslRefreshCallback; + + @Override + protected void before() { + configuration = ConfigurationSingeltonHolder.getInstance(); + configuration.setTslRefreshCallback(tslRefreshCallback); + } + + @Test + public void testCallbackReturnsTrueOnManualRefresh() { + mockEnsureTSLState(true); + configuration.getTSL().refresh(); + configuration.getTSL().refresh(); + + verifyCallbackCalled(2); + } + + @Test + public void testCallbackReturnsFalseOnManualRefresh() { + mockEnsureTSLState(false); + configuration.getTSL().refresh(); + + mockEnsureTSLState(true); + configuration.getTSL().refresh(); + + verifyCallbackCalled(2); + } + + @Test + public void testCallbackThrowsExceptionOnManualRefresh() { + TslRefreshException exceptionToThrow = new TslRefreshException("Exception message"); + mockEnsureTSLState(exceptionToThrow); + + TslRefreshException caughtException = assertThrows( + TslRefreshException.class, + () -> configuration.getTSL().refresh() + ); + + mockEnsureTSLState(true); + configuration.getTSL().refresh(); + + Assert.assertEquals("Exception message", caughtException.getMessage()); + verifyCallbackCalled(2); + } + + @Test + public void testCallbackReturnsTrueOnOpeningAndValidatingContainer() { + mockEnsureTSLState(true); + + Container container = ContainerOpener.open(ASICE_WITH_TS_SIG); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); + + verifyCallbackCalled(1); + } + + @Test + public void testCallbackReturnsFalseOnOpeningAndValidatingContainer() { + mockEnsureTSLState(false); + + Container container = ContainerOpener.open(ASICE_WITH_TS_SIG); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); + + Mockito.verify(tslRefreshCallback, Mockito.atLeastOnce()).ensureTSLState(Mockito.any(TLValidationJobSummary.class)); + Mockito.verifyNoMoreInteractions(tslRefreshCallback); + } + + @Test + public void testCallbackThrowsExceptionOnOpeningContainer() { + TslRefreshException exceptionToThrow = new TslRefreshException("Exception message"); + mockEnsureTSLState(exceptionToThrow); + + TslRefreshException caughtException = assertThrows( + TslRefreshException.class, + () -> ContainerOpener.open(ASICE_WITH_TS_SIG) + ); + + Assert.assertEquals("Exception message", caughtException.getMessage()); + verifyCallbackCalled(1); + } + + @Test + public void testCallbackThrowsExceptionOnValidatingContainer() { + mockEnsureTSLState(false); + Container container = ContainerOpener.open(ASICE_WITH_TS_SIG); + Mockito.reset(tslRefreshCallback); + + TslRefreshException exceptionToThrow = new TslRefreshException("Exception message"); + mockEnsureTSLState(exceptionToThrow); + + TechnicalException caughtException = assertThrows( + TechnicalException.class, + () -> container.validate() + ); + + Assert.assertEquals("Error validating signatures on multiple threads: Exception message", caughtException.getMessage()); + verifyCallbackCalled(1); + } + + @Test + public void testCallbackReturnsTrueOnCreatingAndSigningContainer() { + mockEnsureTSLState(true); + + Container container = createContainerBy(Container.DocumentType.ASICE, + createTextDataFile("test.txt", "Test") + ); + createSignatureBy(container, pkcs12Esteid2018SignatureToken); + + verifyCallbackCalled(1); + } + + @Test + public void testCallbackReturnsFalseOnCreatingAndSigningContainer() { + mockEnsureTSLState(false); + + Container container = createContainerBy(Container.DocumentType.ASICE, + createTextDataFile("test.txt", "Test") + ); + createSignatureBy(container, pkcs12Esteid2018SignatureToken); + + Mockito.verify(tslRefreshCallback, Mockito.atLeastOnce()).ensureTSLState(Mockito.any(TLValidationJobSummary.class)); + Mockito.verifyNoMoreInteractions(tslRefreshCallback); + } + + @Test + public void testCallbackThrowsExceptionOnSigningContainer() { + TslRefreshException exceptionToThrow = new TslRefreshException("Exception message"); + mockEnsureTSLState(exceptionToThrow); + + Container container = createContainerBy(Container.DocumentType.ASICE, + createTextDataFile("test.txt", "Test") + ); + TslRefreshException caughtException = assertThrows( + TslRefreshException.class, + () -> createSignatureBy(container, pkcs12Esteid2018SignatureToken) + ); + + Assert.assertEquals("Exception message", caughtException.getMessage()); + verifyCallbackCalled(1); + } + + private void mockEnsureTSLState(boolean toBeReturned) { + Mockito.doReturn(toBeReturned).when(tslRefreshCallback).ensureTSLState(Mockito.any(TLValidationJobSummary.class)); + } + + private void mockEnsureTSLState(Throwable toBeThrown) { + Mockito.doThrow(toBeThrown).when(tslRefreshCallback).ensureTSLState(Mockito.any(TLValidationJobSummary.class)); + } + + private void verifyCallbackCalled(int wantedNumberOfInvocations) { + Mockito.verify(tslRefreshCallback, Mockito.times(wantedNumberOfInvocations)).ensureTSLState(Mockito.any(TLValidationJobSummary.class)); + Mockito.verifyNoMoreInteractions(tslRefreshCallback); + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocContainerTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocContainerTest.java index 8c98738fd..6d95cd8a3 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocContainerTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocContainerTest.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc; @@ -38,7 +38,6 @@ import org.digidoc4j.exceptions.DuplicateDataFileException; import org.digidoc4j.exceptions.DuplicateSignatureFilesException; import org.digidoc4j.exceptions.IllegalSignatureProfileException; -import org.digidoc4j.exceptions.InvalidSignatureException; import org.digidoc4j.exceptions.TechnicalException; import org.digidoc4j.impl.asic.AsicSignature; import org.digidoc4j.impl.asic.asice.AsicESignature; @@ -57,7 +56,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -69,51 +67,51 @@ public class BDocContainerTest extends AbstractTest { @Test - public void testSetDigestAlgorithmToSHA256() throws Exception { + public void testSetDigestAlgorithmToSHA256() { AsicESignature signature = this.createSignatureBy(DigestAlgorithm.SHA256, pkcs12SignatureToken); Assert.assertEquals("http://www.w3.org/2001/04/xmlenc#sha256", signature.getSignatureDigestAlgorithm().getUri()); } @Test - public void testSetDigestAlgorithmToSHA1() throws Exception { + public void testSetDigestAlgorithmToSHA1() { AsicESignature signature = this.createSignatureBy(DigestAlgorithm.SHA1, pkcs12SignatureToken); Assert.assertEquals("http://www.w3.org/2000/09/xmldsig#sha1", signature.getSignatureDigestAlgorithm().getUri()); } @Test - public void testSetDigestAlgorithmToSHA224() throws Exception { + public void testSetDigestAlgorithmToSHA224() { AsicESignature signature = this.createSignatureBy(DigestAlgorithm.SHA224, pkcs12SignatureToken); Assert.assertEquals("http://www.w3.org/2001/04/xmldsig-more#sha224", signature.getSignatureDigestAlgorithm().getUri()); } @Test - public void testDefaultDigestAlgorithm() throws Exception { + public void testDefaultDigestAlgorithm() { AsicESignature signature = this.createSignatureBy(Container.DocumentType.BDOC, pkcs12SignatureToken); Assert.assertEquals("http://www.w3.org/2001/04/xmlenc#sha256", signature.getSignatureDigestAlgorithm().getUri()); } @Test - public void testOpenBDocDocument() throws Exception { + public void testOpenBDocDocument() { ContainerOpener.open("src/test/resources/testFiles/valid-containers/one_signature.bdoc").validate(); } @Test - public void testOpenBDocDocumentWithTwoSignatures() throws Exception { + public void testOpenBDocDocumentWithTwoSignatures() { ContainerOpener.open("src/test/resources/testFiles/invalid-containers/two_signatures.bdoc").validate(); } @Test(expected = DigiDoc4JException.class) - public void testAddDataFileWhenFileDoesNotExist() throws Exception { + public void testAddDataFileWhenFileDoesNotExist() { this.createNonEmptyContainerBy(Paths.get("notExisting.txt"), "text/plain"); } @Test(expected = DigiDoc4JException.class) - public void testAddDataFileFromInputStreamWithByteArrayConversionFailure() throws Exception { + public void testAddDataFileFromInputStreamWithByteArrayConversionFailure() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile(new InputStream() { @Override - public int read() throws IOException { + public int read() { return 0; } @@ -130,28 +128,23 @@ public void close() throws IOException { }, "test.txt", "text/plain"); } - @Test(expected = InvalidSignatureException.class) - public void testAddRawSignature() throws Exception { - this.createEmptyContainerBy(Container.DocumentType.BDOC, BDocContainer.class).addRawSignature(new byte[]{}); - } - @Test public void testAddUnknownFileTypeKeepsMimeType() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.unknown_type"), "text/test_type"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals("text/test_type", container.getDataFiles().get(0).getMediaType()); } @Test - public void testSaveBDocDocumentWithTwoSignatures() throws Exception { + public void testSaveBDocDocumentWithTwoSignatures() { Container container = this.createNonEmptyContainerBy(Container.DocumentType.BDOC); this.createSignatureBy(container, pkcs12SignatureToken); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Assert.assertEquals(2, container.getSignatures().size()); Assert.assertEquals("6ec00b8b8c54c4f76082bd843e3a1526", container.getSignatures().get(0).getSigningCertificate().getSerial()); @@ -166,7 +159,7 @@ public void testSaveBDocDocumentWithTwoSignatures() throws Exception { } @Test - public void saveContainerWithoutSignatures() throws Exception { + public void saveContainerWithoutSignatures() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); String file = this.getFileBy("bdoc"); container.saveAsFile(file); @@ -176,7 +169,7 @@ public void saveContainerWithoutSignatures() throws Exception { } @Test - public void openContainer_withoutSignatures_andAddMoreDataFiles() throws Exception { + public void openContainer_withoutSignatures_andAddMoreDataFiles() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/container_without_signatures.bdoc"); Assert.assertEquals(1, container.getDataFiles().size()); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); @@ -190,21 +183,23 @@ public void openContainer_withoutSignatures_andAddMoreDataFiles() throws Excepti @Test public void openContainerFromStream_withoutSignatures_andAddMoreDataFiles() throws Exception { + String file = this.getFileBy("bdoc"); try (FileInputStream stream = new FileInputStream("src/test/resources/testFiles/valid-containers/container_without_signatures.bdoc")) { Container container = ContainerOpener.open(stream, false); Assert.assertEquals(1, container.getDataFiles().size()); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); container.addDataFile("src/test/resources/testFiles/helper-files/word_file.docx", "application/octet-stream"); Assert.assertEquals(3, container.getDataFiles().size()); - String file = this.getFileBy("bdoc"); container.saveAsFile(file); - container = ContainerOpener.open(new FileInputStream(file), false); + } + try (FileInputStream stream = new FileInputStream(file)) { + Container container = ContainerOpener.open(stream, false); Assert.assertEquals(3, container.getDataFiles().size()); } } @Test - public void openContainerWithoutSignatures_addDataFileAndSignContainer() throws Exception { + public void openContainerWithoutSignatures_addDataFileAndSignContainer() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/container_without_signatures.bdoc"); Assert.assertEquals(1, container.getDataFiles().size()); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); @@ -222,7 +217,7 @@ public void testGetDefaultSignatureParameters() { Container container = this.createNonEmptyContainerBy(Container.DocumentType.BDOC); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Signature signature = container.getSignatures().get(0); Assert.assertEquals("", signature.getPostalCode()); @@ -248,7 +243,7 @@ public void notThrowingNPEWhenDOCXFileIsAddedToContainer() { } @Test - public void signPdfDataFile() throws Exception { + public void signPdfDataFile() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/special-char-files/dds_acrobat.pdf"), "application/pdf"); this.createSignatureBy(container, pkcs12SignatureToken); Assert.assertEquals(1, container.getDataFiles().size()); @@ -261,11 +256,11 @@ public void signPdfDataFile() throws Exception { } @Test - public void testAddSignaturesToExistingDocument() throws Exception { + public void testAddSignaturesToExistingDocument() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Assert.assertEquals(3, container.getSignatures().size()); Assert.assertEquals("6ec00b8b8c54c4f76082bd843e3a1526", container.getSignatures().get(2).getSigningCertificate().getSerial()); @@ -277,20 +272,20 @@ public void testAddSignaturesToExistingDocument() throws Exception { } @Test - public void testRemoveSignatureWhenOneSignatureExists() throws Exception { + public void testRemoveSignatureWhenOneSignatureExists() { Container container = this.createNonEmptyContainerBy(Container.DocumentType.BDOC); this.createSignatureBy(container, pkcs12SignatureToken); Signature signature = container.getSignatures().get(0); container.removeSignature(signature); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Assert.assertEquals(0, container.getSignatures().size()); container = ContainerOpener.open(file); Assert.assertEquals(0, container.getSignatures().size()); } @Test - public void testAddFilesWithSpecialCharactersIntoContainer() throws Exception { + public void testAddFilesWithSpecialCharactersIntoContainer() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/special-char-files/dds_dds_JÜRIÖÖ € žŠ päev.txt"), "text/plain"); //container.addDataFile("src/test/resources/testFiles/special-char-files/dds_колючей стерне.docx", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); @@ -299,35 +294,35 @@ public void testAddFilesWithSpecialCharactersIntoContainer() throws Exception { } @Test - public void testRemoveSignatureWhenTwoSignaturesExist() throws Exception { + public void testRemoveSignatureWhenTwoSignaturesExist() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); Assert.assertEquals(2, container.getSignatures().size()); Signature signature = container.getSignatures().get(0); container.removeSignature(signature); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals(1, container.getSignatures().size()); } @Test - public void testRemoveSignatureWhenThreeSignaturesExist() throws Exception { + public void testRemoveSignatureWhenThreeSignaturesExist() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals(3, container.getSignatures().size()); Signature signature = container.getSignatures().get(1); container.removeSignature(signature); file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals(2, container.getSignatures().size()); } @Test - public void removeNewlyAddedSignatureFromExistingContainer() throws Exception { + public void removeNewlyAddedSignatureFromExistingContainer() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); Assert.assertEquals(2, container.getSignatures().size()); this.createSignatureBy(container, pkcs12SignatureToken); @@ -337,7 +332,7 @@ public void removeNewlyAddedSignatureFromExistingContainer() throws Exception { } @Test - public void removeSignatureFromExistingAsicEContainer() throws Exception { + public void removeSignatureFromExistingAsicEContainer() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); Assert.assertEquals(2, container.getSignatures().size()); container.removeSignature(container.getSignatures().get(0)); @@ -369,43 +364,43 @@ public void removingNullSignatureDoesNothing() { } @Test - public void testSaveDocumentWithOneSignature() throws Exception { - Assert.assertTrue(Files.exists(Paths.get(this.createSignedContainerBy("bdoc")))); + public void testSaveDocumentWithOneSignature() { + Assert.assertTrue(Files.exists(Paths.get(this.createSignedContainerBy(Container.DocumentType.BDOC, "bdoc")))); } @Test(expected = DigiDoc4JException.class) - public void testRemoveDataFileAfterSigning() throws Exception { - Container container = ContainerOpener.open(this.createSignedContainerBy("bdoc")); + public void testRemoveDataFileAfterSigning() { + Container container = ContainerOpener.open(this.createSignedContainerBy(Container.DocumentType.BDOC, "bdoc")); Assert.assertEquals("test.txt", container.getDataFiles().get(0).getName()); Assert.assertEquals(1, container.getDataFiles().size()); - container.removeDataFile("test.txt"); + container.removeDataFile(container.getDataFiles().get(0)); Assert.assertEquals(0, container.getDataFiles().size()); } @Test - public void testRemoveDataFile() throws Exception { + public void testRemoveDataFile() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); Assert.assertEquals("test.txt", container.getDataFiles().get(0).getName()); Assert.assertEquals(1, container.getDataFiles().size()); - container.removeDataFile("test.txt"); + container.removeDataFile(container.getDataFiles().get(0)); Assert.assertEquals(0, container.getDataFiles().size()); } @Test(expected = DigiDoc4JException.class) - public void testAddDataFileAfterSigning() throws Exception { - Container container = ContainerOpener.open(this.createSignedContainerBy("bdoc")); + public void testAddDataFileAfterSigning() { + Container container = ContainerOpener.open(this.createSignedContainerBy(Container.DocumentType.BDOC, "bdoc")); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); } @Test(expected = DigiDoc4JException.class) - public void testRemovingNonExistingFile() throws Exception { + public void testRemovingNonExistingFile() { Container container = this.createNonEmptyContainer(); - container.removeDataFile("test1.txt"); + container.removeDataFile(new DataFile(new byte[1], "test1.txt", "application/octet-stream")); } @Test(expected = DuplicateDataFileException.class) - public void testAddingSameFileSeveralTimes() throws Exception { + public void testAddingSameFileSeveralTimes() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); } @@ -426,14 +421,14 @@ public void testAddingDifferentPreCreatedFiles() { } @Test(expected = DuplicateDataFileException.class) - public void testAddingSameFileSeveralTimesViaInputStream() throws Exception { + public void testAddingSameFileSeveralTimesViaInputStream() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile(new ByteArrayInputStream("test".getBytes()), "src/test/resources/testFiles/helper-files/test.txt", "text/plain"); container.addDataFile(new ByteArrayInputStream("test".getBytes()), "src/test/resources/testFiles/helper-files/test.txt", "text/plain"); } @Test - public void testAddDateFileViaInputStream() throws Exception { + public void testAddDateFileViaInputStream() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile(new ByteArrayInputStream("test".getBytes()), "src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); @@ -441,26 +436,26 @@ public void testAddDateFileViaInputStream() throws Exception { } @Test(expected = DuplicateDataFileException.class) - public void testAddingSameFileInDifferentContainerSeveralTimes() throws Exception { + public void testAddingSameFileInDifferentContainerSeveralTimes() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); - container.save(this.getFileBy("bdoc")); + container.saveAsFile(this.getFileBy("bdoc")); } @Test(expected = DigiDoc4JException.class) - public void testAddingNotExistingFile() throws Exception { + public void testAddingNotExistingFile() { this.createNonEmptyContainerBy(Paths.get("notExistingFile.txt"), "text/plain"); } @Test - public void testAddFileAsStream() throws Exception { + public void testAddFileAsStream() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); ByteArrayInputStream stream = new ByteArrayInputStream("tere, tere".getBytes()); container.addDataFile(stream, "test1.txt", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); Container containerToTest = ContainerOpener.open(file); Assert.assertEquals("test1.txt", containerToTest.getDataFiles().get(0).getName()); } @@ -479,9 +474,10 @@ public void setsSignatureId() throws Exception { container = ContainerOpener.open(file); Assert.assertEquals("SIGNATURE-1", container.getSignatures().get(0).getId()); Assert.assertEquals("SIGNATURE-2", container.getSignatures().get(1).getId()); - ZipFile zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } } @Test @@ -490,23 +486,24 @@ public void setsDefaultSignatureId() throws Exception { this.createSignatureBy(container, pkcs12SignatureToken); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); String signature1Id = container.getSignatures().get(0).getId(); String signature2Id = container.getSignatures().get(1).getId(); Assert.assertFalse(StringUtils.equals(signature1Id, signature2Id)); Assert.assertTrue(signature1Id.startsWith("id-")); Assert.assertTrue(signature2Id.startsWith("id-")); - ZipFile zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } } @Test public void getDataFileByIndex() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); - Assert.assertEquals("test.txt", container.getDataFile(0).getName()); + Assert.assertEquals("test.txt", container.getDataFiles().get(0).getName()); } @Test(expected = DigiDoc4JException.class) @@ -516,16 +513,17 @@ public void openNonExistingFileThrowsError() { @Test(expected = DigiDoc4JException.class) public void openClosedStreamThrowsException() throws IOException { - FileInputStream stream = new FileInputStream(new File("src/test/resources/testFiles/helper-files/test.txt")); - stream.close(); - ContainerOpener.open(stream, false); + try (FileInputStream stream = new FileInputStream("src/test/resources/testFiles/helper-files/test.txt")) { + stream.close(); + ContainerOpener.open(stream, false); + } } @Test - public void testLargeFileSigning() throws Exception { + public void testLargeFileSigning() { BDocContainer container = (BDocContainer) ContainerBuilder.aContainer(Container.DocumentType.BDOC) .withConfiguration(new Configuration(Configuration.Mode.TEST)).build(); - container.getConfiguration().enableBigFilesSupport(10); + container.getConfiguration().setMaxFileSizeCachedInMemoryInMB(10); container.addDataFile(this.createNonEmptyLargeContainer(container.getConfiguration().getMaxDataFileCachedInBytes() + 100), "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); } @@ -534,12 +532,12 @@ public void testLargeFileSigning() throws Exception { public void openLargeFileFromStream() throws IOException { BDocContainer container = (BDocContainer) ContainerBuilder.aContainer(Container.DocumentType.BDOC). withConfiguration(new Configuration(Configuration.Mode.TEST)).build(); - container.getConfiguration().enableBigFilesSupport(0); + container.getConfiguration().setMaxFileSizeCachedInMemoryInMB(0); String file = this.createNonEmptyLargeContainer(container.getConfiguration().getMaxDataFileCachedInBytes() + 100); container.addDataFile(file, "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); - container.save(file); - try (FileInputStream stream = new FileInputStream(new File(file))) { + container.saveAsFile(file); + try (FileInputStream stream = new FileInputStream(file)) { ContainerOpener.open(stream, true); } Assert.assertEquals(1, container.getSignatures().size()); @@ -548,13 +546,13 @@ public void openLargeFileFromStream() throws IOException { @Test public void openAddFileFromStream() throws IOException { BDocContainer container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.getConfiguration().enableBigFilesSupport(0); + container.getConfiguration().setMaxFileSizeCachedInMemoryInMB(0); String file = this.createNonEmptyLargeContainer(container.getConfiguration().getMaxDataFileCachedInBytes() + 100); - try (FileInputStream stream = new FileInputStream(new File(file))) { + try (FileInputStream stream = new FileInputStream(file)) { container.addDataFile(stream, "fileName", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); - container.save(file); - FileInputStream stream2 = new FileInputStream(new File(file)); + container.saveAsFile(file); + FileInputStream stream2 = new FileInputStream(file); ContainerOpener.open(stream2, true); IOUtils.closeQuietly(stream2); } @@ -562,13 +560,13 @@ public void openAddFileFromStream() throws IOException { } @Test - public void testGetDocumentType() throws Exception { - Container container = ContainerOpener.open(this.createSignedContainerBy("bdoc")); - Assert.assertEquals(Container.DocumentType.BDOC, container.getDocumentType()); + public void testGetDocumentType() { + Container container = ContainerOpener.open(this.createSignedContainerBy(Container.DocumentType.BDOC, "bdoc")); + Assert.assertEquals(Constant.BDOC_CONTAINER_TYPE, container.getType()); } @Test - public void testAddTwoFilesAsStream() throws Exception { + public void testAddTwoFilesAsStream() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); ByteArrayInputStream stream = new ByteArrayInputStream("tere, tere".getBytes()); stream.mark(Integer.MAX_VALUE); @@ -578,38 +576,38 @@ public void testAddTwoFilesAsStream() throws Exception { } @Test - public void testAddTwoFilesAsFileWithoutOCSP() throws Exception { + public void testAddTwoFilesAsFileWithoutOCSP() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); this.createSignatureBy(container, SignatureProfile.B_BES, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals(2, container.getDataFiles().size()); } @Test - public void testGetFileNameAndID() throws Exception { + public void testGetFileNameAndID() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); - Assert.assertEquals("test.txt", container.getDataFile(0).getName()); - Assert.assertEquals("test.xml", container.getDataFile(1).getName()); - Assert.assertEquals("test.txt", container.getDataFile(0).getId()); - Assert.assertEquals("test.xml", container.getDataFile(1).getId()); + Assert.assertEquals("test.txt", container.getDataFiles().get(0).getName()); + Assert.assertEquals("test.xml", container.getDataFiles().get(1).getName()); + Assert.assertEquals("test.txt", container.getDataFiles().get(0).getId()); + Assert.assertEquals("test.xml", container.getDataFiles().get(1).getId()); } @Test - public void testAddTwoFilesAsFileWithOCSP() throws Exception { + public void testAddTwoFilesAsFileWithOCSP() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); container.addDataFile("src/test/resources/testFiles/helper-files/test.xml", "text/xml"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); Assert.assertEquals(2, container.getDataFiles().size()); } @@ -620,8 +618,9 @@ public void saveToStream() throws Exception { container.addDataFile(new ByteArrayInputStream(new byte[]{0x42}), "test_bytes.txt", "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); File expectedContainerAsFile = new File(this.getFileBy("bdoc")); - OutputStream out = new FileOutputStream(expectedContainerAsFile); - container.save(out); + try (OutputStream out = Files.newOutputStream(expectedContainerAsFile.toPath())) { + container.save(out); + } Assert.assertTrue(Files.exists(expectedContainerAsFile.toPath())); Container containerToTest = ContainerOpener.open(expectedContainerAsFile.getAbsolutePath()); Assert.assertArrayEquals(new byte[]{0x42}, containerToTest.getDataFiles().get(0).getBytes()); @@ -646,9 +645,10 @@ public void saveToStreamThrowsException() throws IOException { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); this.createSignatureBy(container, pkcs12SignatureToken); File expectedContainerAsFile = new File(this.getFileBy("bdoc")); - OutputStream out = new FileOutputStream(expectedContainerAsFile); - out.close(); - container.save(out); + try (OutputStream out = Files.newOutputStream(expectedContainerAsFile.toPath())) { + out.close(); + container.save(out); + } } @Test @@ -660,16 +660,17 @@ public void saveExistingContainer() throws Exception { Assert.assertTrue(savedContainer.validate().isValid()); Assert.assertEquals(1, savedContainer.getDataFiles().size()); Assert.assertEquals(2, savedContainer.getSignatures().size()); - ZipFile zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("mimetype")); - Assert.assertNotNull(zip.getEntry("test.txt")); - Assert.assertNotNull(zip.getEntry("META-INF/manifest.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("mimetype")); + Assert.assertNotNull(zip.getEntry("test.txt")); + Assert.assertNotNull(zip.getEntry("META-INF/manifest.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } } @Test - public void containerIsLT() throws Exception { + public void containerIsLT() { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt"), "text/plain"); this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); @@ -680,7 +681,7 @@ public void containerIsLT() throws Exception { } @Test(expected = DigiDoc4JException.class) - public void signWithoutDataFile() throws Exception { + public void signWithoutDataFile() { this.createSignatureBy(this.createEmptyContainerBy(Container.DocumentType.BDOC, Container.class), pkcs12SignatureToken); } @@ -690,17 +691,11 @@ public void nonStandardMimeType() { container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/newtype"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); container = ContainerOpener.open(file); SignatureValidationResult result = container.validate(); Assert.assertEquals(0, result.getErrors().size()); - Assert.assertEquals("text/newtype", container.getDataFile(0).getMediaType()); - } - - @Test - public void getVersion() { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - Assert.assertEquals("", container.getVersion()); + Assert.assertEquals("text/newtype", container.getDataFiles().get(0).getMediaType()); } @Test @@ -760,7 +755,7 @@ public void twoStepSigningVerifySignatureParameters() { } @Test - public void testContainerCreationAsTSA() throws Exception { + public void testContainerCreationAsTSA() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, SignatureProfile.LTA, pkcs12SignatureToken); @@ -768,7 +763,7 @@ public void testContainerCreationAsTSA() throws Exception { } @Test - public void testBDocTM() throws Exception { + public void testBDocTM() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, SignatureProfile.LT_TM, pkcs12SignatureToken); @@ -776,7 +771,7 @@ public void testBDocTM() throws Exception { } @Test - public void testBDocTS() throws Exception { + public void testBDocTS() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); @@ -784,7 +779,7 @@ public void testBDocTS() throws Exception { } @Test - public void containerWithBESProfileHasNoValidationErrors() throws Exception { + public void containerWithBESProfileHasNoValidationErrors() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); this.createSignatureBy(container, SignatureProfile.B_BES, pkcs12SignatureToken); @@ -794,7 +789,7 @@ public void containerWithBESProfileHasNoValidationErrors() throws Exception { } @Test - public void signWithECCCertificate() throws Exception { + public void signWithECCCertificate() { Container container = this.createNonEmptyContainerBy(Container.DocumentType.BDOC); Signature signature = SignatureBuilder.aSignature(container). withSignatureToken(new PKCS12SignatureToken("src/test/resources/testFiles/p12/MadDogOY.p12", "test".toCharArray())). @@ -809,18 +804,19 @@ public void zipFileComment() throws Exception { Container container = this.createNonEmptyContainerBy(Paths.get("src/test/resources/testFiles/helper-files/test.txt")); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); - container.save(file); + container.saveAsFile(file); String expectedComment = Constant.USER_AGENT_STRING; - ZipFile zipFile = new ZipFile(file); - Assert.assertEquals(expectedComment, zipFile.getEntry("mimetype").getComment()); - Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/manifest.xml").getComment()); - Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/manifest.xml").getComment()); - Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/signatures0.xml").getComment()); - Assert.assertEquals(expectedComment, zipFile.getEntry("test.txt").getComment()); + try (ZipFile zipFile = new ZipFile(file)) { + Assert.assertEquals(expectedComment, zipFile.getEntry("mimetype").getComment()); + Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/manifest.xml").getComment()); + Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/manifest.xml").getComment()); + Assert.assertEquals(expectedComment, zipFile.getEntry("META-INF/signatures0.xml").getComment()); + Assert.assertEquals(expectedComment, zipFile.getEntry("test.txt").getComment()); + } } @Test - public void signingMoreThanTwoFiles() throws Exception { + public void signingMoreThanTwoFiles() { Container container = this.createNonEmptyContainerBy(Container.DocumentType.BDOC, Paths.get("src/test/resources/testFiles/special-char-files/dds_dds_JÜRIÖÖ € žŠ päev.txt"), "text/plain"); @@ -843,44 +839,49 @@ public void signatureFileNamesShouldBeInSequence() throws Exception { this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); container.saveAsFile(file); - ZipFile zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + } } @Test public void whenSigningExistingContainer_withTwoSignatures_shouldCreateSignatureFileName_signatures2() throws Exception { - ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc")) { + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/asics_testing_two_signatures.bdoc"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); container.saveAsFile(file); - zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + } } @Test public void whenSigningExistingContainer_with_signatures1_xml_shouldCreateSignatureFileName_signatures2() throws Exception { - ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/DigiDocService_spec_est.pdf-TM-j.bdoc"); - Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/DigiDocService_spec_est.pdf-TM-j.bdoc")) { + Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/DigiDocService_spec_est.pdf-TM-j.bdoc"); this.createSignatureBy(container, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); container.saveAsFile(file); - zip = new ZipFile(file); - Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures2.xml")); + } } @Test(expected = TechnicalException.class) - public void addSignatureWithDuplicateSignatureId_throwsException() throws Exception { + public void addSignatureWithDuplicateSignatureId_throwsException() { Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/test.asice"); Signature signature = SignatureBuilder.aSignature(container). withSignatureToken(pkcs12SignatureToken).withSignatureId("S0").invokeSigning(); @@ -911,19 +912,21 @@ public void addBEpesSignatureToAsicEContainer_throwsException() { @Test public void whenSigningContainer_withSignatureNameContainingNonNumericCharacters_shouldCreateSignatureFileName_inSequence() throws Exception { - ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/valid-bdoc-ts-signature-file-name-with-non-numeric-characters.asice"); - Assert.assertNotNull(zip.getEntry("META-INF/l77Tsignaturesn00B.xml")); - Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile("src/test/resources/testFiles/valid-containers/valid-bdoc-ts-signature-file-name-with-non-numeric-characters.asice")) { + Assert.assertNotNull(zip.getEntry("META-INF/l77Tsignaturesn00B.xml")); + Assert.assertNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNull(zip.getEntry("META-INF/signatures1.xml")); + } Container container = ContainerOpener.open("src/test/resources/testFiles/valid-containers/valid-bdoc-ts-signature-file-name-with-non-numeric-characters.asice"); this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); String file = this.getFileBy("bdoc"); container.saveAsFile(file); - zip = new ZipFile(file); - Assert.assertNotNull(zip.getEntry("META-INF/l77Tsignaturesn00B.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); - Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + try (ZipFile zip = new ZipFile(file)) { + Assert.assertNotNull(zip.getEntry("META-INF/l77Tsignaturesn00B.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures0.xml")); + Assert.assertNotNull(zip.getEntry("META-INF/signatures1.xml")); + } } @Test(expected = DigiDoc4JException.class) @@ -976,7 +979,7 @@ public void containerWithImplicitPolicy(){ } @Test - public void bdocTM_OcspResponderCert_shouldContainResponderCertIdAttribute() throws Exception { + public void bdocTM_OcspResponderCert_shouldContainResponderCertIdAttribute() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); BDocSignature signature = this.createSignatureBy(container, SignatureProfile.LT_TM, pkcs12SignatureToken); @@ -1001,7 +1004,7 @@ public void savingContainerWithoutSignatures_shouldNotThrowException() throws Ex } @Test - public void openBDoc_withoutCAConfiguration_shouldNotThrowException() throws Exception { + public void openBDoc_withoutCAConfiguration_shouldNotThrowException() { this.configuration = new Configuration(Configuration.Mode.TEST); this.configuration.loadConfiguration("src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_no_ca.yaml"); BDocContainer container = new BDocContainer("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc", this.configuration); @@ -1009,13 +1012,13 @@ public void openBDoc_withoutCAConfiguration_shouldNotThrowException() throws Exc } @Test - public void timeStampCertStatusDeprecated() throws Exception { + public void timeStampCertStatusDeprecated() { BDocContainer container = new BDocContainer("src/test/resources/testFiles/invalid-containers/invalid-containers-23816_leedu_live_TS_authority.asice", new Configuration(Configuration.Mode.PROD)); Assert.assertFalse(container.validate().isValid()); } @Test - public void settingUpOwnSignaturePolicy() throws Exception { + public void settingUpOwnSignaturePolicy() { String signatureId = "signatureId"; byte[] digestValue = Base64.decodeBase64("3Tl1oILSvOAWomdI9VeWV6IA/32eSXRUri9kPEz1IVs="); ObjectIdentifierQualifier qualifier = ObjectIdentifierQualifier.OID_AS_URN; @@ -1045,7 +1048,7 @@ public void settingUpOwnSignaturePolicy() throws Exception { } @Test - public void containerWithSignaturePolicyByDefault() throws Exception { + public void containerWithSignaturePolicyByDefault() { Container container = ContainerBuilder.aContainer(Container.DocumentType.BDOC).build(); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); Signature signature = SignatureBuilder.aSignature(container).withSignatureDigestAlgorithm(DigestAlgorithm.SHA224). @@ -1075,18 +1078,20 @@ public void containerWithMultipleIdenticallyNamedSignaturesShouldFail() { Assert.assertSame(4, validationResult.getWarnings().size()); - Assert.assertSame(9, validationResult.getErrors().size()); + Assert.assertSame(11, validationResult.getErrors().size()); List errors = validationResult.getErrors(); Assert.assertEquals(errors.get(0).getMessage(), "Wrong policy identifier: 1.3.6.1.4.1.10015.1000.3.1.1"); - Assert.assertEquals(errors.get(1).getMessage(), "The result of the LTV validation process is not acceptable to continue the process!"); - Assert.assertEquals(errors.get(2).getMessage(), "The signature policy is not available!"); - Assert.assertEquals(errors.get(3).getMessage(), "OCSP nonce is invalid"); - Assert.assertEquals(errors.get(4).getMessage(), "Wrong policy identifier: 1.3.6.1.4.1.10015.1000.3.1.1"); - Assert.assertEquals(errors.get(5).getMessage(), "The result of the LTV validation process is not acceptable to continue the process!"); + Assert.assertEquals(errors.get(1).getMessage(), "The signature policy is not available!"); + Assert.assertEquals(errors.get(2).getMessage(), "The certificate validation is not conclusive!"); + Assert.assertEquals(errors.get(3).getMessage(), "The current time is not in the validity range of the signer's certificate!"); + Assert.assertEquals(errors.get(4).getMessage(), "OCSP nonce is invalid"); + Assert.assertEquals(errors.get(5).getMessage(), "Wrong policy identifier: 1.3.6.1.4.1.10015.1000.3.1.1"); Assert.assertEquals(errors.get(6).getMessage(), "The signature policy is not available!"); - Assert.assertEquals(errors.get(7).getMessage(), "OCSP nonce is invalid"); + Assert.assertEquals(errors.get(7).getMessage(), "The certificate validation is not conclusive!"); + Assert.assertEquals(errors.get(8).getMessage(), "The current time is not in the validity range of the signer's certificate!"); + Assert.assertEquals(errors.get(9).getMessage(), "OCSP nonce is invalid"); - DigiDoc4JException duplicateSigFileEx = errors.get(8); + DigiDoc4JException duplicateSigFileEx = errors.get(10); Assert.assertTrue(duplicateSigFileEx instanceof DuplicateSignatureFilesException); Assert.assertEquals(duplicateSigFileEx.getMessage(), "Duplicate signature files: META-INF/signatures1.xml"); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSerializationTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSerializationTest.java index f066b3f83..a5980fd7b 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSerializationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSerializationTest.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* ThMatchers.is software Matchers.is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as thMatchers.is -* project Matchers.is concerned Matchers.is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc; @@ -23,14 +23,11 @@ import org.digidoc4j.SignatureProfile; import org.digidoc4j.SignatureValidationResult; import org.digidoc4j.exceptions.ServiceUnreachableException; -import org.digidoc4j.exceptions.NotYetImplementedException; import org.digidoc4j.test.util.TestDataBuilderUtil; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; -import java.io.IOException; -import java.net.URI; import java.util.Date; public class BDocSerializationTest extends AbstractTest { @@ -39,12 +36,12 @@ public class BDocSerializationTest extends AbstractTest { private String serializedContainerLocation; @Test - public void twoStepSigningWithSerialization() throws IOException, ClassNotFoundException { + public void twoStepSigningWithSerialization() { String serializedDataToSignPath = this.getFileBy("bdoc"); Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); DataToSign dataToSign = SignatureBuilder.aSignature(container). - withSigningCertificate(this.pkcs12SignatureToken.getCertificate()).buildDataToSign(); + withSigningCertificate(pkcs12SignatureToken.getCertificate()).buildDataToSign(); this.serialize(container, this.serializedContainerLocation); this.serialize(dataToSign, serializedDataToSignPath); dataToSign = this.deserializer(serializedDataToSignPath); @@ -65,7 +62,7 @@ public void changeConfigurationAfterDeserializationToInvalidOcspAndThrowConnecti Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); DataToSign dataToSign = SignatureBuilder.aSignature(container). - withSigningCertificate(this.pkcs12SignatureToken.getCertificate()).buildDataToSign(); + withSigningCertificate(pkcs12SignatureToken.getCertificate()).buildDataToSign(); this.serialize(container, this.serializedContainerLocation); this.serialize(dataToSign, serializedDataToSignPath); dataToSign = this.deserializer(serializedDataToSignPath); @@ -76,17 +73,17 @@ public void changeConfigurationAfterDeserializationToInvalidOcspAndThrowConnecti } @Test - public void verifySerialization() throws Exception { + public void verifySerialization() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); Assert.assertTrue(deserializedContainer.validate().isValid()); } @Test - public void serializeExistingContainer() throws Exception { + public void serializeExistingContainer() { Container container = TestDataBuilderUtil.open("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc"); serialize(container, serializedContainerLocation); Container deserializedContainer = deserializer(serializedContainerLocation); @@ -95,7 +92,7 @@ public void serializeExistingContainer() throws Exception { } @Test - public void validateAfterSerializingExistingContainer() throws Exception { + public void validateAfterSerializingExistingContainer() { Container container = TestDataBuilderUtil.open("src/test/resources/testFiles/valid-containers/valid-bdoc-tm.bdoc"); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); @@ -103,11 +100,11 @@ public void validateAfterSerializingExistingContainer() throws Exception { } @Test - public void serializationVerifySpecifiedSignatureParameters() throws Exception { + public void serializationVerifySpecifiedSignatureParameters() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); Signature signature = SignatureBuilder.aSignature(container).withSignatureDigestAlgorithm(DigestAlgorithm.SHA512). - withSignatureToken(this.pkcs12SignatureToken).withSignatureId("S99").withRoles("manager", "employee"). + withSignatureToken(pkcs12SignatureToken).withSignatureId("S99").withRoles("manager", "employee"). withCity("city").withStateOrProvince("state").withPostalCode("postalCode").withCountry("country"). invokeSigning(); container.addSignature(signature); @@ -124,10 +121,10 @@ public void serializationVerifySpecifiedSignatureParameters() throws Exception { } @Test - public void serializationVerifyDefaultSignatureParameters() throws Exception { + public void serializationVerifyDefaultSignatureParameters() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); Signature signature = deserializedContainer.getSignatures().get(0); @@ -138,10 +135,10 @@ public void serializationVerifyDefaultSignatureParameters() throws Exception { } @Test - public void serializationGetDocumentType() throws Exception { + public void serializationGetDocumentType() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); Assert.assertEquals(container.getType(), deserializedContainer.getType()); @@ -151,7 +148,7 @@ public void serializationGetDocumentType() throws Exception { public void serializationGetOCSPCertificate() throws Exception { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); byte[] ocspCertBeforeSerialization = container.getSignatures().get(0).getOCSPCertificate(). @@ -162,10 +159,10 @@ public void serializationGetOCSPCertificate() throws Exception { } @Test - public void serializationGetSigningTime() throws Exception { + public void serializationGetSigningTime() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); Date signingTimeBeforeSerialization = container.getSignatures().get(0).getClaimedSigningTime(); @@ -173,35 +170,11 @@ public void serializationGetSigningTime() throws Exception { Assert.assertEquals(signingTimeBeforeSerialization, signingTimeAfterSerialization); } - @Test(expected = NotYetImplementedException.class) - public void serializationGetPolicy() throws Exception { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); - this.serialize(container, this.serializedContainerLocation); - Container deserializedContainer = this.deserializer(this.serializedContainerLocation); - String signaturePolicyBeforeSerialization = container.getSignatures().get(0).getPolicy(); - String signaturePolicyAfterSerialization = deserializedContainer.getSignatures().get(0).getPolicy(); - Assert.assertEquals(signaturePolicyBeforeSerialization, signaturePolicyAfterSerialization); - } - - @Test(expected = NotYetImplementedException.class) - public void serializationGetSignaturePolicyURI() throws Exception { - Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); - container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); - this.serialize(container, this.serializedContainerLocation); - Container deserializedContainer = this.deserializer(this.serializedContainerLocation); - URI signaturePolicyURIBeforeSerialization = container.getSignatures().get(0).getSignaturePolicyURI(); - URI signaturePolicyURIAfterSerialization = deserializedContainer.getSignatures().get(0).getSignaturePolicyURI(); - Assert.assertEquals(signaturePolicyURIBeforeSerialization, signaturePolicyURIAfterSerialization); - } - @Test public void serializationGetSigningCertificate() throws Exception { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); byte[] signingCertBeforeSerialization = container.getSignatures().get(0).getSigningCertificate(). @@ -212,10 +185,10 @@ public void serializationGetSigningCertificate() throws Exception { } @Test - public void serializationGetRawSignature() throws Exception { + public void serializationGetRawSignature() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); byte[] rawSignatureBeforeSerialization = container.getSignatures().get(0).getAdESSignature(); @@ -227,7 +200,7 @@ public void serializationGetRawSignature() throws Exception { public void serializationGetTimeStampTokenCertificate() throws Exception { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, SignatureProfile.LT, this.pkcs12SignatureToken); + this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); byte[] timeStampTokenCertificateBeforeSerialization = container.getSignatures().get(0). @@ -238,10 +211,10 @@ public void serializationGetTimeStampTokenCertificate() throws Exception { } @Test - public void serializationGetProfile() throws Exception { + public void serializationGetProfile() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); SignatureProfile signatureProfileBeforeSerialization = container.getSignatures().get(0).getProfile(); @@ -250,10 +223,10 @@ public void serializationGetProfile() throws Exception { } @Test - public void serializationGetDataFiles() throws Exception { + public void serializationGetDataFiles() { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); int nrOfDataFilesBeforeSerialization = container.getDataFiles().size(); @@ -265,7 +238,7 @@ public void serializationGetDataFiles() throws Exception { public void serializationDataFileCheck() throws Exception { Container container = this.createEmptyContainerBy(Container.DocumentType.BDOC); container.addDataFile("src/test/resources/testFiles/helper-files/test.txt", "text/plain"); - this.createSignatureBy(container, this.pkcs12SignatureToken); + this.createSignatureBy(container, pkcs12SignatureToken); this.serialize(container, this.serializedContainerLocation); Container deserializedContainer = this.deserializer(this.serializedContainerLocation); DataFile dataFileBeforeSerialization = container.getDataFiles().get(0); @@ -290,7 +263,7 @@ public void twoStepSigningWithSerialization2() { container = SerializationUtils.deserialize(serializedContainer); DataToSign dataToSign = SignatureBuilder.aSignature(container) - .withSigningCertificate(this.pkcs12SignatureToken.getCertificate()) + .withSigningCertificate(pkcs12SignatureToken.getCertificate()) .withSignatureProfile(SignatureProfile.LT_TM) .buildDataToSign(); diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSignatureOpenerTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSignatureOpenerTest.java index 077e0e807..21293b636 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSignatureOpenerTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSignatureOpenerTest.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc; @@ -39,14 +39,14 @@ public class BDocSignatureOpenerTest extends AbstractTest { private BDocSignatureOpener signatureOpener; @Test - public void openBesSignature() throws Exception { + public void openBesSignature() { Signature signature = this.signatureOpener.open( constructXadesSignatureWrapper(new FileDocument("src/test/resources/testFiles/xades/test-bes-signature.xml"))); Assert.assertTrue(signature instanceof BDocSignature); Assert.assertEquals(SignatureProfile.B_BES, signature.getProfile()); Assert.assertEquals("Assert 3", "id-693869a500c60f0dc262f7287f033d5d", signature.getId()); Assert.assertEquals("Assert 4", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", signature.getSignatureMethod()); - Assert.assertEquals(new Date(1454928400000L), signature.getSigningTime()); + Assert.assertEquals(new Date(1454928400000L), signature.getClaimedSigningTime()); Assert.assertEquals("Assert 5", "Tallinn", signature.getCity()); Assert.assertEquals("Assert 6", "Harjumaa", signature.getStateOrProvince()); Assert.assertEquals("Assert 7", "13456", signature.getPostalCode()); @@ -66,7 +66,7 @@ public void openBesSignature() throws Exception { } @Test - public void openXadesSignature() throws Exception { + public void openXadesSignature() { Date date_2016_29_1_time_19_58_36 = new Date(1454090316000L); Date date_2016_29_1_time_19_58_37 = new Date(1454090317000L); Signature signature = this.signatureOpener.open( @@ -75,7 +75,7 @@ public void openXadesSignature() throws Exception { Assert.assertEquals("Assert 2", "S0", signature.getId()); Assert.assertEquals("Assert 3", SignatureProfile.LT, signature.getProfile()); Assert.assertEquals("Assert 4", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", signature.getSignatureMethod()); - Assert.assertEquals("Assert 5", date_2016_29_1_time_19_58_36, signature.getSigningTime()); + Assert.assertEquals("Assert 5", date_2016_29_1_time_19_58_36, signature.getTrustedSigningTime()); Assert.assertTrue("Assert 6", StringUtils.startsWith(signature.getSigningCertificate().issuerName(), "C=EE,O=AS Sertifitseerimiskeskus")); Assert.assertNotNull("Assert 7", signature.getOCSPCertificate()); Assert.assertTrue("Assert 8", StringUtils.contains(signature.getOCSPCertificate().getSubjectName(), "OU=OCSP")); @@ -87,7 +87,7 @@ public void openXadesSignature() throws Exception { } @Test - public void serializeBDocSignature() throws Exception { + public void serializeBDocSignature() { Signature signature = this.signatureOpener.open( constructXadesSignatureWrapper(new FileDocument("src/test/resources/testFiles/xades/test-bdoc-ts.xml"))); String serializedPath = this.getFileBy("ser"); @@ -112,7 +112,7 @@ public void openXadesSignature_withoutXmlPreamble_shouldBeValid() throws Excepti protected void before() { this.configuration = Configuration.of(Configuration.Mode.TEST); this.signatureOpener = new BDocSignatureOpener(this.configuration); - this.signatureParser = new AsicSignatureParser(Collections.singletonList( + this.signatureParser = new AsicSignatureParser(Collections.singletonList( new FileDocument("src/test/resources/testFiles/helper-files/test.txt")), this.configuration); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ContainerParticlesRemovalTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ContainerParticlesRemovalTest.java index d51f5dd32..3f55443ef 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ContainerParticlesRemovalTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ContainerParticlesRemovalTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl.bdoc; import eu.europa.esig.dss.model.DSSDocument; @@ -8,6 +18,7 @@ import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.DataFile; import org.digidoc4j.Signature; +import org.digidoc4j.SignatureBuilder; import org.digidoc4j.SignatureProfile; import org.digidoc4j.exceptions.SignatureNotFoundException; import org.digidoc4j.impl.asic.AsicEntry; @@ -194,16 +205,21 @@ public void tryingToRemoveNonExistingSignatureByIndexFromBDocContainer_shouldThr container.addDataFile(mockDataFile()); Signature signature = this.createSignatureBy(container, SignatureProfile.LT_TM, pkcs12SignatureToken); + Signature nonExistingSignature = SignatureBuilder.aSignature(container) + .withSignatureProfile(SignatureProfile.LT_TM) + .withSignatureToken(pkcs12SignatureToken) + .withSignatureId("id-non-existing") + .invokeSigning(); assertEquals(1, container.getSignatures().size()); assertTrue(container.getSignatures().contains(signature)); SignatureNotFoundException caughtException = assertThrows( SignatureNotFoundException.class, - () -> container.removeSignature(1) + () -> container.removeSignature(nonExistingSignature) ); - assertEquals("Signature from index 1 not found", caughtException.getMessage()); + assertEquals("Signature not found: id-non-existing", caughtException.getMessage()); assertEquals(1, container.getSignatures().size()); assertTrue(container.getSignatures().contains(signature)); } @@ -214,16 +230,21 @@ public void tryingToRemoveNonExistingSignatureByIndexFromASiCEContainer_shouldTh container.addDataFile(mockDataFile()); Signature signature = this.createSignatureBy(container, SignatureProfile.LT, pkcs12SignatureToken); + Signature nonExistingSignature = SignatureBuilder.aSignature(container) + .withSignatureProfile(SignatureProfile.LT) + .withSignatureToken(pkcs12SignatureToken) + .withSignatureId("id-non-existing") + .invokeSigning(); assertEquals(1, container.getSignatures().size()); assertTrue(container.getSignatures().contains(signature)); SignatureNotFoundException caughtException = assertThrows( SignatureNotFoundException.class, - () -> container.removeSignature(1) + () -> container.removeSignature(nonExistingSignature) ); - assertEquals("Signature from index 1 not found", caughtException.getMessage()); + assertEquals("Signature not found: id-non-existing", caughtException.getMessage()); assertEquals(1, container.getSignatures().size()); assertTrue(container.getSignatures().contains(signature)); } @@ -245,7 +266,7 @@ public void dataFileRemovalFromBDocContainerThroughoutContainerSavingAndOpening_ containerParseResultContainsDataFile(container.getContainerParseResult(), dataFile.getName()); assertTrue(container.validate().isValid()); - container.removeDataFile(dataFile.getName()); + container.removeDataFile(container.getDataFiles().get(0)); assertTrue(container.getDataFiles().isEmpty()); containerParseResultDoesNotContainDataFile(container.getContainerParseResult(), dataFile.getName()); assertTrue(container.validate().isValid()); @@ -275,7 +296,7 @@ public void dataFileRemovalFromASiCEContainerThroughoutContainerSavingAndOpening containerParseResultContainsDataFile(container.getContainerParseResult(), dataFile.getName()); assertTrue(container.validate().isValid()); - container.removeDataFile(dataFile.getName()); + container.removeDataFile(container.getDataFiles().get(0)); assertTrue(container.getDataFiles().isEmpty()); containerParseResultDoesNotContainDataFile(container.getContainerParseResult(), dataFile.getName()); assertTrue(container.validate().isValid()); diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/IncompleteSigningTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/IncompleteSigningTest.java index 323f6b9b2..56ff13155 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/IncompleteSigningTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/IncompleteSigningTest.java @@ -1,7 +1,18 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl.bdoc; import eu.europa.esig.dss.model.DSSException; import eu.europa.esig.dss.model.x509.CertificateToken; +import eu.europa.esig.dss.spi.client.http.DSSFileLoader; import eu.europa.esig.dss.spi.client.http.DataLoader; import org.apache.commons.codec.binary.Hex; import org.digidoc4j.AbstractTest; @@ -15,7 +26,11 @@ import org.digidoc4j.exceptions.CertificateValidationException; import org.digidoc4j.exceptions.OCSPRequestFailedException; import org.digidoc4j.exceptions.TechnicalException; +import org.digidoc4j.exceptions.TslRefreshException; import org.digidoc4j.test.MockConfigurableDataLoader; +import org.digidoc4j.test.MockConfigurableFileLoader; +import org.digidoc4j.test.MockTSLRefreshCallback; +import org.digidoc4j.test.TestAssert; import org.junit.Assert; import org.junit.Test; @@ -25,7 +40,6 @@ import java.nio.file.Paths; import java.security.cert.X509Certificate; - /** * Description of tests by their suffix: *

    @@ -44,7 +58,7 @@ */ public class IncompleteSigningTest extends AbstractTest { - private static final String LTV_VALIDATION_ERROR_MESSAGE = "The result of the LTV validation process is not acceptable to continue the process!"; + private static final String VALIDATION_ERROR_MESSAGE = "The certificate validation is not conclusive!"; @Test(expected = OCSPRequestFailedException.class) public void signatureProfileLtTmShouldFailWhenSigningCertificateIsNotTrustedByTSL() { @@ -69,10 +83,7 @@ public void signatureProfileBbesShouldNotFailWhenSigningCertificateIsNotTrustedB setUpProdConfigurationWithTestTsaAndOcsp(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_BES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test @@ -80,10 +91,7 @@ public void signatureProfileBepesShouldNotFailWhenSigningCertificateIsNotTrusted setUpProdConfigurationWithTestTsaAndOcsp(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_EPES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test(expected = CertificateValidationException.class) @@ -113,10 +121,7 @@ public void signatureProfileBbesShouldNotFailWhenOcspResponderIsNotTrustedByTSL( ensureCertificateTrustedByTSL(pkcs12SignatureToken.getCertificate()); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_BES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test @@ -125,27 +130,45 @@ public void signatureProfileBepesShouldNotFailWheOcspResponderIsNotTrustedByTSL( ensureCertificateTrustedByTSL(pkcs12SignatureToken.getCertificate()); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_EPES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); + } + + @Test(expected = TslRefreshException.class) + public void signatureProfileLtTmShouldFailWhenTslCouldNotBeLoadedWithDefaultTslCallback() { + setUpTestConfigurationWithEmptyTSL(); + createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT_TM, pkcs12SignatureToken); } @Test(expected = OCSPRequestFailedException.class) - public void signatureProfileLtTmShouldFailWhenTslCouldNotBeLoaded() { + public void signatureProfileLtTmShouldFailWhenTslCouldNotBeLoadedWithCustomTslCallback() { setUpTestConfigurationWithEmptyTSL(); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT_TM, pkcs12SignatureToken); } + @Test(expected = TslRefreshException.class) + public void signatureProfileLtShouldFailWhenTslCouldNotBeLoadedWithDefaultTslCallback() { + setUpTestConfigurationWithEmptyTSL(); + createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT, pkcs12SignatureToken); + } + @Test(expected = OCSPRequestFailedException.class) - public void signatureProfileLtShouldFailWhenTslCouldNotBeLoaded() { + public void signatureProfileLtShouldFailWhenTslCouldNotBeLoadedWithCustomTslCallback() { setUpTestConfigurationWithEmptyTSL(); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT, pkcs12SignatureToken); } + @Test(expected = TslRefreshException.class) + public void signatureProfileLtaShouldFailWhenTslCouldNotBeLoadedWithDefaultTslCallback() { + setUpTestConfigurationWithEmptyTSL(); + createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LTA, pkcs12SignatureToken); + } + @Test(expected = OCSPRequestFailedException.class) - public void signatureProfileLtaShouldFailWhenTslCouldNotBeLoaded() { + public void signatureProfileLtaShouldFailWhenTslCouldNotBeLoadedWithCustomTslCallback() { setUpTestConfigurationWithEmptyTSL(); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LTA, pkcs12SignatureToken); } @@ -154,10 +177,7 @@ public void signatureProfileBbesShouldNotFailWhenTslCouldNotBeLoaded() { setUpTestConfigurationWithEmptyTSL(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_BES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test @@ -165,15 +185,19 @@ public void signatureProfileBepesShouldNotFailWhenTslCouldNotBeLoaded() { setUpTestConfigurationWithOkTslButFailingDataLoaders(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_EPES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); + } + + @Test(expected = TslRefreshException.class) + public void signatureProfileLtTmShouldFailWhenTslLoadingFailsWithDefaultTslCallback() { + setUpTestConfigurationWithFailingTSL(); + createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT_TM, pkcs12SignatureToken); } @Test(expected = OCSPRequestFailedException.class) - public void signatureProfileLtTmShouldFailWhenTslLoadingFails() { + public void signatureProfileLtTmShouldFailWhenTslLoadingFailsWithCustomTslCallback() { setUpTestConfigurationWithFailingTSL(); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.LT_TM, pkcs12SignatureToken); } @@ -194,10 +218,7 @@ public void signatureProfileBbesShouldNotFailWhenTslLoadingFails() { setUpTestConfigurationWithFailingTSL(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_BES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test @@ -205,10 +226,7 @@ public void signatureProfileBepesShouldNotFailWhenTslLoadingFails() { setUpTestConfigurationWithFailingTSL(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_EPES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test(expected = TechnicalException.class) @@ -234,10 +252,7 @@ public void signatureProfileBbesShouldNotFailWhenDataLoadersFail() { setUpTestConfigurationWithOkTslButFailingDataLoaders(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_BES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } @Test @@ -245,10 +260,7 @@ public void signatureProfileBepesShouldNotFailWhenDataLoadersFail() { setUpTestConfigurationWithOkTslButFailingDataLoaders(); Signature signature = createSignatureBy(createNonEmptyContainerByConfiguration(), SignatureProfile.B_EPES, pkcs12SignatureToken); ValidationResult validationResult = reloadSignature(signature, Configuration.Mode.TEST).validateSignature(); - Assert.assertTrue( - "Validation result is expected to contain error: " + LTV_VALIDATION_ERROR_MESSAGE, - validationResult.getErrors().stream().anyMatch(e -> e.getMessage().contains(LTV_VALIDATION_ERROR_MESSAGE)) - ); + TestAssert.assertContainsErrors(validationResult.getErrors(), VALIDATION_ERROR_MESSAGE); } /** @@ -324,11 +336,18 @@ private static void configureFailingDataLoaders(Configuration configuration) { }) .withPoster((url, content) -> { String contentHex = (content == null) ? "null" : Hex.encodeHexString(content); - throw new DSSException(String.format("Failed to POST URL: %s; content: %s", url, contentHex)); + String message = String.format("Failed to POST URL: %s; content: %s", url, contentHex); + throw new DSSException(message); + }); + + DSSFileLoader failingFileLoader = new MockConfigurableFileLoader() + .withDocumentGetter(url -> { + String message = String.format("Failed to GET URL: %s", url); + throw new DSSException(message); }); configuration.setOcspDataLoaderFactory(() -> failingDataLoader); - configuration.setTslDataLoaderFactory(() -> failingDataLoader); + configuration.setTslFileLoaderFactory(() -> failingFileLoader); configuration.setTspDataLoaderFactory(() -> failingDataLoader); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/SignatureTimeTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/SignatureTimeTest.java index 1dd494802..5888d72aa 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/SignatureTimeTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/SignatureTimeTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl.bdoc; import org.digidoc4j.AbstractTest; @@ -9,6 +19,11 @@ import org.junit.Assert; import org.junit.Test; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; + /** * Created by Andrei on 26.04.2017. */ @@ -16,43 +31,53 @@ public class SignatureTimeTest extends AbstractTest { @Test - public void signatureProfileLTTMTest() throws Exception { + public void signatureProfileLTTMTest() { + Instant notBefore = truncatedCurrentTime(); Container container = this.createNonEmptyContainer(); - BDocSignature signature = (BDocSignature) this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT_TM, this.pkcs12SignatureToken); + BDocSignature signature = createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT_TM, pkcs12SignatureToken); container.addSignature(signature); - Assert.assertEquals(signature.getSigningTime(), signature.getTrustedSigningTime()); + assertTimeBetweenNotBeforeAndNow(signature.getClaimedSigningTime(), notBefore, Duration.ofMinutes(1L)); + assertTimeBetweenNotBeforeAndNow(signature.getTrustedSigningTime(), notBefore, Duration.ofMinutes(1L)); } @Test - public void signatureProfileLTTest() throws Exception { + public void signatureProfileLTTest() { + Instant notBefore = truncatedCurrentTime(); Container container = this.createNonEmptyContainer(); - AsicESignature signature = (AsicESignature) this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT, this.pkcs12SignatureToken); + AsicESignature signature = createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LT, pkcs12SignatureToken); container.addSignature(signature); - Assert.assertEquals(signature.getSigningTime(), signature.getTrustedSigningTime()); + assertTimeBetweenNotBeforeAndNow(signature.getClaimedSigningTime(), notBefore, Duration.ofMinutes(1L)); + assertTimeBetweenNotBeforeAndNow(signature.getTrustedSigningTime(), notBefore, Duration.ofMinutes(1L)); } @Test - public void signatureProfileLTATest() throws Exception { + public void signatureProfileLTATest() { + Instant notBefore = truncatedCurrentTime(); Container container = this.createNonEmptyContainer(); - AsicESignature signature = (AsicESignature) this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LTA, this.pkcs12SignatureToken); + AsicESignature signature = createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.LTA, pkcs12SignatureToken); container.addSignature(signature); - Assert.assertEquals(signature.getSigningTime(), signature.getTrustedSigningTime()); + assertTimeBetweenNotBeforeAndNow(signature.getClaimedSigningTime(), notBefore, Duration.ofMinutes(1L)); + assertTimeBetweenNotBeforeAndNow(signature.getTrustedSigningTime(), notBefore, Duration.ofMinutes(1L)); } @Test - public void signatureProfileB_BESTest() throws Exception { + public void signatureProfileB_BESTest() { + Instant notBefore = truncatedCurrentTime(); Container container = this.createNonEmptyContainer(); - AsicESignature signature = (AsicESignature) this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_BES, this.pkcs12SignatureToken); + AsicESignature signature = createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_BES, pkcs12SignatureToken); container.addSignature(signature); - Assert.assertEquals(signature.getSigningTime(), signature.getClaimedSigningTime()); + assertTimeBetweenNotBeforeAndNow(signature.getClaimedSigningTime(), notBefore, Duration.ofMinutes(1L)); + Assert.assertNull(signature.getTrustedSigningTime()); } @Test - public void signatureProfileB_EPESTest() throws Exception { + public void signatureProfileB_EPESTest() { + Instant notBefore = truncatedCurrentTime(); Container container = this.createNonEmptyContainer(); - AsicESignature signature = (AsicESignature) this.createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_EPES, this.pkcs12SignatureToken); + AsicESignature signature = createSignatureBy(Container.DocumentType.BDOC, SignatureProfile.B_EPES, pkcs12SignatureToken); container.addSignature(signature); - Assert.assertEquals(signature.getSigningTime(), signature.getClaimedSigningTime()); + assertTimeBetweenNotBeforeAndNow(signature.getClaimedSigningTime(), notBefore, Duration.ofMinutes(1L)); + Assert.assertNull(signature.getTrustedSigningTime()); } /* @@ -64,4 +89,19 @@ protected void before() { this.configuration = Configuration.of(Configuration.Mode.TEST); } + private static Instant truncatedCurrentTime() { + return Instant.now().truncatedTo(ChronoUnit.SECONDS); + } + + private static void assertTimeBetweenNotBeforeAndNow(Date time, Instant notBefore, Duration notAfterSkew) { + Instant timeAsInstant = time.toInstant(); + if (timeAsInstant.isBefore(notBefore)) { + Assert.fail(String.format("Time '%s' is before 'not-before' (%s)", timeAsInstant, notBefore)); + } + Instant notAfter = Instant.now().plus(notAfterSkew); + if (timeAsInstant.isAfter(notAfter)) { + Assert.fail(String.format("Time '%s' is after 'not-after' (%s)", timeAsInstant, notAfter)); + } + } + } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/UriEncodingTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/UriEncodingTest.java index c9409b47b..a7b6075e7 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/UriEncodingTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/UriEncodingTest.java @@ -1,22 +1,27 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc; import org.apache.xml.security.signature.Reference; -import org.digidoc4j.*; +import org.digidoc4j.AbstractTest; +import org.digidoc4j.Configuration; +import org.digidoc4j.Container; +import org.digidoc4j.ContainerBuilder; +import org.digidoc4j.ContainerOpener; +import org.digidoc4j.ContainerValidationResult; +import org.digidoc4j.Signature; import org.digidoc4j.impl.asic.asice.AsicESignature; -import org.digidoc4j.impl.asic.asice.bdoc.BDocSignature; +import org.digidoc4j.test.TestAssert; import org.digidoc4j.test.util.TestDataBuilderUtil; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.io.ByteArrayInputStream; @@ -27,7 +32,7 @@ public class UriEncodingTest extends AbstractTest { @Test // DetachedSignatureBuilder.createReference(...) uses UTF-8 from dss5.0 - public void signatureReferencesUseUriEncodingButManifestUsesPlainUtf8() throws InterruptedException { + public void signatureReferencesUseUriEncodingButManifestUsesPlainUtf8() { String fileName = "dds_JÜRIÖÖ € žŠ päev.txt"; String expectedEncoding = "dds_J%C3%9CRI%C3%96%C3%96%20%E2%82%AC%20%C5%BE%C5%A0%20p%C3%A4ev.txt"; this.signAndAssert(fileName, expectedEncoding); @@ -36,23 +41,70 @@ public void signatureReferencesUseUriEncodingButManifestUsesPlainUtf8() throws I @Test // DetachedSignatureBuilder.createReference(...) uses UTF-8 from dss5.0 - public void encodeDataFileWithSpecialCharacters() throws Exception { + public void encodeDataFileWithSpecialCharacters() { String fileName = "et10i_0123456789!#$%&'()+,-. ;=@[]_`}~ et_EE"; String expectedEncoding = "et10i_0123456789%21%23%24%25%26%27%28%29%2B%2C-.%20%3B%3D%40%5B%5D_%60%7D%7E%20et_EE"; this.signAndAssert(fileName, expectedEncoding); } @Test - @Ignore("https://ec.europa.eu/cefdigital/tracker/browse/DSS-1515") - public void validatePartialEncoding_shouldBeValid() throws Exception { + public void validatePartialEncoding_shouldBeValid() { Container container = this.openContainerByConfiguration(Paths.get("src/test/resources/testFiles/valid-containers/et10_0123456789!#$%&'()+,-. ;=@[]_`}- et_EE_utf8.zip-d_ec.bdoc"), this.configuration); - Assert.assertTrue(container.validate().isValid()); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); } @Test - public void validateContainer_withWhitespaceEncodedAsPlus_shouldBeValid() throws Exception { + public void validateContainer_withWhitespaceEncodedAsPlus_shouldBeValid() { Container container = this.openContainerByConfiguration(Paths.get("src/test/resources/testFiles/valid-containers/M1n1 Testäöüõ!.txt-TS-d4j.bdoc"), this.configuration); - Assert.assertTrue(container.validate().isValid()); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), + "The reference data object has not been found!", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!" + ); + } + + @Test + public void validateContainer_withSpaceInDataFileNamePercentEncodedInSignature_shouldBeValid() { + Container container = ContainerOpener.open( + "src/test/resources/testFiles/valid-containers/space-in-datafile-name-percent-encoded-in-signature.asice", + Configuration.of(Configuration.Mode.TEST) + ); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); + } + + @Test + public void validateContainer_withPlusInDataFileNamePercentEncodedInSignature_shouldBeValid() { + Container container = ContainerOpener.open( + "src/test/resources/testFiles/valid-containers/plus-in-datafile-name-percent-encoded-in-signature.asice", + Configuration.of(Configuration.Mode.TEST) + ); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); + } + + @Test + public void validateContainer_withSpaceInDataFileNameEncodedAsPlusInSignature_shouldNotBeValid() { + Container container = ContainerOpener.open( + "src/test/resources/testFiles/invalid-containers/space-in-datafile-name-encoded-as-plus-in-signature.asice", + Configuration.of(Configuration.Mode.TEST) + ); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), + "The reference data object has not been found!" + ); + } + + @Test + public void validateContainer_withPlusInDataFileNameNotEncodedInSignature_shouldBeValid() { + Container container = ContainerOpener.open( + "src/test/resources/testFiles/valid-containers/plus-in-datafile-name-unencoded-in-signature.asice", + Configuration.of(Configuration.Mode.TEST) + ); + ContainerValidationResult validationResult = container.validate(); + TestAssert.assertContainerIsValid(validationResult); } /* diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java index 2bb7f1491..cd8fbd192 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ValidationTest.java @@ -154,7 +154,7 @@ public void testExpiredCertSign() { .buildDataToSign(); dataToSign.finalize(TestSigningUtil.sign(dataToSign.getDataToSign(), dataToSign.getDigestAlgorithm())); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("not in certificate validity range")); + Assert.assertTrue(e.getMessage().contains("is expired at signing time")); throw e; } } @@ -165,7 +165,7 @@ public void signatureFileContainsIncorrectFileName() { .open("src/test/resources/prodFiles/invalid-containers/filename_mismatch_signature.asice", PROD_CONFIGURATION); SignatureValidationResult validate = container.validate(); List errors = validate.getErrors(); - Assert.assertEquals(5, errors.size()); + Assert.assertEquals(7, errors.size()); TestAssert.assertContainsError("(Signature ID: S0) - The signature file for signature S0 has an entry for file <0123456789~#%&()=`@{[]}'.txt> with mimetype but the manifest file does not have an entry for this file", errors); } @@ -212,11 +212,11 @@ public void containerFileAndManifestContainsExtraFile() { public void validateContainer_withChangedDataFileContent_isInvalid() throws Exception { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/invalid-data-file.bdoc"); SignatureValidationResult validate = container.validate(); - Assert.assertEquals(2, validate.getErrors().size()); - Assert.assertEquals("(Signature ID: S0) - The result of the LTV validation process is not acceptable to continue the process!", - validate.getErrors().get(0).toString()); - Assert.assertEquals("(Signature ID: S0) - The reference data object is not intact!", - validate.getErrors().get(1).toString()); + TestAssert.assertContainsExactSetOfErrors(validate.getErrors(), + "(Signature ID: S0) - The reference data object is not intact!", + "(Signature ID: S0) - The current time is not in the validity range of the signer's certificate!", + "(Signature ID: S0) - The certificate validation is not conclusive!" + ); } @Test @@ -226,16 +226,14 @@ public void secondSignatureFileContainsIncorrectFileName() { "src/test/resources/testFiles/invalid-containers/filename_mismatch_second_signature.asice", this.configuration); SignatureValidationResult validate = container.validate(); - List errors = validate.getErrors(); - Assert.assertEquals(4, errors.size()); - Assert.assertEquals("(Signature ID: S1) - The result of the LTV validation process is not acceptable to continue the process!", - errors.get(0).toString()); - Assert.assertEquals( - "(Signature ID: S1) - Manifest file has an entry for file with mimetype but " - + "the signature file for signature S1 does not have an entry for this file", - errors.get(2).toString()); - Assert.assertEquals("Container contains a file named which is not found in the signature file", - errors.get(3).toString()); + TestAssert.assertContainsExactSetOfErrors(validate.getErrors(), + "(Signature ID: S1) - The reference data object is not intact!", + "(Signature ID: S1) - Manifest file has an entry for file with mimetype but " + + "the signature file for signature S1 does not have an entry for this file", + "Container contains a file named which is not found in the signature file", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!" + ); } @Test @@ -259,8 +257,12 @@ public void container_withChangedDataFileName_shouldBeInvalid() throws Exception Container container = ContainerOpener .open("src/test/resources/testFiles/invalid-containers/bdoc-tm-with-changed-data-file-name.bdoc"); SignatureValidationResult result = container.validate(); - Assert.assertEquals(3, result.getErrors().size()); - Assert.assertEquals("Container contains a file named which is not found in the signature file", result.getErrors().get(2).getMessage()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - The reference data object has not been found!", + "Container contains a file named which is not found in the signature file", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!" + ); } @Test @@ -327,8 +329,9 @@ public void missingManifestFile() { .open("src/test/resources/prodFiles/invalid-containers/missing_manifest.asice", PROD_CONFIGURATION); SignatureValidationResult result = container.validate(); Assert.assertFalse(result.isValid()); - Assert.assertEquals("Unsupported format: Container does not contain a manifest file", - result.getErrors().get(0).getMessage()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "Unsupported format: Container does not contain a manifest file" + ); } @Test(expected = DigiDoc4JException.class) @@ -354,8 +357,10 @@ public void containerMissesFileWhichIsInManifestAndSignatureFile() { TestTSLUtil.addSkTsaCertificateToTsl(this.configuration); Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/zip_misses_file_which_is_in_manifest.asice"); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - TestAssert.assertContainsError("(Signature ID: S0) - The certificate chain for timestamp is not trusted, it does not contain a trust anchor.", errors); // Timestamp issuer originates from PROD chain + TestAssert.assertContainsErrors(result.getErrors(), + "The reference data object has not been found!", + "Signature has an invalid timestamp" // Timestamp issuer originates from PROD chain + ); } @Test @@ -382,9 +387,14 @@ public void invalidNoncePolicyOid() { .open("src/test/resources/prodFiles/invalid-containers/23608_bdoc21-invalid-nonce-policy-oid.bdoc", PROD_CONFIGURATION); SignatureValidationResult result = container.validate(); List errors = result.getErrors(); - Assert.assertEquals(2, errors.size()); - TestAssert.assertContainsError("Wrong policy identifier: 1.3.6.1.4.1.10015.1000.3.4.3", errors); - TestAssert.assertContainsError("The certificate is not related to a granted status!", errors); + TestAssert.assertContainsExactSetOfErrors(errors, + "Wrong policy identifier: 1.3.6.1.4.1.10015.1000.3.4.3", + "The certificate is not related to a granted status!", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!", + "The best-signature-time is not before the expiration date of the signing certificate!", + "The past signature validation is not conclusive!" + ); } @Test @@ -393,9 +403,9 @@ public void badNonceContent() { .open("src/test/resources/prodFiles/invalid-containers/bdoc21-bad-nonce-content.bdoc", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(1, errors.size()); - Assert.assertEquals("(Signature ID: S0) - OCSP nonce is invalid", errors.get(0).toString()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - OCSP nonce is invalid" + ); } @Test @@ -403,11 +413,13 @@ public void noSignedPropRefTM() { Container container = ContainerOpener .open("src/test/resources/prodFiles/invalid-containers/REF-03_bdoc21-TM-no-signedpropref.bdoc", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(3, errors.size()); - TestAssert.assertContainsError("(Signature ID: S0) - SignedProperties Reference element is missing", errors); - TestAssert.assertContainsError("(Signature ID: S0) - The result of the LTV validation process is not acceptable to continue the process!", errors); - Assert.assertEquals(3, container.getSignatures().get(0).validateSignature().getErrors().size()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - SignedProperties Reference element is missing", + "(Signature ID: S0) - The signed qualifying property: neither 'message-digest' nor 'SignedProperties' is present!", + "(Signature ID: S0) - The current time is not in the validity range of the signer's certificate!", + "(Signature ID: S0) - The certificate validation is not conclusive!" + ); + Assert.assertEquals(4, container.getSignatures().get(0).validateSignature().getErrors().size()); } @Test @@ -415,10 +427,12 @@ public void noSignedPropRefTS() { Container container = ContainerOpener .open("src/test/resources/prodFiles/invalid-containers/REF-03_bdoc21-TS-no-signedpropref.asice", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(3, errors.size()); - TestAssert.assertContainsError("(Signature ID: S0) - SignedProperties Reference element is missing", errors); - TestAssert.assertContainsError("(Signature ID: S0) - The result of the LTV validation process is not acceptable to continue the process!", errors); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - SignedProperties Reference element is missing", + "(Signature ID: S0) - The signed qualifying property: neither 'message-digest' nor 'SignedProperties' is present!", + "(Signature ID: S0) - The current time is not in the validity range of the signer's certificate!", + "(Signature ID: S0) - The certificate validation is not conclusive!" + ); } @Test @@ -437,9 +451,9 @@ public void incorrectSignedPropertiesReference() { .open("src/test/resources/prodFiles/invalid-containers/signed_properties_reference_not_found.asice", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(4, errors.size()); - TestAssert.assertContainsError("The reference data object has not been found!", errors); + TestAssert.assertContainsExactNumberOfErrorsAndAllExpectedErrorMessages(result.getErrors(), 3, + "The reference data object has not been found!" + ); } @Test @@ -447,12 +461,17 @@ public void nonceIncorrectContent() { Container container = ContainerOpener .open("src/test/resources/prodFiles/invalid-containers/nonce-vale-sisu.bdoc", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(6, errors.size()); - TestAssert.assertContainsError("OCSP nonce is invalid", errors); - TestAssert.assertContainsError("Wrong policy identifier: 1.3.6.1.4.1.10015.1000.2.10.10", errors); - TestAssert.assertContainsError("The result of the LTV validation process is not acceptable to continue the process!", errors); - TestAssert.assertContainsError("The certificate is not related to a granted status!", errors); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "OCSP nonce is invalid", + "Wrong policy identifier: 1.3.6.1.4.1.10015.1000.2.10.10", + "The certificate is not related to a granted status!", + "The signature policy is not available!", + "The reference data object has not been found!", + "The signature file for signature S0 has an entry for file with mimetype " + + " but the manifest file does not have an entry for this file", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!" + ); } @Test @@ -461,10 +480,9 @@ public void badNoncePolicyOidQualifier() { .open("src/test/resources/prodFiles/invalid-containers/SP-03_bdoc21-bad-nonce-policy-oidasuri.bdoc", PROD_CONFIGURATION_WITH_TEST_POLICY); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(1, errors.size()); - Assert.assertEquals("(Signature ID: S0) - Wrong policy identifier qualifier: OIDAsURI", - errors.get(0).toString()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - Wrong policy identifier qualifier: OIDAsURI" + ); Assert.assertEquals(1, container.getSignatures().get(0).validateSignature().getErrors().size()); } @@ -481,61 +499,59 @@ public void invalidNonce() { public void invalidWeakDigestUnknownCa() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/23200_weakdigest-unknown-ca.asice"); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(3, errors.size()); - Assert.assertEquals( - "(Signature ID: S0) - Unable to build a certificate chain until a trusted list!", - errors.get(0).toString()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - Unable to build a certificate chain up to a trusted list!", + "The certificate chain for signature is not trusted, it does not contain a trust anchor." + ); } @Test public void invalidUnknownCa() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/SS-4_teadmataCA.4.asice"); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(3, errors.size()); - Assert.assertEquals( - "(Signature ID: S0) - Unable to build a certificate chain until a trusted list!", - errors.get(0).toString()); + TestAssert.assertContainsExactNumberOfErrorsAndAllExpectedErrorMessages(result.getErrors(), 2, + "(Signature ID: S0) - Unable to build a certificate chain up to a trusted list!" + ); } @Test public void validBDocRsa2047_whenASN1UnsafeIntegerAllowed() { PROD_CONFIGURATION.setAllowASN1UnsafeInteger(true); - Assert.assertEquals(true, PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); + Assert.assertTrue(PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); Container container = ContainerOpener .open("src/test/resources/prodFiles/valid-containers/IB-4183_3.4kaart_RSA2047.bdoc", PROD_CONFIGURATION); - SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(0, errors.size()); + ContainerValidationResult result = container.validate(); + TestAssert.assertContainerIsValid(result); PROD_CONFIGURATION.setAllowASN1UnsafeInteger(false); } @Test public void validTSRsa2047_whenASN1UnsafeIntegerAllowed() { PROD_CONFIGURATION.setAllowASN1UnsafeInteger(true); - Assert.assertEquals(true, PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); + Assert.assertTrue(PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); Container container = ContainerOpener .open("src/test/resources/prodFiles/valid-containers/IB-4183_3.4kaart_RSA2047_TS.asice", PROD_CONFIGURATION); - SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(0, errors.size()); + ContainerValidationResult result = container.validate(); + TestAssert.assertContainerIsValid(result); PROD_CONFIGURATION.setAllowASN1UnsafeInteger(false); } - @Test(expected = TechnicalException.class) + @Test public void invalidBDocRsa2047_whenASN1UnsafeIntegerNotAllowed() { PROD_CONFIGURATION.setAllowASN1UnsafeInteger(false); - Assert.assertEquals(false, PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); + Assert.assertFalse(PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); Container container = ContainerOpener .open("src/test/resources/prodFiles/valid-containers/IB-4183_3.4kaart_RSA2047.bdoc", PROD_CONFIGURATION); - container.validate(); + ContainerValidationResult result = container.validate(); + TestAssert.assertContainsErrors(result.getErrors(), + "There is no candidate for the signing certificate!" + ); } @Test(expected = TechnicalException.class) public void invalidTSRsa2047_whenASN1UnsafeIntegerNotAllowed() { PROD_CONFIGURATION.setAllowASN1UnsafeInteger(false); - Assert.assertEquals(false, PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); + Assert.assertFalse(PROD_CONFIGURATION.isASN1UnsafeIntegerAllowed()); Container container = ContainerOpener .open("src/test/resources/prodFiles/valid-containers/IB-4183_3.4kaart_RSA2047_TS.asice", PROD_CONFIGURATION); container.validate(); @@ -545,11 +561,15 @@ public void invalidTSRsa2047_whenASN1UnsafeIntegerNotAllowed() { public void brokenTS() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/TS_broken_TS.asice"); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); - Assert.assertEquals(4, errors.size()); - Assert.assertEquals("(Signature ID: S0) - The result of the timestamps validation process is not conclusive!", - errors.get(1).toString()); - Assert.assertEquals("(Signature ID: S0) - " + InvalidTimestampException.MESSAGE, errors.get(3).toString()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: S0) - The certificate chain for time-stamp is not trusted, it does not contain a trust anchor.", + "(Signature ID: S0) - Unable to build a certificate chain up to a trusted list!", + "(Signature ID: S0) - " + InvalidTimestampException.MESSAGE, + "(Signature ID: S0) - The current time is not in the validity range of the signer's certificate!", + "(Signature ID: S0) - The certificate validation is not conclusive!", + "(Signature ID: S0) - The best-signature-time is not before the expiration date of the signing certificate!", + "(Signature ID: S0) - The past signature validation is not conclusive!" + ); } @Test @@ -683,10 +703,9 @@ public void ocspResponseShouldNotBeTakenFromPreviouslyValidatedSignatures_whenOc @Test public void validateContainerWithBomSymbolsInMimeType_shouldBeValid() throws Exception { - Assert.assertTrue(this.openContainerByConfiguration( + TestAssert.assertContainerIsValid(this.openContainerByConfiguration( Paths.get("src/test/resources/prodFiles/valid-containers/IB-4185_bdoc21_TM_mimetype_with_BOM_PROD.bdoc"), - PROD_CONFIGURATION) - .validate().isValid()); + PROD_CONFIGURATION)); } @Test @@ -756,17 +775,15 @@ public void mixTSLCertAndTSLOnlineSources_SignatureTypeLT_notValid() throws Exce this.createSignatureBy(container, SignatureProfile.LT, new PKCS12SignatureToken("src/test/resources/testFiles/p12/user_one.p12", "user_one".toCharArray())); SignatureValidationResult result = container.validate(); - List errors = result.getErrors(); List signatureList = container.getSignatures(); Signature signature = signatureList.get(0); String signatureId = signature.getId(); Assert.assertFalse(result.isValid()); - Assert.assertEquals(4, errors.size()); - Assert.assertEquals("(Signature ID: " + signatureId + - ") - The result of the timestamps validation process is not conclusive!", - errors.get(1).toString()); - Assert.assertEquals("(Signature ID: " + signatureId + ") - Signature has an invalid timestamp", - errors.get(3).toString()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "(Signature ID: " + signatureId + ") - The certificate chain for time-stamp is not trusted, it does not contain a trust anchor.", + "(Signature ID: " + signatureId + ") - Unable to build a certificate chain up to a trusted list!", + "(Signature ID: " + signatureId + ") - Signature has an invalid timestamp" + ); } @Test @@ -788,15 +805,14 @@ public void validateBDocTs_Invalid() throws Exception { Container container = ContainerOpener.open("src/test/resources/prodFiles/invalid-containers/bdoc21-ts-ok.bdoc", PROD_CONFIGURATION); SignatureValidationResult result = container.validate(); Assert.assertFalse(result.isValid()); - Assert.assertEquals(9, result.getErrors().size()); - TestAssert.assertContainsError("The result of the timestamps validation process is not conclusive!", result.getErrors()); - TestAssert.assertContainsError("The certificate chain for timestamp is not trusted, it does not contain a trust anchor.", result.getErrors()); - TestAssert.assertContainsError("Signature has an invalid timestamp", result.getErrors()); - TestAssert.assertContainsError("The result of the LTV validation process is not acceptable to continue the process!", result.getErrors()); - TestAssert.assertContainsError("The certificate is not related to a granted status!", result.getErrors()); - TestAssert.assertContainsError( - "Manifest file has an entry for file with mimetype but the " + - "signature file for signature S0 indicates the mimetype is <>", result.getErrors()); + TestAssert.assertContainsExactNumberOfErrorsAndAllExpectedErrorMessages(result.getErrors(), 9, + "The certificate chain for time-stamp is not trusted, it does not contain a trust anchor.", + "Signature has an invalid timestamp", + "The certificate validation is not conclusive!", + "The certificate is not related to a granted status!", + "Manifest file has an entry for file with mimetype but the " + + "signature file for signature S0 indicates the mimetype is <>" + ); } @Test @@ -848,7 +864,7 @@ public void prodContainerWithSignatureWarningOfTrustedCertificateNotMatchingWith fromExistingFile("src/test/resources/prodFiles/valid-containers/Baltic MoU digital signing_EST_LT_LV.bdoc"). withConfiguration(PROD_CONFIGURATION).build(); ContainerValidationResult validationResult = container.validate(); - Assert.assertTrue(validationResult.isValid()); + TestAssert.assertContainerIsValid(validationResult); Assert.assertTrue(validationResult.getErrors().isEmpty()); I18nProvider i18nProvider = new I18nProvider(); Assert.assertFalse(validationResult.getWarnings().contains(i18nProvider.getMessage(MessageTag.QUAL_IS_TRUST_CERT_MATCH_SERVICE_ANS2))); @@ -870,12 +886,16 @@ public void testContainerWithSignatureWarningOfTrustedCertificateNotMatchingWith } @Test - public void container_withTimestampTakenWhenSigningCertificateWasNotValid_shouldBeInvalid() throws Exception { + public void container_withTimestampTakenWhenSigningCertificateWasNotValid_shouldBeInvalid() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/signing_certificate_not_valid_during_timestamping.asice"); SignatureValidationResult result = container.validate(); Assert.assertFalse("Signature must not be valid when timestamp was taken while signing certificate was not valid", result.isValid()); - Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals("Signature has been created with expired certificate", result.getErrors().get(0).getMessage()); + TestAssert.assertContainsExactSetOfErrors(result.getErrors(), + "The best-signature-time is not before the expiration date of the signing certificate!", + "The past signature validation is not conclusive!", + "The current time is not in the validity range of the signer's certificate!", + "The certificate validation is not conclusive!" + ); } @Test @@ -897,9 +917,10 @@ public void container_withPssSignature_shouldBeValid(){ public void container_withExpiredAIAOCSP_LT_shouldBeInvalid() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/esteid2018signerAiaOcspLT.asice"); ContainerValidationResult validationResult = container.validate(); - TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), - "The result of the LTV validation process is not acceptable to continue the process!", - "No acceptable revocation data for the certificate!" + TestAssert.assertContainsErrors(validationResult.getErrors(), + "The certificate validation is not conclusive!", + "No acceptable revocation data for the certificate!", + "The revocation data is not consistent!" ); } @@ -908,8 +929,10 @@ public void container_withExpiredAIAOCSP_LTA_shouldBeInvalid() { Container container = ContainerOpener.open("src/test/resources/testFiles/invalid-containers/esteid2018signerAiaOcspLTA.asice"); ContainerValidationResult validationResult = container.validate(); TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), - "The result of the LTV validation process is not acceptable to continue the process!", - "No acceptable revocation data for the certificate!" + "The certificate validation is not conclusive!", + "No acceptable revocation data for the certificate!", + "The revocation data is not consistent!", + "The current time is not in the validity range of the signer's certificate!" ); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/asic/AsicSignatureFinalizerTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/asic/AsicSignatureFinalizerTest.java index bde2ef509..f72084929 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/asic/AsicSignatureFinalizerTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/asic/AsicSignatureFinalizerTest.java @@ -75,7 +75,7 @@ public void signatureFinalizerFieldsEqualToDataToSign() { SignatureFinalizer signatureFinalizer = SignatureFinalizerBuilder.aFinalizer(container, dataToSign.getSignatureParameters()); assertEquals(dataToSign.getSignatureParameters(), signatureFinalizer.getSignatureParameters()); assertEquals(dataToSign.getConfiguration(), signatureFinalizer.getConfiguration()); - assertEquals(dataToSign.getDigestAlgorithm(), signatureFinalizer.getSignatureParameters().getDigestAlgorithm()); + assertEquals(dataToSign.getDigestAlgorithm(), signatureFinalizer.getSignatureParameters().getSignatureDigestAlgorithm()); } @Test diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/SignatureValidationReportTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/SignatureValidationReportTest.java index aa2d5c2bb..0883d0b35 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/SignatureValidationReportTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/SignatureValidationReportTest.java @@ -1,72 +1,80 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc.report; -import static java.util.Arrays.asList; -import static org.hamcrest.Matchers.containsInAnyOrder; - -import java.util.Date; - +import eu.europa.esig.dss.enumerations.Indication; import eu.europa.esig.dss.enumerations.SignatureLevel; +import eu.europa.esig.dss.enumerations.SignatureQualification; +import eu.europa.esig.dss.enumerations.SubIndication; +import eu.europa.esig.dss.simplereport.jaxb.XmlDetails; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureLevel; +import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureScope; import org.digidoc4j.impl.asic.report.SignatureValidationReport; import org.junit.Assert; import org.junit.Test; -import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; -import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureLevel; -import eu.europa.esig.dss.simplereport.jaxb.XmlSignatureScope; -import eu.europa.esig.dss.enumerations.SignatureQualification; -import eu.europa.esig.dss.enumerations.Indication; -import eu.europa.esig.dss.enumerations.SubIndication; +import java.util.Date; + +import static java.util.Arrays.asList; +import static org.hamcrest.Matchers.containsInAnyOrder; public class SignatureValidationReportTest { @Test - public void copyXmlSignatureParameters() throws Exception { + public void copyXmlSignatureParameters() { XmlSignature signature = new XmlSignature(); Date today = new Date(); signature.setSigningTime(today); + signature.setBestSignatureTime(today); signature.setSignedBy("SignedBy"); signature.setIndication(Indication.TOTAL_PASSED); - // TODO: check and test XmlSignatureLevel usage XmlSignatureLevel sigLevel = new XmlSignatureLevel(); sigLevel.setValue(SignatureQualification.QES); sigLevel.setDescription(SignatureQualification.QES.getLabel()); signature.setSignatureLevel(sigLevel); signature.setSubIndication(SubIndication.NO_POE); - signature.getErrors().addAll(asList("Error1", "Error2")); - signature.getWarnings().addAll(asList("Warning1", "Warning2")); - signature.getInfos().addAll(asList("Info1", "Info2")); - signature.getSignatureScope().addAll(asList(new XmlSignatureScope())); + signature.setAdESValidationDetails(new XmlDetails()); + signature.getAdESValidationDetails().getError().addAll(asList(createMessage("AdESError1"), createMessage("AdESError2"))); + signature.getAdESValidationDetails().getWarning().addAll(asList(createMessage("AdESWarning1"), createMessage("AdESWarning2"))); + signature.getAdESValidationDetails().getInfo().addAll(asList(createMessage("AdESInfo1"), createMessage("AdESInfo2"))); + signature.setQualificationDetails(new XmlDetails()); + signature.getQualificationDetails().getError().addAll(asList(createMessage("QError1"), createMessage("QError2"))); + signature.getQualificationDetails().getWarning().addAll(asList(createMessage("QWarning1"), createMessage("QWarning2"))); + signature.getQualificationDetails().getInfo().addAll(asList(createMessage("QInfo1"), createMessage("QInfo2"))); + signature.getSignatureScope().add(new XmlSignatureScope()); signature.setId("123abc"); - //TODO not in use DSS 5.2 - //signature.setType("Type"); signature.setParentId("Parent ID"); signature.setSignatureFormat(SignatureLevel.UNKNOWN); SignatureValidationReport report = SignatureValidationReport.create(signature); Assert.assertEquals(today, report.getSigningTime()); + Assert.assertEquals(today, report.getBestSignatureTime()); Assert.assertEquals("SignedBy", report.getSignedBy()); Assert.assertEquals(Indication.TOTAL_PASSED, report.getIndication()); Assert.assertEquals("QES", report.getSignatureLevel().getValue().name()); Assert.assertEquals("QES?", report.getSignatureLevel().getValue().getReadable()); Assert.assertEquals(SubIndication.NO_POE, report.getSubIndication()); - Assert.assertThat(report.getErrors(), containsInAnyOrder("Error1", "Error2")); - Assert.assertThat(report.getWarnings(), containsInAnyOrder("Warning1", "Warning2")); - Assert.assertThat(report.getInfos(), containsInAnyOrder("Info1", "Info2")); + Assert.assertThat(report.getErrors(), containsInAnyOrder("AdESError1", "AdESError2", "QError1", "QError2")); + Assert.assertThat(report.getWarnings(), containsInAnyOrder("AdESWarning1", "AdESWarning2", "QWarning1", "QWarning2")); + Assert.assertThat(report.getInfos(), containsInAnyOrder("AdESInfo1", "AdESInfo2", "QInfo1", "QInfo2")); Assert.assertEquals(1, report.getSignatureScope().size()); Assert.assertEquals("123abc", report.getId()); - //TODO not in use DSS 5.2 - //Assert.assertEquals("Type", report.getType()); - Assert.assertEquals("Parent ID", report.getParentId()); Assert.assertEquals(SignatureLevel.UNKNOWN, report.getSignatureFormat()); } + private static XmlMessage createMessage(String message) { + XmlMessage xmlMessage = new XmlMessage(); + xmlMessage.setValue(message); + return xmlMessage; + } + } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/ValidationReportTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/ValidationReportTest.java index dfc52c105..951c41dfb 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/ValidationReportTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/report/ValidationReportTest.java @@ -1,12 +1,12 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc.report; @@ -49,6 +49,8 @@ public void validContainerWithOneSignature() throws Exception { TestAssert.assertXPathHasValue("true", "count(/SimpleReport/Signature[@Id='" + signatureId + "']/CertificateChain/Certificate) > 1", report); TestAssert.assertXPathHasValue("O’CONNEŽ-ŠUSLIK TESTNUMBER,MARY ÄNN,60001013739", "/SimpleReport/Signature[@Id='" + signatureId + "']/CertificateChain/Certificate[1]/qualifiedName", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature[@Id='" + signatureId + "']/SigningTime)", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature[@Id='" + signatureId + "']/BestSignatureTime)", report); } @Test @@ -66,6 +68,8 @@ public void validContainerWithOneTmSignature() throws Exception { TestAssert.assertXPathHasValue("dds_acrobat.pdf", "/SimpleReport/Signature/SignatureScope[2]/@name", report); TestAssert.assertXPathHasValue("true", "count(/SimpleReport/Signature/CertificateChain/Certificate) > 1", report); TestAssert.assertXPathHasValue("O’CONNEŽ-ŠUSLIK TESTNUMBER,MARY ÄNN,60001013739", "/SimpleReport/Signature/CertificateChain/Certificate[1]/qualifiedName", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature/SigningTime)", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature/BestSignatureTime)", report); } @Test @@ -136,7 +140,7 @@ public void invalidContainerWithOneSignature() throws Exception { TestAssert.assertXPathHasValue("ŽÕRINÜWŠKY,MÄRÜ-LÖÖZ,11404176865", "/SimpleReport/Signature/SignedBy", report); TestAssert.assertXPathHasValue("INDETERMINATE", "/SimpleReport/Signature/Indication", report); TestAssert.assertXPathHasValue("REVOKED_NO_POE", "/SimpleReport/Signature/SubIndication", report); - TestAssert.assertXPathHasValue("The past signature validation is not conclusive!", "/SimpleReport/Signature/Errors", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature/Errors[.='The past signature validation is not conclusive!'])", report); TestAssert.assertXPathHasValue("META-INF/signatures0.xml", "/SimpleReport/Signature/DocumentName", report); TestAssert.assertXPathHasValue("test.txt", "/SimpleReport/Signature/SignatureScope/@name", report); TestAssert.assertXPathHasValue("true", "count(/SimpleReport/Signature/CertificateChain/Certificate) > 1", report); @@ -157,7 +161,7 @@ public void invalidContainerWithManifestErrors() throws Exception { TestAssert.assertXPathHasValue("NO_CERTIFICATE_CHAIN_FOUND", "/SimpleReport/Signature/SubIndication", report); TestAssert.assertXPathHasValue("META-INF/signatures0.xml", "/SimpleReport/Signature/DocumentName", report); TestAssert.assertXPathHasValue("RELEASE-NOTES.txt", "/SimpleReport/Signature/SignatureScope/@name", report); - TestAssert.assertXPathHasValue("Unable to build a certificate chain until a trusted list!", "/SimpleReport/Signature/Errors", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature/Errors[.='Unable to build a certificate chain up to a trusted list!'])", report); TestAssert.assertXPathHasValue("Manifest file has an entry for file with mimetype " + "but the signature file for signature S0 does not have an entry for this file", "/SimpleReport/ContainerError[1]", report); TestAssert.assertXPathHasValue("The signature file for signature S0 has an entry for file " + @@ -183,7 +187,7 @@ public void signatureContainsAdditionalErrors() throws Exception { TestAssert.assertXPathHasValue("XAdES-BASELINE-T", "/SimpleReport/Signature/@SignatureFormat", report); TestAssert.assertXPathHasValue("ŽAIKOVSKI,IGOR,37101010021", "/SimpleReport/Signature/SignedBy", report); TestAssert.assertXPathHasValue("INDETERMINATE", "/SimpleReport/Signature/Indication", report); - TestAssert.assertXPathHasValue("Unable to build a certificate chain until a trusted list!", "/SimpleReport/Signature/Errors[1]", report); + TestAssert.assertXPathHasValue("1", "count(/SimpleReport/Signature/Errors[.='Signature has an invalid timestamp'])", report); TestAssert.assertXPathHasValue("META-INF/signatures0.xml", "/SimpleReport/Signature/DocumentName", report); TestAssert.assertXPathHasValue("test.txt", "/SimpleReport/Signature/SignatureScope/@name", report); } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/tsl/TslLoaderTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/tsl/TslLoaderTest.java index f395eade9..65dfe6a02 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/tsl/TslLoaderTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/tsl/TslLoaderTest.java @@ -1,22 +1,24 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.impl.bdoc.tsl; +import eu.europa.esig.dss.enumerations.Indication; +import eu.europa.esig.dss.enumerations.SubIndication; import eu.europa.esig.dss.spi.tsl.LOTLInfo; import eu.europa.esig.dss.spi.tsl.TLInfo; import eu.europa.esig.dss.tsl.job.TLValidationJob; -import eu.europa.esig.dss.enumerations.Indication; import org.digidoc4j.AbstractTest; import org.digidoc4j.Configuration; import org.digidoc4j.impl.asic.tsl.TslLoader; +import org.digidoc4j.test.MockTSLRefreshCallback; import org.digidoc4j.test.util.TestCommonUtil; import org.digidoc4j.test.util.TestTSLUtil; import org.junit.Assert; @@ -29,7 +31,7 @@ public class TslLoaderTest extends AbstractTest { @Ignore @Test - public void loadAndValidateProdTsl() throws Exception { + public void loadAndValidateProdTsl() { this.configuration = new Configuration(Configuration.Mode.PROD); this.createTSLLoader(); this.tslLoader.prepareTsl(); @@ -39,7 +41,7 @@ public void loadAndValidateProdTsl() throws Exception { } @Test - public void loadTsl_whenCacheIsNotExpired_shouldUseCachedTsl() throws Exception { + public void loadTsl_whenCacheIsNotExpired_shouldUseCachedTsl() { this.configuration = new Configuration(Configuration.Mode.TEST); this.configuration.setTslCacheExpirationTime(10000L); this.createTSLLoader(); @@ -50,7 +52,7 @@ public void loadTsl_whenCacheIsNotExpired_shouldUseCachedTsl() throws Exception } @Test - public void loadTsl_whenCacheIsExpired_shouldDownloadNewTsl() throws Exception { + public void loadTsl_whenCacheIsExpired_shouldDownloadNewTsl() { this.configuration = new Configuration(Configuration.Mode.TEST); this.configuration.setTslCacheExpirationTime(500L); this.createTSLLoader(); @@ -62,7 +64,7 @@ public void loadTsl_whenCacheIsExpired_shouldDownloadNewTsl() throws Exception { @Test @Ignore - public void loadTsl_forAllCountries_byDefault() throws Exception { + public void loadTsl_forAllCountries_byDefault() { this.configuration = new Configuration(Configuration.Mode.PROD); LOTLInfo tslRepository = this.initTSLAndGetRepository(); this.assertCountryLoaded(tslRepository, "EE"); @@ -72,7 +74,7 @@ public void loadTsl_forAllCountries_byDefault() throws Exception { @Test @Ignore - public void loadTsl_forOneContry() throws Exception { + public void loadTsl_forOneCountry() { this.configuration = new Configuration(Configuration.Mode.PROD); this.configuration.setTrustedTerritories("EE"); LOTLInfo tslRepository = this.initTSLAndGetRepository(); @@ -82,7 +84,7 @@ public void loadTsl_forOneContry() throws Exception { @Test @Ignore - public void loadTsl_forTwoCountries() throws Exception { + public void loadTsl_forTwoCountries() { this.configuration = new Configuration(Configuration.Mode.PROD); this.configuration.setTrustedTerritories("EE", "ES"); LOTLInfo tslRepository = this.initTSLAndGetRepository(); @@ -92,7 +94,7 @@ public void loadTsl_forTwoCountries() throws Exception { } @Test - public void loadTestTsl_shouldContainTestTerritory() throws Exception { + public void loadTestTsl_shouldContainTestTerritory() { this.configuration = new Configuration(Configuration.Mode.TEST); LOTLInfo tslRepository = this.initTSLAndGetRepository(); this.assertCountryLoaded(tslRepository, "EE_T"); @@ -104,7 +106,7 @@ public void loadTestTsl_shouldContainTestTerritory() throws Exception { @Test @Ignore - public void loadTsl_withoutCountryHr_byDefault() throws Exception { + public void loadTsl_withoutCountryHr_byDefault() { this.configuration = new Configuration(Configuration.Mode.PROD); LOTLInfo tslRepository = this.initTSLAndGetRepository(); this.assertCountryLoaded(tslRepository, "EE"); @@ -114,6 +116,76 @@ public void loadTsl_withoutCountryHr_byDefault() throws Exception { this.assertCountryNotLoaded(tslRepository, "HR"); } + @Test + public void loadProdTsl_withDefaultLotlTruststoreAndPivotSupportDisabled_shouldFail() { + // TODO: this test might be needed to be updated after the pivot chain is reset + configuration = new Configuration(Configuration.Mode.PROD); + configuration.setLotlPivotSupportEnabled(false); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); + LOTLInfo tslRepository = this.initTSLAndGetRepository(); + Assert.assertEquals(Indication.INDETERMINATE, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertEquals(SubIndication.NO_CERTIFICATE_CHAIN_FOUND, tslRepository.getValidationCacheInfo().getSubIndication()); + Assert.assertEquals(0, configuration.getTSL().getNumberOfCertificates()); + } + + @Test + public void loadProdTsl_withDefaultLotlTruststoreAndPivotSupportEnabled_shouldSucceed() { + // TODO: this test might be needed to be updated after the pivot chain is reset + this.configuration = new Configuration(Configuration.Mode.PROD); + configuration.setLotlPivotSupportEnabled(true); + LOTLInfo tslRepository = this.initTSLAndGetRepository(); + Assert.assertEquals(Indication.TOTAL_PASSED, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertTrue(configuration.getTSL().getNumberOfCertificates() > 0); + } + + @Test + public void loadProdTsl_withPivot300LotlTruststoreAndPivotSupportDisabled_shouldSucceed() { + this.configuration = new Configuration(Configuration.Mode.PROD); + // TODO: this might be needed to be updated after the next pivot release + // The used truststore contains the certificates specified in pivot LOTL with sequence number 300 + configuration.setLotlTruststorePath("prodFiles/truststores/lotl-pivot300-truststore.p12"); + configuration.setLotlPivotSupportEnabled(false); + LOTLInfo tslRepository = this.initTSLAndGetRepository(); + Assert.assertEquals(Indication.TOTAL_PASSED, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertTrue(configuration.getTSL().getNumberOfCertificates() > 0); + } + + @Test + public void loadProdTsl_withPivot300LotlTruststoreAndPivotSupportEnabled_shouldSucceed() { + this.configuration = new Configuration(Configuration.Mode.PROD); + // TODO: this might be needed to be updated after the next pivot release + // The used truststore contains the certificates specified in pivot LOTL with sequence number 300 + configuration.setLotlTruststorePath("prodFiles/truststores/lotl-pivot300-truststore.p12"); + configuration.setLotlPivotSupportEnabled(true); + LOTLInfo tslRepository = this.initTSLAndGetRepository(); + Assert.assertEquals(Indication.TOTAL_PASSED, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertTrue(configuration.getTSL().getNumberOfCertificates() > 0); + } + + @Test + public void loadProdTsl_withNonLotlSignersTruststoreAndPivotSupportDisabled_shouldFail() { + configuration = new Configuration(Configuration.Mode.PROD); + configuration.setLotlTruststorePath("testFiles/truststores/lotl-ssl-only-truststore.p12"); + configuration.setLotlPivotSupportEnabled(false); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); + LOTLInfo tslRepository = initTSLAndGetRepository(); + Assert.assertEquals(Indication.INDETERMINATE, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertEquals(SubIndication.NO_CERTIFICATE_CHAIN_FOUND, tslRepository.getValidationCacheInfo().getSubIndication()); + Assert.assertEquals(0, configuration.getTSL().getNumberOfCertificates()); + } + + @Test + public void loadProdTsl_withNonLotlSignersTruststoreAndPivotSupportEnabled_shouldFail() { + configuration = new Configuration(Configuration.Mode.PROD); + configuration.setLotlTruststorePath("testFiles/truststores/lotl-ssl-only-truststore.p12"); + configuration.setLotlPivotSupportEnabled(true); + configuration.setTslRefreshCallback(new MockTSLRefreshCallback(true)); + LOTLInfo tslRepository = initTSLAndGetRepository(); + Assert.assertEquals(Indication.INDETERMINATE, tslRepository.getValidationCacheInfo().getIndication()); + Assert.assertEquals(SubIndication.NO_CERTIFICATE_CHAIN_FOUND, tslRepository.getValidationCacheInfo().getSubIndication()); + Assert.assertEquals(0, configuration.getTSL().getNumberOfCertificates()); + } + /* * RESTRICTED METHODS */ @@ -141,7 +213,7 @@ private long refreshTSLAndGetCacheLastModificationTime() { } private void assertTSLIsValid() { - LOTLInfo lotlInfo = this.tslLoader.getTlValidationJob().getSummary().getLOTLInfos().get(0);; + LOTLInfo lotlInfo = this.tslLoader.getTlValidationJob().getSummary().getLOTLInfos().get(0); for (TLInfo country :lotlInfo.getTLInfos()) { Indication indication = country.getValidationCacheInfo().getIndication(); Assert.assertEquals("TSL is not valid for country " + country, Indication.TOTAL_PASSED, indication); diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/xades/XadesValidationReportProcessorTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/xades/XadesValidationReportProcessorTest.java index 14d2ea37a..48e42b728 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/xades/XadesValidationReportProcessorTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/xades/XadesValidationReportProcessorTest.java @@ -2,15 +2,21 @@ import eu.europa.esig.dss.i18n.I18nProvider; import eu.europa.esig.dss.i18n.MessageTag; -import eu.europa.esig.dss.simplereport.jaxb.XmlSimpleReport; +import eu.europa.esig.dss.simplereport.jaxb.XmlDetails; +import eu.europa.esig.dss.simplereport.jaxb.XmlMessage; import eu.europa.esig.dss.simplereport.jaxb.XmlSignature; +import eu.europa.esig.dss.simplereport.jaxb.XmlSimpleReport; +import eu.europa.esig.dss.simplereport.jaxb.XmlTimestamp; +import eu.europa.esig.dss.simplereport.jaxb.XmlTimestamps; +import eu.europa.esig.dss.simplereport.jaxb.XmlToken; import eu.europa.esig.dss.validation.reports.Reports; import org.digidoc4j.impl.asic.xades.XadesValidationReportProcessor; import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; -import java.util.Arrays; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.when; @@ -30,9 +36,38 @@ public void organizationNameMissingWarningRemoved() { Reports validationReports = Mockito.mock(Reports.class); when(validationReports.getSimpleReportJaxb()).thenReturn(simpleReport); - assertSame(2, signature.getWarnings().size()); + assertSame(2, signature.getAdESValidationDetails().getWarning().size()); + assertSame(2, signature.getQualificationDetails().getWarning().size()); XadesValidationReportProcessor.process(validationReports); - assertSame(1, signature.getWarnings().size()); + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + } + + @Test + public void organizationNameMissingWarningRemovedFromTimestamp() { + XmlTimestamp timestamp = mockTimestampWithWarnings( + i18nProvider.getMessage(MessageTag.QUAL_IS_ADES), + i18nProvider.getMessage(MessageTag.QUAL_IS_TRUST_CERT_MATCH_SERVICE_ANS1) + ); + XmlSignature signature = mockSignatureWithWarnings( + i18nProvider.getMessage(MessageTag.QUAL_IS_ADES) + ); + mockSignatureTimestamps(signature, timestamp); + XmlSimpleReport simpleReport = new XmlSimpleReport(); + simpleReport.getSignatureOrTimestamp().add(signature); + + Reports validationReports = Mockito.mock(Reports.class); + when(validationReports.getSimpleReportJaxb()).thenReturn(simpleReport); + + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + assertSame(2, timestamp.getAdESValidationDetails().getWarning().size()); + assertSame(2, timestamp.getQualificationDetails().getWarning().size()); + XadesValidationReportProcessor.process(validationReports); + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + assertSame(1, timestamp.getAdESValidationDetails().getWarning().size()); + assertSame(1, timestamp.getQualificationDetails().getWarning().size()); } @Test @@ -47,9 +82,38 @@ public void trustedCertificateNotMatchingWithTrustedServiceWarningRemoved() { Reports validationReports = Mockito.mock(Reports.class); when(validationReports.getSimpleReportJaxb()).thenReturn(simpleReport); - assertSame(2, signature.getWarnings().size()); + assertSame(2, signature.getAdESValidationDetails().getWarning().size()); + assertSame(2, signature.getQualificationDetails().getWarning().size()); XadesValidationReportProcessor.process(validationReports); - assertSame(1, signature.getWarnings().size()); + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + } + + @Test + public void trustedCertificateNotMatchingWithTrustedServiceWarningRemovedFromTimestamp() { + XmlTimestamp timestamp = mockTimestampWithWarnings( + i18nProvider.getMessage(MessageTag.QUAL_IS_ADES), + i18nProvider.getMessage(MessageTag.QUAL_IS_TRUST_CERT_MATCH_SERVICE_ANS2) + ); + XmlSignature signature = mockSignatureWithWarnings( + i18nProvider.getMessage(MessageTag.QUAL_IS_ADES) + ); + mockSignatureTimestamps(signature, timestamp); + XmlSimpleReport simpleReport = new XmlSimpleReport(); + simpleReport.getSignatureOrTimestamp().add(signature); + + Reports validationReports = Mockito.mock(Reports.class); + when(validationReports.getSimpleReportJaxb()).thenReturn(simpleReport); + + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + assertSame(2, timestamp.getAdESValidationDetails().getWarning().size()); + assertSame(2, timestamp.getQualificationDetails().getWarning().size()); + XadesValidationReportProcessor.process(validationReports); + assertSame(1, signature.getAdESValidationDetails().getWarning().size()); + assertSame(1, signature.getQualificationDetails().getWarning().size()); + assertSame(1, timestamp.getAdESValidationDetails().getWarning().size()); + assertSame(1, timestamp.getQualificationDetails().getWarning().size()); } @Test @@ -64,14 +128,49 @@ public void noWarningRemoved() { Reports validationReports = Mockito.mock(Reports.class); when(validationReports.getSimpleReportJaxb()).thenReturn(simpleReport); - assertSame(2, signature.getWarnings().size()); + assertSame(2, signature.getAdESValidationDetails().getWarning().size()); + assertSame(2, signature.getQualificationDetails().getWarning().size()); XadesValidationReportProcessor.process(validationReports); - assertSame(2, signature.getWarnings().size()); + assertSame(2, signature.getAdESValidationDetails().getWarning().size()); + assertSame(2, signature.getQualificationDetails().getWarning().size()); + } + + private static void mockSignatureTimestamps(XmlSignature signatureMock, XmlTimestamp... timestamps) { + XmlTimestamps timestampsWrapper = Mockito.mock(XmlTimestamps.class); + ArrayList timestampsList = Stream.of(timestamps) + .collect(Collectors.toCollection(ArrayList::new)); + when(timestampsWrapper.getTimestamp()).thenReturn(timestampsList); + when(signatureMock.getTimestamps()).thenReturn(timestampsWrapper); + } + + private static void mockTokenWarnings(XmlToken tokenMock, String... warnings) { + XmlDetails adESDetails = mockDetailsWithWarnings(warnings); + when(tokenMock.getAdESValidationDetails()).thenReturn(adESDetails); + XmlDetails qualificationDetails = mockDetailsWithWarnings(warnings); + when(tokenMock.getQualificationDetails()).thenReturn(qualificationDetails); } - private XmlSignature mockSignatureWithWarnings(String... warnings) { + private static XmlSignature mockSignatureWithWarnings(String... warnings) { XmlSignature signature = Mockito.mock(XmlSignature.class); - when(signature.getWarnings()).thenReturn(new ArrayList<>(Arrays.asList(warnings))); + mockTokenWarnings(signature, warnings); return signature; } + + private static XmlTimestamp mockTimestampWithWarnings(String... warnings) { + XmlTimestamp timestamp = Mockito.mock(XmlTimestamp.class); + mockTokenWarnings(timestamp, warnings); + return timestamp; + } + + private static XmlDetails mockDetailsWithWarnings(String... warnings) { + XmlDetails details = Mockito.mock(XmlDetails.class); + ArrayList warningsList = Stream.of(warnings).map(w -> { + XmlMessage message = Mockito.mock(XmlMessage.class); + when(message.getValue()).thenReturn(w); + return message; + }).collect(Collectors.toCollection(ArrayList::new)); + when(details.getWarning()).thenReturn(warningsList); + return details; + } + } diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/edoc/TimeStampValidationForEDocTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/edoc/TimeStampValidationForEDocTest.java index e232d5330..c5ef59dd6 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/edoc/TimeStampValidationForEDocTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/edoc/TimeStampValidationForEDocTest.java @@ -4,6 +4,7 @@ import org.digidoc4j.Configuration; import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.exceptions.TimestampAfterOCSPResponseTimeException; +import org.digidoc4j.test.TestAssert; import org.junit.Assert; import org.junit.Test; @@ -22,14 +23,20 @@ public class TimeStampValidationForEDocTest extends AbstractTest { public void timestampAfterOcspResponseTimeShouldResultInInvalidContainerForEDOC() { ContainerValidationResult validationResult = this.openContainerByConfiguration(Paths.get(EDOC_LOCATION)).validate(); Assert.assertFalse("Signature should be invalid if timestamp was taken after OCSP", validationResult.isValid()); - Assert.assertEquals(2, validationResult.getErrors().size()); + TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), + "Timestamp time is after OCSP response production time", + "The certificate is not related to a TSA/QTST!" + ); Assert.assertTrue("Validation result should contain " + TimestampAfterOCSPResponseTimeException.class.getSimpleName(), - validationResult.getErrors().get(1) instanceof TimestampAfterOCSPResponseTimeException); + validationResult.getErrors().stream().anyMatch(e -> e instanceof TimestampAfterOCSPResponseTimeException)); } @Test public void invalidTimestampMsgIsNotExistForASICE() { - Assert.assertEquals(1, this.openContainerByConfiguration(Paths.get(ASICE_LOCATION)).validate().getErrors().size()); + ContainerValidationResult validationResult = this.openContainerByConfiguration(Paths.get(ASICE_LOCATION)).validate(); + TestAssert.assertContainsExactSetOfErrors(validationResult.getErrors(), + "The certificate is not related to a TSA/QTST!" + ); } /* diff --git a/digidoc4j/src/test/java/org/digidoc4j/impl/pades/PadesValidationTest.java b/digidoc4j/src/test/java/org/digidoc4j/impl/pades/PadesValidationTest.java index e69230b9a..37ca274c7 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/impl/pades/PadesValidationTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/impl/pades/PadesValidationTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.impl.pades; import org.digidoc4j.AbstractTest; @@ -45,11 +55,14 @@ public void PadesT_shouldFail() { fromExistingFile("src/test/resources/prodFiles/invalid-containers/PadesProfileT.pdf").build(); SignatureValidationResult result = container.validate(); Assert.assertFalse(result.isValid()); - TestAssert.assertContainsError("The result of the LTV validation process is not acceptable to continue the process!", result.getErrors()); + TestAssert.assertContainsErrors(result.getErrors(), + "The certificate validation is not conclusive!", + "No acceptable revocation data for the certificate!" + ); } @Test - public void testValidPadesContainerWithTwoSignatures() { + public void PadesLTAndPadesB_shouldFail() { /* Given PDF contains two signatures from the same certificate : B and LT Only LT signature contains revocation aand somehow it gets included while validating B level signature @@ -57,7 +70,14 @@ public void testValidPadesContainerWithTwoSignatures() { Container container = ContainerBuilder.aContainer(Container.DocumentType.PADES).withConfiguration(Configuration.of(Configuration.Mode.PROD)). fromExistingFile("src/test/resources/prodFiles/valid-containers/hellopades-lt-b.pdf").build(); SignatureValidationResult result = container.validate(); - Assert.assertTrue(result.isValid()); + Assert.assertFalse(result.isValid()); + TestAssert.assertContainsErrors(result.getErrors(), + "The certificate validation is not conclusive!", + "The current time is not in the validity range of the signer's certificate!", + "The best-signature-time is not before the expiration date of the signing certificate!", + "The past signature validation is not conclusive!", + "The certificate is not related to a granted status!" + ); } @Test diff --git a/digidoc4j/src/test/java/org/digidoc4j/main/DigiDoc4JTest.java b/digidoc4j/src/test/java/org/digidoc4j/main/DigiDoc4JTest.java index 2a1634443..c0f98d100 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/main/DigiDoc4JTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/main/DigiDoc4JTest.java @@ -728,6 +728,8 @@ public void verifyEdoc() throws Exception { @Override public void checkAssertion() throws Exception { Assert.assertThat(stdOut.getLog(), StringContains.containsString("OCSP response production time is before timestamp time")); + Assert.assertThat(stdOut.getLog(), StringContains.containsString("Error: (Signature ID: S1) - Timestamp time is after OCSP response production time")); + Assert.assertThat(stdOut.getLog(), StringContains.containsString("Error: (Signature ID: S1) - The certificate is not related to a TSA/QTST!")); Assert.assertThat(stdOut.getLog(), StringContains.containsString("Signature has 2 validation errors")); Assert.assertThat(stdOut.getLog(), StringContains.containsString("Signature S1 is not valid")); } @@ -749,6 +751,8 @@ public void verifyEdocWithDss() throws Exception { @Override public void checkAssertion() throws Exception { Assert.assertThat(stdOut.getLog(), StringContains.containsString("OCSP response production time is before timestamp time")); + Assert.assertThat(stdOut.getLog(), StringContains.containsString("Error: (Signature ID: S1) - Timestamp time is after OCSP response production time")); + Assert.assertThat(stdOut.getLog(), StringContains.containsString("Error: (Signature ID: S1) - The certificate is not related to a TSA/QTST!")); Assert.assertThat(stdOut.getLog(), StringContains.containsString("Signature has 2 validation errors")); Assert.assertThat(stdOut.getLog(), StringContains.containsString("Validation finished. Container is NOT valid!")); } @@ -843,7 +847,7 @@ public void verifyBDocFullReport() throws Exception { this.systemExit.checkAssertionAfterwards(new Assertion() { @Override public void checkAssertion() throws Exception { - Assert.assertThat(stdOut.getLog(), StringContains.containsString("Type = REVOCATION. BBB_XCV_CCCBB_REV_ANS: " + + Assert.assertThat(stdOut.getLog(), StringContains.containsString( "The certificate chain for revocation data is not trusted, it does not contain a trust anchor")); } }); @@ -888,7 +892,7 @@ public void validateDetachedXades_withWrongDigestFile_shouldFail() throws Except "src/test/resources/testFiles/xades/test-bdoc-ts.xml"}; TestDigiDoc4JUtil.call(parameters); - Assert.assertThat(stdOut.getLog(), StringContains.containsString("The result of the LTV validation process is not acceptable to continue the process!")); + Assert.assertThat(stdOut.getLog(), StringContains.containsString("The reference data object is not intact!")); } @Test diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/CustomContainer.java b/digidoc4j/src/test/java/org/digidoc4j/test/CustomContainer.java index e78b0e788..5d2a0fc07 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/test/CustomContainer.java +++ b/digidoc4j/src/test/java/org/digidoc4j/test/CustomContainer.java @@ -1,33 +1,28 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.test; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.cert.X509Certificate; -import java.util.List; - import org.digidoc4j.Configuration; import org.digidoc4j.Container; import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.DataFile; -import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.Signature; -import org.digidoc4j.SignatureParameters; import org.digidoc4j.SignatureProfile; -import org.digidoc4j.SignatureToken; -import org.digidoc4j.SignedInfo; import org.digidoc4j.exceptions.NotYetImplementedException; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + /** * This class is used in unit tests for testing custom container creation. */ @@ -159,104 +154,9 @@ public DataFile getTimeStampToken() { throw new NotYetImplementedException(); } - @Override - public SignedInfo prepareSigning(X509Certificate signerCert) { - return null; - } - - @Override - public String getSignatureProfile() { - return null; - } - - @Override - public void setSignatureParameters(SignatureParameters signatureParameters) { - - } - - @Override - public DigestAlgorithm getDigestAlgorithm() { - return null; - } - - @Override - public void addRawSignature(byte[] signature) { - - } - - @Override - public void addRawSignature(InputStream signatureStream) { - - } - - @Override - public DataFile getDataFile(int index) { - return null; - } - - @Override - public int countDataFiles() { - return 0; - } - - @Override - public void removeDataFile(String fileName) { - - } - - @Override - public void removeSignature(int signatureId) { - - } - - @Override - public void save(String path) { - - } - @Override public void save(OutputStream out) { } - @Override - public Signature sign(SignatureToken signatureToken) { - return null; - } - - @Override - public Signature signRaw(byte[] rawSignature) { - return null; - } - - @Override - public Signature getSignature(int index) { - return null; - } - - @Override - public int countSignatures() { - return 0; - } - - @Override - public DocumentType getDocumentType() { - return null; - } - - @Override - public String getVersion() { - return null; - } - - @Override - public void extendTo(SignatureProfile profile) { - - } - - @Override - public void setSignatureProfile(SignatureProfile profile) { - - } - } diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableDataLoader.java b/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableDataLoader.java index cec84cd7f..c07d0c183 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableDataLoader.java +++ b/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableDataLoader.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.test; import eu.europa.esig.dss.model.DSSException; @@ -12,85 +22,85 @@ public class MockConfigurableDataLoader implements DataLoader { - @FunctionalInterface - public interface Getter { - byte[] get(String url, Boolean refresh) throws DSSException; - } - - @FunctionalInterface - public interface Poster { - byte[] post(String url, byte[] content) throws DSSException; - } - - private Getter getter = (url, refresh) -> { - throw new UnsupportedOperationException("GET operations not configured"); - }; - private Poster poster = (url, content) -> { - throw new UnsupportedOperationException("POST operations not configured"); - }; - - @Override - public byte[] get(String url) throws DSSException { - return getter.get(url, null); - } - - @Override - public DataAndUrl get(List urlStrings) throws DSSException { - if (Utils.isCollectionEmpty(urlStrings)) { - throw new DSSException("Cannot process the GET call. List of URLs is empty!"); - } else { - Map exceptions = new HashMap(); - for (String url : urlStrings) { - try { - byte[] bytes = getter.get(url, null); - if (!Utils.isArrayEmpty(bytes)) { - return new DataAndUrl(bytes, url); - } - } catch (Exception e) { - exceptions.put(url, e); - } - } - throw new DSSDataLoaderMultipleException(exceptions); + @FunctionalInterface + public interface Getter { + byte[] get(String url, Boolean refresh) throws DSSException; + } + + @FunctionalInterface + public interface Poster { + byte[] post(String url, byte[] content) throws DSSException; + } + + private Getter getter = (url, refresh) -> { + throw new UnsupportedOperationException("GET operations not configured"); + }; + private Poster poster = (url, content) -> { + throw new UnsupportedOperationException("POST operations not configured"); + }; + + @Override + public byte[] get(String url) throws DSSException { + return getter.get(url, null); + } + + @Override + public DataAndUrl get(List urlStrings) throws DSSException { + if (Utils.isCollectionEmpty(urlStrings)) { + throw new DSSException("Cannot process the GET call. List of URLs is empty!"); + } else { + Map exceptions = new HashMap(); + for (String url : urlStrings) { + try { + byte[] bytes = getter.get(url, null); + if (!Utils.isArrayEmpty(bytes)) { + return new DataAndUrl(url, bytes); + } + } catch (Exception e) { + exceptions.put(url, e); } + } + throw new DSSDataLoaderMultipleException(exceptions); } - - @Override - public byte[] get(String url, boolean refresh) throws DSSException { - return getter.get(url, refresh); - } - - @Override - public byte[] post(String url, byte[] content) throws DSSException { - return poster.post(url, content); - } - - @Override - public void setContentType(String contentType) {} - - public Getter getGetter() { - return getter; - } - - public void setGetter(Getter getter) { - this.getter = Objects.requireNonNull(getter); - } - - public MockConfigurableDataLoader withGetter(Getter getter) { - setGetter(getter); - return this; - } - - public Poster getPoster() { - return poster; - } - - public void setPoster(Poster poster) { - this.poster = Objects.requireNonNull(poster); - } - - public MockConfigurableDataLoader withPoster(Poster poster) { - setPoster(poster); - return this; - } + } + + @Override + public byte[] get(String url, boolean refresh) throws DSSException { + return getter.get(url, refresh); + } + + @Override + public byte[] post(String url, byte[] content) throws DSSException { + return poster.post(url, content); + } + + @Override + public void setContentType(String contentType) {} + + public Getter getGetter() { + return getter; + } + + public void setGetter(Getter getter) { + this.getter = Objects.requireNonNull(getter); + } + + public MockConfigurableDataLoader withGetter(Getter getter) { + setGetter(getter); + return this; + } + + public Poster getPoster() { + return poster; + } + + public void setPoster(Poster poster) { + this.poster = Objects.requireNonNull(poster); + } + + public MockConfigurableDataLoader withPoster(Poster poster) { + setPoster(poster); + return this; + } } diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableFileLoader.java b/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableFileLoader.java new file mode 100644 index 000000000..c3316b2be --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/test/MockConfigurableFileLoader.java @@ -0,0 +1,74 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.test; + +import eu.europa.esig.dss.model.DSSDocument; +import eu.europa.esig.dss.model.DSSException; +import eu.europa.esig.dss.spi.client.http.DSSFileLoader; + +import java.util.Objects; + +public class MockConfigurableFileLoader implements DSSFileLoader { + + @FunctionalInterface + public interface DocumentGetter { + DSSDocument getDocument(String url) throws DSSException; + } + + @FunctionalInterface + public interface Remover { + boolean remove(String url); + } + + private DocumentGetter getter = (url) -> { + throw new UnsupportedOperationException("GET operations not configured"); + }; + private Remover remover = (url) -> { + throw new UnsupportedOperationException("REMOVE operations not configured"); + }; + + @Override + public DSSDocument getDocument(String url) throws DSSException { + return getter.getDocument(url); + } + + @Override + public boolean remove(String url) { + return remover.remove(url); + } + + public DocumentGetter getDocumentGetter() { + return getter; + } + + public void setDocumentGetter(DocumentGetter getter) { + this.getter = Objects.requireNonNull(getter); + } + + public MockConfigurableFileLoader withDocumentGetter(DocumentGetter getter) { + setDocumentGetter(getter); + return this; + } + + public Remover getRemover() { + return remover; + } + + public void setRemover(Remover remover) { + this.remover = Objects.requireNonNull(remover); + } + + public MockConfigurableFileLoader withRemover(Remover remover) { + setRemover(remover); + return this; + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/MockSignature.java b/digidoc4j/src/test/java/org/digidoc4j/test/MockSignature.java index 932a505fe..40bdac0fe 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/test/MockSignature.java +++ b/digidoc4j/src/test/java/org/digidoc4j/test/MockSignature.java @@ -1,29 +1,26 @@ /* DigiDoc4J library -* -* This software is released under either the GNU Library General Public -* License (see LICENSE.LGPL). -* -* Note that the only valid version of the LGPL license as far as this -* project is concerned is the original GNU Library General Public License -* Version 2.1, February 1999 -*/ + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ package org.digidoc4j.test; -import java.net.URI; -import java.util.Date; -import java.util.List; - import org.digidoc4j.Signature; import org.digidoc4j.SignatureProfile; import org.digidoc4j.ValidationResult; import org.digidoc4j.X509Cert; -import org.digidoc4j.exceptions.DigiDoc4JException; + +import java.util.Date; +import java.util.List; /** * Created by Janar Rahumeel (CGI Estonia) */ - public class MockSignature implements Signature { @Override @@ -56,21 +53,11 @@ public X509Cert getOCSPCertificate() { return null; } - @Override - public String getPolicy() { - return null; - } - @Override public String getPostalCode() { return null; } - @Override - public Date getProducedAt() { - return null; - } - @Override public Date getOCSPResponseCreationTime() { return null; @@ -111,16 +98,6 @@ public Date getClaimedSigningTime() { return null; } - @Override - public Date getSigningTime() { - return null; - } - - @Override - public URI getSignaturePolicyURI() { - return null; - } - @Override public String getStateOrProvince() { return null; @@ -136,19 +113,9 @@ public ValidationResult validateSignature() { return null; } - @Override - public List validate() { - return null; - } - @Override public byte[] getAdESSignature() { return new byte[0]; } - @Override - public byte[] getRawSignature() { - return new byte[0]; - } - } diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/MockSignatureBuilder.java b/digidoc4j/src/test/java/org/digidoc4j/test/MockSignatureBuilder.java index 6a0f85601..cf38deb18 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/test/MockSignatureBuilder.java +++ b/digidoc4j/src/test/java/org/digidoc4j/test/MockSignatureBuilder.java @@ -58,7 +58,8 @@ public Configuration getConfiguration() { @Override public SignatureParameters getSignatureParameters() { SignatureParameters signatureParameters = new SignatureParameters(); - signatureParameters.setDigestAlgorithm(DigestAlgorithm.SHA512); + signatureParameters.setSignatureDigestAlgorithm(DigestAlgorithm.SHA512); + signatureParameters.setDataFileDigestAlgorithm(DigestAlgorithm.SHA512); return signatureParameters; } }; diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/MockTSLRefreshCallback.java b/digidoc4j/src/test/java/org/digidoc4j/test/MockTSLRefreshCallback.java new file mode 100644 index 000000000..7303d6e7b --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/test/MockTSLRefreshCallback.java @@ -0,0 +1,42 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + +package org.digidoc4j.test; + +import eu.europa.esig.dss.spi.tsl.TLValidationJobSummary; +import org.digidoc4j.TSLRefreshCallback; + +import java.util.Objects; + +public class MockTSLRefreshCallback implements TSLRefreshCallback { + + private final boolean valueToReturn; + private final RuntimeException exceptionToThrow; + + public MockTSLRefreshCallback(boolean valueToReturn) { + this.valueToReturn = valueToReturn; + this.exceptionToThrow = null; + } + + public MockTSLRefreshCallback(RuntimeException exceptionToThrow) { + this.exceptionToThrow = Objects.requireNonNull(exceptionToThrow); + this.valueToReturn = false; + } + + @Override + public boolean ensureTSLState(TLValidationJobSummary summary) { + if (exceptionToThrow != null) { + throw exceptionToThrow; + } else { + return valueToReturn; + } + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/test/TestAssert.java b/digidoc4j/src/test/java/org/digidoc4j/test/TestAssert.java index ebf49b2fb..9e4391eb1 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/test/TestAssert.java +++ b/digidoc4j/src/test/java/org/digidoc4j/test/TestAssert.java @@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils; import org.digidoc4j.Configuration; import org.digidoc4j.Container; +import org.digidoc4j.ContainerValidationResult; import org.digidoc4j.Signature; import org.digidoc4j.exceptions.DigiDoc4JException; import org.digidoc4j.impl.SKOnlineOCSPSource; @@ -82,22 +83,69 @@ public static void assertContainsError(String expectedError, List was not found", expectedError)); } - public static void assertContainsExactSetOfErrors(List errors, String... expectedErrors) { - Assert.assertEquals( - String.format("Expected %d errors, but found %d", expectedErrors.length, errors.size()), - expectedErrors.length, errors.size() - ); - for (String expectedError : expectedErrors) { - assertContainsError(expectedError, errors); + public static void assertContainsErrors(List errors, String... errorsToExpect) { + if (errorsToExpect.length == 0 || errorListContainsAllExpectedStrings(errors, errorsToExpect)) { + return; } + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Expected to find errors containing the following strings:"); + for (String expectedError : errorsToExpect) { + stringBuilder.append(System.lineSeparator()).append('\t').append(expectedError); + } + if (errors.size() > 0) { + stringBuilder.append(System.lineSeparator()).append("Actual errors found (").append(errors.size()).append("):"); + for (DigiDoc4JException exception : errors) { + stringBuilder.append(System.lineSeparator()).append('\t').append(exception); + } + } else { + stringBuilder.append("No errors found!"); + } + Assert.fail(stringBuilder.toString()); + } + + public static void assertContainsExactSetOfErrors(List errors, String... allExpectedErrors) { + assertContainsExactNumberOfErrorsAndAllExpectedErrorMessages(errors, allExpectedErrors.length, allExpectedErrors); + } + + public static void assertContainsExactNumberOfErrorsAndAllExpectedErrorMessages(List errors, int expectedNumberOfErrors, String... errorsToExpect) { + if (errors.size() == expectedNumberOfErrors && errorListContainsAllExpectedStrings(errors, errorsToExpect)) { + return; + } + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Expected ").append(expectedNumberOfErrors).append(" errors") + .append(errors.size() == expectedNumberOfErrors ? " and" : ", but") + .append(" found ").append(errors.size()); + if (errorsToExpect.length > 0) { + stringBuilder.append(System.lineSeparator()).append("List of strings expected to be contained in error messages:"); + for (String expectedError : errorsToExpect) { + stringBuilder.append(System.lineSeparator()).append('\t').append(expectedError); + } + } + if (errors.size() > 0) { + stringBuilder.append(System.lineSeparator()).append("Actual errors found (").append(errors.size()).append("):"); + for (DigiDoc4JException exception : errors) { + stringBuilder.append(System.lineSeparator()).append('\t').append(exception); + } + } + Assert.fail(stringBuilder.toString()); } public static void assertSignatureMetadataContainsFileName(Signature signature, String fileName) { Assert.assertNotNull(TestAssert.findSignedFile(signature, fileName)); } + public static void assertContainerIsValid(ContainerValidationResult containerValidationResult) { + if (!containerValidationResult.isValid()) { + StringBuilder stringBuilder = new StringBuilder("Container is invalid"); + for (DigiDoc4JException exception : containerValidationResult.getErrors()) { + stringBuilder.append(System.lineSeparator()).append('\t').append(exception); + } + Assert.fail(stringBuilder.toString()); + } + } + public static void assertContainerIsValid(Container container) { - Assert.assertTrue("Container is invalid", container.validate().isValid()); + assertContainerIsValid(container.validate()); } public static void assertContainerIsInvalid(Container container) { @@ -161,4 +209,22 @@ private static void assertContainerStream(InputStream stream) throws IOException Assert.assertTrue(IOUtils.toByteArray(stream).length > 0); } + private static boolean errorListContainsAllExpectedStrings(List errorList, String... expectedStrings) { + for (String expectedString : expectedStrings) { + if (!errorListContainsExpectedString(errorList, expectedString)) { + return false; + } + } + return true; + } + + private static boolean errorListContainsExpectedString(List errorList, String expectedString) { + for (DigiDoc4JException error : errorList) { + if (error != null && error.toString().contains(expectedString)) { + return true; + } + } + return false; + } + } diff --git a/digidoc4j/src/test/java/org/digidoc4j/utils/DigestUtilsTest.java b/digidoc4j/src/test/java/org/digidoc4j/utils/DigestUtilsTest.java new file mode 100644 index 000000000..c4e541940 --- /dev/null +++ b/digidoc4j/src/test/java/org/digidoc4j/utils/DigestUtilsTest.java @@ -0,0 +1,51 @@ +package org.digidoc4j.utils; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.digidoc4j.DigestAlgorithm; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.security.*; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; + +public class DigestUtilsTest { + + @BeforeClass + public static void setUpStatic() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Test + public void ecKeySize224_returnsSha512() throws GeneralSecurityException { + KeyPair keyPair = generateEcKeyPair("secp224r1"); + Assert.assertEquals(DigestAlgorithm.SHA512, DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) keyPair.getPublic())); + } + + @Test + public void ecKeySize256_returnsSha256() throws GeneralSecurityException { + KeyPair keyPair = generateEcKeyPair("secp256r1"); + Assert.assertEquals(DigestAlgorithm.SHA256, DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) keyPair.getPublic())); + } + + @Test + public void ecKeySize384_returnsSha384() throws GeneralSecurityException { + KeyPair keyPair = generateEcKeyPair("secp384r1"); + Assert.assertEquals(DigestAlgorithm.SHA384, DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) keyPair.getPublic())); + } + + @Test + public void ecKeySize521_returnsSha512() throws GeneralSecurityException { + KeyPair keyPair = generateEcKeyPair("secp521r1"); + Assert.assertEquals(DigestAlgorithm.SHA512, DigestUtils.getRecommendedSignatureDigestAlgorithm((ECPublicKey) keyPair.getPublic())); + } + + private KeyPair generateEcKeyPair(String algo) throws GeneralSecurityException { + ECGenParameterSpec ecGenSpec = new ECGenParameterSpec(algo); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC"); + keyPairGenerator.initialize(ecGenSpec, new SecureRandom()); + return keyPairGenerator.generateKeyPair(); + } + +} diff --git a/digidoc4j/src/test/java/org/digidoc4j/utils/ResourceUtilsTest.java b/digidoc4j/src/test/java/org/digidoc4j/utils/ResourceUtilsTest.java index 7133e58e8..b75ff4246 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/utils/ResourceUtilsTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/utils/ResourceUtilsTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.utils; import org.junit.Assert; @@ -46,33 +56,51 @@ public void getResourceWithClasspathPrefix() { Assert.assertNotNull(inputStream); } - @Test(expected = IllegalArgumentException.class) - public void getResourceWithInvalidClasspathPrefixPath() { - ResourceUtils.getResource("classpath:test.xml"); + @Test + public void getClasspathResourceWithoutPrefix() { + InputStream inputStream = ResourceUtils.getResource("testFiles/keystores/truststore.jks"); + Assert.assertNotNull(inputStream); + } + + @Test + public void getNonExistingResourceWithClasspathPrefixPath() { + IllegalArgumentException caughtException = Assert.assertThrows( + IllegalArgumentException.class, + () -> ResourceUtils.getResource("classpath:test.xml") + ); + Assert.assertEquals("Classpath resource not found: test.xml", caughtException.getMessage()); } @Test public void getResourceWithFilePrefix() { Path path = Paths.get("target/test-classes/testFiles/keystores/truststore.jks"); - InputStream inputStream = ResourceUtils.getResource("file:" + path.toAbsolutePath().toString()); + InputStream inputStream = ResourceUtils.getResource("file:" + path.toAbsolutePath()); Assert.assertNotNull(inputStream); } - @Test(expected = IllegalArgumentException.class) - public void getResourceWithInvalidFilePrefix() { - ResourceUtils.getResource("file:test.xml"); - } - @Test - public void getResourceWithoutPrefix() { + public void getFileResourceWithoutPrefix() { Path path = Paths.get("target/test-classes/testFiles/keystores/truststore.jks"); InputStream inputStream = ResourceUtils.getResource(path.toAbsolutePath().toString()); Assert.assertNotNull(inputStream); } - @Test(expected = IllegalArgumentException.class) - public void getResourceWithInvalidPath() { - ResourceUtils.getResource("test.xml"); + @Test + public void getNonExistingResourceWithFilePrefix() { + IllegalArgumentException caughtException = Assert.assertThrows( + IllegalArgumentException.class, + () -> ResourceUtils.getResource("file:test.xml") + ); + Assert.assertEquals("File resource not found: test.xml", caughtException.getMessage()); + } + + @Test + public void getNonExistingResource() { + IllegalArgumentException caughtException = Assert.assertThrows( + IllegalArgumentException.class, + () -> ResourceUtils.getResource("test.xml") + ); + Assert.assertEquals("Resource not found: test.xml", caughtException.getMessage()); } } \ No newline at end of file diff --git a/digidoc4j/src/test/java/org/digidoc4j/utils/ZipEntryInputStreamTest.java b/digidoc4j/src/test/java/org/digidoc4j/utils/ZipEntryInputStreamTest.java index b33bcec6e..ea0acdfbf 100644 --- a/digidoc4j/src/test/java/org/digidoc4j/utils/ZipEntryInputStreamTest.java +++ b/digidoc4j/src/test/java/org/digidoc4j/utils/ZipEntryInputStreamTest.java @@ -1,3 +1,13 @@ +/* DigiDoc4J library + * + * This software is released under either the GNU Library General Public + * License (see LICENSE.LGPL). + * + * Note that the only valid version of the LGPL license as far as this + * project is concerned is the original GNU Library General Public License + * Version 2.1, February 1999 + */ + package org.digidoc4j.utils; import org.junit.Assert; @@ -14,229 +24,214 @@ @RunWith(MockitoJUnitRunner.class) public class ZipEntryInputStreamTest { - @Mock - private ZipInputStream zipInputStream; - - private ZipEntryInputStream zipEntryInputStream; - - @Before - public void setUp() { - zipEntryInputStream = new ZipEntryInputStream(zipInputStream, null); - Mockito.verifyZeroInteractions(zipInputStream); - } - - - @Test - public void availableShouldDelegateToZipInputStreamAvailable() throws IOException { - Mockito.doReturn(7).when(zipInputStream).available(); - - int result = zipEntryInputStream.available(); - Assert.assertEquals(7, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).available(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void availableShouldPassOnExceptionThrownByZipInputStreamAvailable() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).available(); - - try { - zipEntryInputStream.available(); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).available(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void closeShouldDelegateToZipInputStreamCloseEntry() throws IOException { - zipEntryInputStream.close(); - - Mockito.verify(zipInputStream, Mockito.times(1)).closeEntry(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void closeShouldPassOnExceptionThrownByZipInputStreamAvailable() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).closeEntry(); - - try { - zipEntryInputStream.close(); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).closeEntry(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void markShouldDelegateToZipInputStreamMark() { - zipEntryInputStream.mark(7); - - Mockito.verify(zipInputStream, Mockito.times(1)).mark(7); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void markSupportedShouldDelegateToZipInputStreamMarkSupported() throws IOException { - Mockito.doReturn(true).when(zipInputStream).markSupported(); - - boolean result = zipEntryInputStream.markSupported(); - Assert.assertEquals(true, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).markSupported(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void readShouldDelegateToZipInputStreamRead() throws IOException { - Mockito.doReturn(7).when(zipInputStream).read(); - - int result = zipEntryInputStream.read(); - Assert.assertEquals(7, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).read(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void readShouldPassOnExceptionThrownByZipInputStreamRead() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).read(); - - try { - zipEntryInputStream.read(); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).read(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } + @Mock + private ZipInputStream zipInputStream; + + private ZipEntryInputStream zipEntryInputStream; + @Before + public void setUp() { + zipEntryInputStream = new ZipEntryInputStream(zipInputStream, null); + Mockito.verifyNoInteractions(zipInputStream); + } + + @Test + public void availableShouldDelegateToZipInputStreamAvailable() throws IOException { + Mockito.doReturn(7).when(zipInputStream).available(); + + int result = zipEntryInputStream.available(); + Assert.assertEquals(7, result); - @Test - public void readWithArrayShouldDelegateToZipInputStreamReadWithArray() throws IOException { - Mockito.doReturn(7).when(zipInputStream).read(Mockito.any(byte[].class)); - byte[] arrayOfBytes = new byte[32]; - - int result = zipEntryInputStream.read(arrayOfBytes); - Assert.assertEquals(7, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void readWithArrayShouldPassOnExceptionThrownByZipInputStreamReadWithArray() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).read(Mockito.any(byte[].class)); - byte[] arrayOfBytes = new byte[32]; - - try { - zipEntryInputStream.read(arrayOfBytes); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void readWithArrayAndBoundsShouldDelegateToZipInputStreamReadWithArrayAndBounds() throws IOException { - Mockito.doReturn(7).when(zipInputStream).read(Mockito.any(byte[].class), Mockito.anyInt(), Mockito.anyInt()); - byte[] arrayOfBytes = new byte[32]; - - int result = zipEntryInputStream.read(arrayOfBytes, 3, 9); - Assert.assertEquals(7, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes, 3, 9); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void readWithArrayAndBoundsShouldPassOnExceptionThrownByZipInputStreamReadWithArrayAndBounds() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).read(Mockito.any(byte[].class), Mockito.anyInt(), Mockito.anyInt()); - byte[] arrayOfBytes = new byte[32]; - - try { - zipEntryInputStream.read(arrayOfBytes, 3, 9); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes, 3, 9); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void resetShouldDelegateToZipInputStreamReset() throws IOException { - zipEntryInputStream.reset(); - - Mockito.verify(zipInputStream, Mockito.times(1)).reset(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void resetShouldPassOnExceptionThrownByZipInputStreamReset() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).reset(); - - try { - zipEntryInputStream.reset(); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).reset(); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - - @Test - public void skipShouldDelegateToZipInputStreamSkip() throws IOException { - Mockito.doReturn(9L).when(zipInputStream).skip(Mockito.anyLong()); - - long result = zipEntryInputStream.skip(13L); - Assert.assertEquals(9L, result); - - Mockito.verify(zipInputStream, Mockito.times(1)).skip(13L); - Mockito.verifyNoMoreInteractions(zipInputStream); - } - - @Test - public void skipShouldPassOnExceptionThrownByZipInputStreamSkip() throws IOException { - IOException ioException = new IOException("Some ZipInputStream exception"); - Mockito.doThrow(ioException).when(zipInputStream).skip(13L); - - try { - zipEntryInputStream.skip(13L); - Assert.fail("Should not reach here"); - } catch (IOException exception) { - Assert.assertEquals(ioException.getMessage(), exception.getMessage()); - } - - Mockito.verify(zipInputStream, Mockito.times(1)).skip(13L); - Mockito.verifyNoMoreInteractions(zipInputStream); - } + Mockito.verify(zipInputStream, Mockito.times(1)).available(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void availableShouldPassOnExceptionThrownByZipInputStreamAvailable() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).available(); + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.available() + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).available(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void closeShouldDelegateToZipInputStreamCloseEntry() throws IOException { + zipEntryInputStream.close(); + + Mockito.verify(zipInputStream, Mockito.times(1)).closeEntry(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void closeShouldPassOnExceptionThrownByZipInputStreamAvailable() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).closeEntry(); + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.close() + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).closeEntry(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void markShouldDelegateToZipInputStreamMark() { + zipEntryInputStream.mark(7); + + Mockito.verify(zipInputStream, Mockito.times(1)).mark(7); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void markSupportedShouldDelegateToZipInputStreamMarkSupported() throws IOException { + Mockito.doReturn(true).when(zipInputStream).markSupported(); + + boolean result = zipEntryInputStream.markSupported(); + + Assert.assertTrue(result); + Mockito.verify(zipInputStream, Mockito.times(1)).markSupported(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readShouldDelegateToZipInputStreamRead() throws IOException { + Mockito.doReturn(7).when(zipInputStream).read(); + + int result = zipEntryInputStream.read(); + + Assert.assertEquals(7, result); + Mockito.verify(zipInputStream, Mockito.times(1)).read(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readShouldPassOnExceptionThrownByZipInputStreamRead() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).read(); + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.read() + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).read(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readWithArrayShouldDelegateToZipInputStreamReadWithArray() throws IOException { + Mockito.doReturn(7).when(zipInputStream).read(Mockito.any(byte[].class)); + byte[] arrayOfBytes = new byte[32]; + + int result = zipEntryInputStream.read(arrayOfBytes); + + Assert.assertEquals(7, result); + Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readWithArrayShouldPassOnExceptionThrownByZipInputStreamReadWithArray() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).read(Mockito.any(byte[].class)); + byte[] arrayOfBytes = new byte[32]; + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.read(arrayOfBytes) + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readWithArrayAndBoundsShouldDelegateToZipInputStreamReadWithArrayAndBounds() throws IOException { + Mockito.doReturn(7).when(zipInputStream).read(Mockito.any(byte[].class), Mockito.anyInt(), Mockito.anyInt()); + byte[] arrayOfBytes = new byte[32]; + + int result = zipEntryInputStream.read(arrayOfBytes, 3, 9); + + Assert.assertEquals(7, result); + Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes, 3, 9); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void readWithArrayAndBoundsShouldPassOnExceptionThrownByZipInputStreamReadWithArrayAndBounds() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).read(Mockito.any(byte[].class), Mockito.anyInt(), Mockito.anyInt()); + byte[] arrayOfBytes = new byte[32]; + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.read(arrayOfBytes, 3, 9) + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).read(arrayOfBytes, 3, 9); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void resetShouldDelegateToZipInputStreamReset() throws IOException { + zipEntryInputStream.reset(); + + Mockito.verify(zipInputStream, Mockito.times(1)).reset(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void resetShouldPassOnExceptionThrownByZipInputStreamReset() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).reset(); + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.reset() + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).reset(); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void skipShouldDelegateToZipInputStreamSkip() throws IOException { + Mockito.doReturn(9L).when(zipInputStream).skip(Mockito.anyLong()); + + long result = zipEntryInputStream.skip(13L); + + Assert.assertEquals(9L, result); + Mockito.verify(zipInputStream, Mockito.times(1)).skip(13L); + Mockito.verifyNoMoreInteractions(zipInputStream); + } + + @Test + public void skipShouldPassOnExceptionThrownByZipInputStreamSkip() throws IOException { + IOException ioException = new IOException("Some ZipInputStream exception"); + Mockito.doThrow(ioException).when(zipInputStream).skip(13L); + + IOException caughtException = Assert.assertThrows( + IOException.class, + () -> zipEntryInputStream.skip(13L) + ); + + Assert.assertSame(ioException, caughtException); + Mockito.verify(zipInputStream, Mockito.times(1)).skip(13L); + Mockito.verifyNoMoreInteractions(zipInputStream); + } } \ No newline at end of file diff --git a/digidoc4j/src/test/resources/prodFiles/truststores/lotl-pivot300-truststore.p12 b/digidoc4j/src/test/resources/prodFiles/truststores/lotl-pivot300-truststore.p12 new file mode 100644 index 000000000..9cbca7a69 Binary files /dev/null and b/digidoc4j/src/test/resources/prodFiles/truststores/lotl-pivot300-truststore.p12 differ diff --git a/digidoc4j/src/test/resources/prodFiles/valid-containers/volikiri.asice b/digidoc4j/src/test/resources/prodFiles/valid-containers/volikiri.asice deleted file mode 100644 index 3bd9fe311..000000000 Binary files a/digidoc4j/src/test/resources/prodFiles/valid-containers/volikiri.asice and /dev/null differ diff --git a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_fail_level.xml b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_fail_level.xml index b950855b2..d4a38f553 100644 --- a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_fail_level.xml +++ b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_fail_level.xml @@ -29,7 +29,7 @@ - + nonRepudiation @@ -66,7 +66,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -315,7 +315,7 @@ - + diff --git a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_warn_level.xml b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_warn_level.xml index c8eca8901..eba808696 100644 --- a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_warn_level.xml +++ b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_all_warn_level.xml @@ -29,7 +29,7 @@ - + nonRepudiation @@ -66,7 +66,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -315,7 +315,7 @@ - + diff --git a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_version_fail.xml b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_version_fail.xml index fc7b92b18..f4decb184 100644 --- a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_version_fail.xml +++ b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_version_fail.xml @@ -29,7 +29,7 @@ - + nonRepudiation @@ -66,7 +66,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -315,7 +315,7 @@ - + diff --git a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_well_signed_fail.xml b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_well_signed_fail.xml index be51a55f1..a6d3b72f2 100644 --- a/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_well_signed_fail.xml +++ b/digidoc4j/src/test/resources/testFiles/constraints/eIDAS_test_constraint_well_signed_fail.xml @@ -29,7 +29,7 @@ - + nonRepudiation @@ -66,7 +66,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -315,7 +315,7 @@ - + diff --git a/digidoc4j/src/test/resources/testFiles/constraints/moved_constraint.xml b/digidoc4j/src/test/resources/testFiles/constraints/moved_constraint.xml index d06cb9665..a34fa63a4 100644 --- a/digidoc4j/src/test/resources/testFiles/constraints/moved_constraint.xml +++ b/digidoc4j/src/test/resources/testFiles/constraints/moved_constraint.xml @@ -29,7 +29,7 @@ - + nonRepudiation @@ -66,7 +66,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -315,7 +315,7 @@ - + diff --git a/digidoc4j/src/test/resources/testFiles/invalid-containers/space-in-datafile-name-encoded-as-plus-in-signature.asice b/digidoc4j/src/test/resources/testFiles/invalid-containers/space-in-datafile-name-encoded-as-plus-in-signature.asice new file mode 100644 index 000000000..ce134d824 Binary files /dev/null and b/digidoc4j/src/test/resources/testFiles/invalid-containers/space-in-datafile-name-encoded-as-plus-in-signature.asice differ diff --git a/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-percent-encoded-in-signature.asice b/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-percent-encoded-in-signature.asice new file mode 100644 index 000000000..3da74b80b Binary files /dev/null and b/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-percent-encoded-in-signature.asice differ diff --git a/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-unencoded-in-signature.asice b/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-unencoded-in-signature.asice new file mode 100644 index 000000000..631d5c19f Binary files /dev/null and b/digidoc4j/src/test/resources/testFiles/valid-containers/plus-in-datafile-name-unencoded-in-signature.asice differ diff --git a/digidoc4j/src/test/resources/testFiles/valid-containers/space-in-datafile-name-percent-encoded-in-signature.asice b/digidoc4j/src/test/resources/testFiles/valid-containers/space-in-datafile-name-percent-encoded-in-signature.asice new file mode 100644 index 000000000..52528d0be Binary files /dev/null and b/digidoc4j/src/test/resources/testFiles/valid-containers/space-in-datafile-name-percent-encoded-in-signature.asice differ diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc4j_test_conf_territories_lists.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc4j_test_conf_territories_lists.yaml new file mode 100644 index 000000000..736bf90fd --- /dev/null +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc4j_test_conf_territories_lists.yaml @@ -0,0 +1,8 @@ +REQUIRED_TERRITORIES: + - IE + - LV + +TRUSTED_TERRITORIES: + - AU + - NZ + - AR diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml index 9abbaa8ee..136f104b4 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_all_optional_settings.yaml @@ -17,15 +17,24 @@ SIGN_OCSP_REQUESTS: false TSP_SOURCE: TEST_TSP_SOURCE VALIDATION_POLICY: TEST_VALIDATION_POLICY DIGIDOC_DF_CACHE_DIR: TEST_DIGIDOC_DF_CACHE_DIR +LOTL_LOCATION: TEST_LOTL_LOCATION +LOTL_TRUSTSTORE_PATH: TEST_LOTL_TRUSTSTORE_PATH +LOTL_TRUSTSTORE_TYPE: TEST_LOTL_TRUSTSTORE_TYPE +LOTL_TRUSTSTORE_PASSWORD: TEST_LOTL_TRUSTSTORE_PASSWORD +LOTL_PIVOT_SUPPORT_ENABLED: true TSL_LOCATION: TEST_TSL_LOCATION +TSL_KEYSTORE_LOCATION: TEST_TSL_KEYSTORE_LOCATION +TSL_KEYSTORE_PASSWORD: TEST_TSL_KEYSTORE_PASSWORD REVOCATION_AND_TIMESTAMP_DELTA_IN_MINUTES: 1337 TSL_CACHE_EXPIRATION_TIME: 86400000 HTTP_PROXY_HOST: cache.noile.ee HTTP_PROXY_PORT: 8080 +HTTP_PROXY_USER: plainProxyMan +HTTP_PROXY_PASSWORD: plainProxyPass HTTPS_PROXY_HOST: secure.noile.ee HTTPS_PROXY_PORT: 8443 -HTTP_PROXY_USER: proxyMan -HTTP_PROXY_PASSWORD: proxyPass +HTTPS_PROXY_USER: secureProxyMan +HTTPS_PROXY_PASSWORD: secureProxyPass SSL_KEYSTORE_PATH: sslKeystorePath SSL_KEYSTORE_TYPE: sslKeystoreType SSL_KEYSTORE_PASSWORD: sslKeystorePassword @@ -36,10 +45,12 @@ SSL_PROTOCOL: sslProtocol SUPPORTED_SSL_PROTOCOLS: sslProtocol1, sslProtocol2, sslProtocol3 SUPPORTED_SSL_CIPHER_SUITES: sslCipherSuite1, sslCipherSuite2 TRUSTED_TERRITORIES: NZ, AU, BR +REQUIRED_TERRITORIES: GB, LT ALLOWED_OCSP_RESPONDERS_FOR_TM: SK OCSP RESPONDER 2011, ESTEID-SK 2007 OCSP RESPONDER, EID-SK 2007 OCSP RESPONDER ALLOWED_TS_AND_OCSP_RESPONSE_DELTA_IN_MINUTES: 1 SIGNATURE_PROFILE: LT_TM SIGNATURE_DIGEST_ALGORITHM: SHA512 +DATAFILE_DIGEST_ALGORITHM: SHA512 PREFER_AIA_OCSP: true ZIP_COMPRESSION_RATIO_CHECK_THRESHOLD_IN_BYTES: 73 MAX_ALLOWED_ZIP_COMPRESSION_RATIO: 37 @@ -61,10 +72,12 @@ DIGIDOC_CAS: TSL_HTTP_PROXY_HOST: TSL.cache.noile.ee TSL_HTTP_PROXY_PORT: 80800 +TSL_HTTP_PROXY_USER: TSL-plainProxyMan +TSL_HTTP_PROXY_PASSWORD: TSL-plainProxyPass TSL_HTTPS_PROXY_HOST: TSL.secure.noile.ee TSL_HTTPS_PROXY_PORT: 84430 -TSL_HTTP_PROXY_USER: TSL-proxyMan -TSL_HTTP_PROXY_PASSWORD: TSL-proxyPass +TSL_HTTPS_PROXY_USER: TSL-secureProxyMan +TSL_HTTPS_PROXY_PASSWORD: TSL-secureProxyPass TSL_SSL_KEYSTORE_PATH: TSL-sslKeystorePath TSL_SSL_KEYSTORE_TYPE: TSL-sslKeystoreType TSL_SSL_KEYSTORE_PASSWORD: TSL-sslKeystorePassword @@ -77,10 +90,12 @@ TSL_SUPPORTED_SSL_CIPHER_SUITES: TSL-sslCipherSuite1, TSL-sslCipherSuite2 OCSP_HTTP_PROXY_HOST: OCSP.cache.noile.ee OCSP_HTTP_PROXY_PORT: 80801 +OCSP_HTTP_PROXY_USER: OCSP-plainProxyMan +OCSP_HTTP_PROXY_PASSWORD: OCSP-plainProxyPass OCSP_HTTPS_PROXY_HOST: OCSP.secure.noile.ee OCSP_HTTPS_PROXY_PORT: 84431 -OCSP_HTTP_PROXY_USER: OCSP-proxyMan -OCSP_HTTP_PROXY_PASSWORD: OCSP-proxyPass +OCSP_HTTPS_PROXY_USER: OCSP-secureProxyMan +OCSP_HTTPS_PROXY_PASSWORD: OCSP-secureProxyPass OCSP_SSL_KEYSTORE_PATH: OCSP-sslKeystorePath OCSP_SSL_KEYSTORE_TYPE: OCSP-sslKeystoreType OCSP_SSL_KEYSTORE_PASSWORD: OCSP-sslKeystorePassword @@ -93,10 +108,12 @@ OCSP_SUPPORTED_SSL_CIPHER_SUITES: OCSP-sslCipherSuite1, OCSP-sslCipherSuite2 TSP_HTTP_PROXY_HOST: TSP.cache.noile.ee TSP_HTTP_PROXY_PORT: 80802 +TSP_HTTP_PROXY_USER: TSP-plainProxyMan +TSP_HTTP_PROXY_PASSWORD: TSP-plainProxyPass TSP_HTTPS_PROXY_HOST: TSP.secure.noile.ee TSP_HTTPS_PROXY_PORT: 84432 -TSP_HTTP_PROXY_USER: TSP-proxyMan -TSP_HTTP_PROXY_PASSWORD: TSP-proxyPass +TSP_HTTPS_PROXY_USER: TSP-secureProxyMan +TSP_HTTPS_PROXY_PASSWORD: TSP-secureProxyPass TSP_SSL_KEYSTORE_PATH: TSP-sslKeystorePath TSP_SSL_KEYSTORE_TYPE: TSP-sslKeystoreType TSP_SSL_KEYSTORE_PASSWORD: TSP-sslKeystorePassword diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml index 8dda785ca..6d4218985 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf.yaml @@ -1,15 +1,15 @@ DATAFILE_HASHCODE_MODE: false DIGIDOC_MAX_DATAFILE_CACHED: 8192 DIGIDOC_SECURITY_PROVIDER: org.bouncycastle.jce.provider.BouncyCastleProvider1 -TSL_LOCATION: file:conf/test_TSLLocation +LOTL_LOCATION: file:conf/test_LOTLLocation +LOTL_TRUSTSTORE_PATH: file:conf/trust_store +LOTL_TRUSTSTORE_PASSWORD: password TSP_SOURCE: http://tsp.source.test/HttpTspServer VALIDATION_POLICY: conf/test_validation_policy.xml OCSP_SOURCE: http://www.openxades.org/cgi-bin/test_ocsp_source.cgi DIGIDOC_PKCS12_CONTAINER: conf/OCSP_access_certificate_test_file_name DIGIDOC_PKCS12_PASSWD: OCSP_test_password DIGIDOC_DF_CACHE_DIR: /test_cache_dir -TSL_KEYSTORE_LOCATION: keystore -TSL_KEYSTORE_PASSWORD: password TSL_CACHE_EXPIRATION_TIME: 1776 HTTP_PROXY_HOST: cache.noile.ee HTTP_PROXY_PORT: 8080 diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml index 5dc2cd979..4491be5b8 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_generic_proxy_and_ssl_settings.yaml @@ -1,9 +1,11 @@ HTTP_PROXY_HOST: cache.noile.ee HTTP_PROXY_PORT: 8080 +HTTP_PROXY_USER: plainProxyMan +HTTP_PROXY_PASSWORD: plainProxyPass HTTPS_PROXY_HOST: secure.noile.ee HTTPS_PROXY_PORT: 8443 -HTTP_PROXY_USER: proxyMan -HTTP_PROXY_PASSWORD: proxyPass +HTTPS_PROXY_USER: secureProxyMan +HTTPS_PROXY_PASSWORD: secureProxyPass SSL_KEYSTORE_PATH: sslKeystorePath SSL_KEYSTORE_TYPE: sslKeystoreType SSL_KEYSTORE_PASSWORD: sslKeystorePassword diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_hashcode_mode.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_hashcode_mode.yaml index c4d413b8f..1ce29736c 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_hashcode_mode.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_hashcode_mode.yaml @@ -1,15 +1,15 @@ DATAFILE_HASHCODE_MODE: true DIGIDOC_MAX_DATAFILE_CACHED: 8192 DIGIDOC_SECURITY_PROVIDER: org.bouncycastle.jce.provider.BouncyCastleProvider1 -TSL_LOCATION: file:conf/test_TSLLocation +LOTL_LOCATION: file:conf/test_LOTLLocation +LOTL_TRUSTSTORE_PATH: file:conf/trust_store +LOTL_TRUSTSTORE_PASSWORD: password TSP_SOURCE: http://tsp.source.test/HttpTspServer VALIDATION_POLICY: conf/test_validation_policy.xml OCSP_SOURCE: http://www.openxades.org/cgi-bin/test_ocsp_source.cgi DIGIDOC_PKCS12_CONTAINER: conf/OCSP_access_certificate_test_file_name DIGIDOC_PKCS12_PASSWD: OCSP_test_password DIGIDOC_DF_CACHE_DIR: /test_cache_dir -TSL_KEYSTORE_LOCATION: keystore -TSL_KEYSTORE_PASSWORD: password TSL_CACHE_EXPIRATION_TIME: 1776 HTTP_PROXY_HOST: cache.noile.ee HTTP_PROXY_PORT: 8080 diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml index 523cc86f7..de79aba61 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_specific_proxy_and_ssl_settings.yaml @@ -1,9 +1,11 @@ TSL_HTTP_PROXY_HOST: TSL.cache.noile.ee TSL_HTTP_PROXY_PORT: 80800 +TSL_HTTP_PROXY_USER: TSL-plainProxyMan +TSL_HTTP_PROXY_PASSWORD: TSL-plainProxyPass TSL_HTTPS_PROXY_HOST: TSL.secure.noile.ee TSL_HTTPS_PROXY_PORT: 84430 -TSL_HTTP_PROXY_USER: TSL-proxyMan -TSL_HTTP_PROXY_PASSWORD: TSL-proxyPass +TSL_HTTPS_PROXY_USER: TSL-secureProxyMan +TSL_HTTPS_PROXY_PASSWORD: TSL-secureProxyPass TSL_SSL_KEYSTORE_PATH: TSL-sslKeystorePath TSL_SSL_KEYSTORE_TYPE: TSL-sslKeystoreType TSL_SSL_KEYSTORE_PASSWORD: TSL-sslKeystorePassword @@ -16,10 +18,12 @@ TSL_SUPPORTED_SSL_CIPHER_SUITES: TSL-sslCipherSuite1, TSL-sslCipherSuite2 OCSP_HTTP_PROXY_HOST: OCSP.cache.noile.ee OCSP_HTTP_PROXY_PORT: 80801 +OCSP_HTTP_PROXY_USER: OCSP-plainProxyMan +OCSP_HTTP_PROXY_PASSWORD: OCSP-plainProxyPass OCSP_HTTPS_PROXY_HOST: OCSP.secure.noile.ee OCSP_HTTPS_PROXY_PORT: 84431 -OCSP_HTTP_PROXY_USER: OCSP-proxyMan -OCSP_HTTP_PROXY_PASSWORD: OCSP-proxyPass +OCSP_HTTPS_PROXY_USER: OCSP-secureProxyMan +OCSP_HTTPS_PROXY_PASSWORD: OCSP-secureProxyPass OCSP_SSL_KEYSTORE_PATH: OCSP-sslKeystorePath OCSP_SSL_KEYSTORE_TYPE: OCSP-sslKeystoreType OCSP_SSL_KEYSTORE_PASSWORD: OCSP-sslKeystorePassword @@ -32,10 +36,12 @@ OCSP_SUPPORTED_SSL_CIPHER_SUITES: OCSP-sslCipherSuite1, OCSP-sslCipherSuite2 TSP_HTTP_PROXY_HOST: TSP.cache.noile.ee TSP_HTTP_PROXY_PORT: 80802 +TSP_HTTP_PROXY_USER: TSP-plainProxyMan +TSP_HTTP_PROXY_PASSWORD: TSP-plainProxyPass TSP_HTTPS_PROXY_HOST: TSP.secure.noile.ee TSP_HTTPS_PROXY_PORT: 84432 -TSP_HTTP_PROXY_USER: TSP-proxyMan -TSP_HTTP_PROXY_PASSWORD: TSP-proxyPass +TSP_HTTPS_PROXY_USER: TSP-secureProxyMan +TSP_HTTPS_PROXY_PASSWORD: TSP-secureProxyPass TSP_SSL_KEYSTORE_PATH: TSP-sslKeystorePath TSP_SSL_KEYSTORE_TYPE: TSP-sslKeystoreType TSP_SSL_KEYSTORE_PASSWORD: TSP-sslKeystorePassword diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml new file mode 100644 index 000000000..28d1fdd40 --- /dev/null +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_tsl_location_and_keystore.yaml @@ -0,0 +1,3 @@ +TSL_LOCATION: file:conf/test_TSLLocation +TSL_KEYSTORE_LOCATION: file:conf/test_TSLKeyStore_location +TSL_KEYSTORE_PASSWORD: test_TSLKeyStore_password diff --git a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_without_cache_dir.yaml b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_without_cache_dir.yaml index 1d1563836..da547faa5 100644 --- a/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_without_cache_dir.yaml +++ b/digidoc4j/src/test/resources/testFiles/yaml-configurations/digidoc_test_conf_without_cache_dir.yaml @@ -1,7 +1,7 @@ DATAFILE_HASHCODE_MODE: false DIGIDOC_MAX_DATAFILE_CACHED: 8192 DIGIDOC_SECURITY_PROVIDER: org.bouncycastle.jce.provider.BouncyCastleProvider1 -TSL_LOCATION: file:conf/test_TSLLocation +LOTL_LOCATION: file:conf/test_LOTLLocation TSP_SOURCE: http://tsp.source.test/HttpTspServer VALIDATION_POLICY: conf/test_validation_policy.xml OCSP_SOURCE: http://www.openxades.org/cgi-bin/test_ocsp_source.cgi diff --git a/pom.xml b/pom.xml index 525dc9725..ebdf589dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.digidoc4j digidoc4j-parent - 4.3.0 + 5.0.0 pom DigiDoc4J parent @@ -141,8 +141,8 @@ 1.8 1.8 1.8 - 1.7.32 - 1.69 + 1.7.36 + 1.70 none @@ -177,7 +177,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 ${project.build.sourceEncoding} ${maven.compiler.source} @@ -201,7 +201,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + 3.4.0 8 @@ -213,6 +213,8 @@ ${javadocOpt} + + ${project.basedir}/src/main/java @@ -222,12 +224,12 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + 3.0.0-M6 org.jacoco jacoco-maven-plugin - 0.8.7 + 0.8.8 @@ -318,7 +320,7 @@ org.owasp dependency-check-maven - 6.1.6 + 7.1.0 false false diff --git a/publish.sh b/publish.sh index 84fcc5c7e..67770e272 100755 --- a/publish.sh +++ b/publish.sh @@ -1,6 +1,6 @@ #!/bin/bash -version="4.3.0" +version="5.0.0" staging_url="https://oss.sonatype.org/service/local/staging/deploy/maven2/" repositoryId="ossrh"