Skip to content
Permalink
Browse files

Merge branch 'develop'

  • Loading branch information...
siimsuu committed Aug 23, 2019
2 parents 7f99bde + 3f6e136 commit d9241f859932d75897a7d4aced6a412df0f93dbd
Showing with 656 additions and 182 deletions.
  1. +2 −3 README.md
  2. +19 −0 RELEASE-NOTES.txt
  3. +2 −2 ddoc4j/pom.xml
  4. +4 −4 digidoc4j/pom.xml
  5. +3 −3 digidoc4j/src/main/doc/overview.html
  6. +1 −1 digidoc4j/src/main/java/org/digidoc4j/Constant.java
  7. +28 −6 digidoc4j/src/main/java/org/digidoc4j/DigestDataFile.java
  8. +3 −3 ...ava/org/digidoc4j/exceptions/{InvalidServiceUrlException.java → ServiceUnreachableException.java}
  9. +2 −2 digidoc4j/src/main/java/org/digidoc4j/impl/SkDataLoader.java
  10. +33 −26 digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicContainer.java
  11. +19 −1 digidoc4j/src/main/java/org/digidoc4j/impl/asic/AsicParseResult.java
  12. +0 −7 digidoc4j/src/main/java/org/digidoc4j/impl/asic/asice/bdoc/BDocContainer.java
  13. +1 −1 digidoc4j/src/main/java/org/digidoc4j/impl/ddoc/DDocFacade.java
  14. +1 −1 digidoc4j/src/main/java/org/digidoc4j/main/DigiDoc4J.java
  15. +1 −1 digidoc4j/src/main/java/org/digidoc4j/main/ExecutionOption.java
  16. +8 −6 digidoc4j/src/main/java/org/digidoc4j/main/xades/DetachedXadesSignatureExecutor.java
  17. +28 −27 digidoc4j/src/test/java/org/digidoc4j/ConfigurationTest.java
  18. +94 −15 digidoc4j/src/test/java/org/digidoc4j/DetachedXadesSignatureBuilderTest.java
  19. +3 −3 digidoc4j/src/test/java/org/digidoc4j/SignatureBuilderTest.java
  20. +93 −57 digidoc4j/src/test/java/org/digidoc4j/SignatureTest.java
  21. +11 −5 digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocContainerTest.java
  22. +2 −2 digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/BDocSerializationTest.java
  23. +283 −0 digidoc4j/src/test/java/org/digidoc4j/impl/bdoc/ContainerParticlesRemovalTest.java
  24. +12 −3 digidoc4j/src/test/java/org/digidoc4j/main/DigiDoc4JTest.java
  25. +2 −2 pom.xml
  26. +1 −1 publish.sh
@@ -56,7 +56,6 @@ DigiDoc4j is a Java library for digitally signing documents and creating digital
* [DigiDoc4j API](http://open-eid.github.io/digidoc4j/)
* [Examples](https://github.com/open-eid/digidoc4j/wiki/Examples-of-using-it)
* [Wiki](https://github.com/open-eid/digidoc4j/wiki)
* [Pivotal Tracker](https://www.pivotaltracker.com/n/projects/1110130) contains user stories and issues
* [Architecture of ID-software](http://open-eid.github.io/)
* [Digital signature formats](http://www.id.ee/index.php?id=36108)
* [BDOC 2.1.2 specification](http://id.ee/public/bdoc-spec212-eng.pdf)
@@ -66,7 +65,7 @@ DigiDoc4j is a Java library for digitally signing documents and creating digital
* Java 1.7
* 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
* EU TSL (European Commission's Trusted Status List) - https://ec.europa.eu/tools/lotl/eu-lotl.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

@@ -82,7 +81,7 @@ You can use the library as a Maven dependency from the Maven Central (http://mvn
```

# Known issues
The list of user stories and issues are tracked in [Pivotal Tracker](https://www.pivotaltracker.com/n/projects/1110130)
The list of issues are tracked in [GitHub](https://github.com/open-eid/digidoc4j/issues)

# Licence
* LGPL (GNU Library General Public License, see LICENSE.LGPL)
@@ -1,6 +1,25 @@
DigiDoc4J Java library release notes
------------------------------------

Release 3.3.0
------------------
Summary of the major changes since 3.2.0
------------------------------------------
* Default LOTL location update
* Depracate currect method for DigestDataFile creation. Addition of obligatory mimeType setting.
* Fix of removeDataFile functionality
* Dependencies update

Release 3.2.0
------------------
Summary of the major changes since 3.1.1
------------------------------------------
* DataToSign serialization improvements
* Added two-step signing option without Container nor DataToSign object serialization. Container can be saved to disk and only SignatureParameters has to be serialized. Later one can finalize signature with SignatureFinalizer which is initialized from the loaded Container and deserialized SignatureParameters.
* OCSP and TSA services requests error handling changes - more logical exceptions and stopping of signing process in case of any fault
* Removal of unnecessary logging
* Dependencies update

Release 3.1.1
------------------
Summary of the major changes since 3.1.0
@@ -6,7 +6,7 @@
<groupId>org.digidoc4j</groupId>
<artifactId>ddoc4j</artifactId>
<packaging>jar</packaging>
<version>3.2.0</version>
<version>3.3.0</version>

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

<dependencies>
@@ -7,7 +7,7 @@
<groupId>org.digidoc4j</groupId>
<artifactId>digidoc4j</artifactId>
<packaging>jar</packaging>
<version>3.2.0</version>
<version>3.3.0</version>

<name>DigiDoc4j</name>
<description>DigiDoc4j is a Java library for digitally signing documents and creating digital signature containers
@@ -18,7 +18,7 @@
<parent>
<artifactId>digidoc4j-parent</artifactId>
<groupId>org.digidoc4j</groupId>
<version>3.2.0</version>
<version>3.3.0</version>
</parent>

<properties>
@@ -43,7 +43,7 @@
<dependency>
<artifactId>ddoc4j</artifactId>
<groupId>org.digidoc4j</groupId>
<version>3.2.0</version>
<version>3.3.0</version>
</dependency>

<dependency>
@@ -338,7 +338,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
<version>2.9.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -61,7 +61,7 @@ <h2>Validating signature container and all of its contents</h2>
<p>See also: {@link org.digidoc4j.SignatureValidationResult org.digidoc4j.ValidationResult}</p>
<h2>Using TSL lists as trust anchors</h2>
<p>TSL (Trust Service status List) list is a signed XML document that provides information about the status of trust services. The format is based on <a href="http://www.etsi.org/deliver/etsi_ts/119600_119699/119612/01.02.01_60/ts_119612v010201p.pdf" target="_blank">ETSI 119 612</a> standard. </p>
<p>digidoc4j uses TSL lists for checking the trustworthiness of the certificates that are used in the signature. The <a href="https://ec.europa.eu/information_society/policy/esignature/trusted-list/" target="_blank">European Commission's TSL</a> list is used as the List Of Trusted List (LOTL) (accessible from: <a href="https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml" target="_blank">https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml</a>).</p>
<p>digidoc4j uses TSL lists for checking the trustworthiness of the certificates that are used in the signature. The <a href="https://ec.europa.eu/information_society/policy/esignature/trusted-list/" target="_blank">European Commission's TSL</a> list is used as the List Of Trusted List (LOTL) (accessible from: <a href="https://ec.europa.eu/tools/lotl/eu-lotl.xml" target="_blank">https://ec.europa.eu/tools/lotl/eu-lotl.xml</a>).</p>
<p>The main use case regarding TSL lists usage is:</p>
<ol>
<li>Using TSL lists for checking the trustworthiness of the signer's certificate, OCSP service and time-stamping service certificates during signature creation and validation processes.</li>
@@ -123,7 +123,7 @@ <h2>Component diagram</h2>
</tr>
<tr>
<td>TSL repository</td>
<td><p>Repository for the European Commission's central TSL list with links to the locations where the trusted lists are published as notified by EU Member States, accessible from <a href="https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml" target="_blank">https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml</a>. <br>
<td><p>Repository for the European Commission's central TSL list with links to the locations where the trusted lists are published as notified by EU Member States, accessible from <a href="https://ec.europa.eu/tools/lotl/eu-lotl.xml" target="_blank">https://ec.europa.eu/tools/lotl/eu-lotl.xml</a>. <br>
<br>
See also: <br>
- Standard document: <a href="http://www.etsi.org/deliver/etsi_ts/119600_119699/119612/01.02.01_60/ts_119612v010201p.pdf" target="_blank">ETSI 119 612</a><br>
@@ -445,4 +445,4 @@ <h2>Test mode</h2>

<p><code><strong>java -Ddigidoc4j.mode=TEST -jar digidoc4j-util.jar</strong></code></p>
</body>
</html>
</html>
@@ -66,7 +66,7 @@
public static class Production {

public static final String TSP_SOURCE = "http://tsa.sk.ee";
public static final String TSL_LOCATION = "https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml";
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 VALIDATION_POLICY = "conf/constraint.xml";
public static final String OCSP_SOURCE = "http://ocsp.sk.ee/";
@@ -1,43 +1,65 @@
package org.digidoc4j;

import eu.europa.esig.dss.DigestDocument;
import java.util.Arrays;

import org.apache.commons.codec.binary.Base64;
import org.digidoc4j.exceptions.InvalidDataFileException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import eu.europa.esig.dss.DigestDocument;
import eu.europa.esig.dss.MimeType;

public class DigestDataFile extends DataFile {

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


private String contentType = null;

/**
* 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 fileName name of the file
* @param digestAlgorithm algorithm of the digest
* @param digest digest of the file contents
* @param digest digest of the file contents
* @param mimeType mime-type of the data file, for example 'text/plain' or 'application/msword'
*/
public DigestDataFile(String fileName, DigestAlgorithm digestAlgorithm, byte[] digest, String mimeType) {
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));
try {
DigestDocument document = new DigestDocument();
document.setName(fileName);
document.addDigest(digestAlgorithm.getDssDigestAlgorithm(), Base64.encodeBase64String(digest));
if (mimeType != null)
document.setMimeType(mimeType);
setDocument(document);
} catch (Exception e) {
logger.error(e.getMessage());
throw new InvalidDataFileException(e);
}
}


public String getContentType() {
return contentType;
}
@@ -12,9 +12,9 @@

import org.digidoc4j.ServiceType;

public class InvalidServiceUrlException extends NetworkException {
public class ServiceUnreachableException extends NetworkException {

public InvalidServiceUrlException(String serviceUrl, ServiceType serviceType) {
super(String.format("Failed to connect to %s service <%s>", serviceType, serviceUrl), serviceUrl, serviceType);
public ServiceUnreachableException(String serviceUrl, ServiceType serviceType) {
super(String.format("Failed to connect to %s service <%s>. Service is down or URL is invalid.", serviceType, serviceUrl), serviceUrl, serviceType);
}
}
@@ -24,7 +24,7 @@
import org.digidoc4j.Configuration;
import org.digidoc4j.ServiceType;
import org.digidoc4j.exceptions.ConnectionTimedOutException;
import org.digidoc4j.exceptions.InvalidServiceUrlException;
import org.digidoc4j.exceptions.ServiceUnreachableException;
import org.digidoc4j.exceptions.NetworkException;
import org.digidoc4j.exceptions.ServiceAccessDeniedException;
import org.digidoc4j.exceptions.TechnicalException;
@@ -79,7 +79,7 @@ protected SkDataLoader(Configuration configuration) {
return readHttpResponse(httpResponse);

} catch (UnknownHostException e) {
throw new InvalidServiceUrlException(url, getServiceType());
throw new ServiceUnreachableException(url, getServiceType());
} catch (InterruptedIOException e) {
throw new ConnectionTimedOutException(url, getServiceType());
} catch (NetworkException e) {
@@ -348,21 +348,21 @@ private void removeExistingSignature(AsicSignature signature) {
return;
}
String signatureFileName = signatureDocument.getName();
removeExistingSignatureFromContainer(signatureFileName);
removeExistingFileFromContainer(signatureFileName);
}

private void removeExistingFileFromContainer(String filePath) {
LOGGER.debug("Removing file from the container: " + filePath);
if (containerParseResult != null) {
List<AsicEntry> asicEntries = containerParseResult.getAsicEntries();
for (AsicEntry entry : asicEntries) {
String entryFileName = entry.getZipEntry().getName();
if (StringUtils.equalsIgnoreCase(filePath, entryFileName)) {
asicEntries.remove(entry);
LOGGER.debug("File was successfully removed");
break;
}
}
private void removeExistingSignatureFromContainer(String signatureName) {
LOGGER.debug("Removing signature '{}' from the container", signatureName);
if (containerParseResult.removeSignature(signatureName)) {
LOGGER.debug("Signature '{}' successfully removed from container", signatureName);
}
}

private void removeExistingFileFromContainer(String fileName) {
LOGGER.debug("Removing file '{}' from the container" + fileName);
if (containerParseResult.removeAsicEntry(fileName)) {
LOGGER.debug("File '{}' successfully removed from container", fileName);
}
}

@@ -421,7 +421,9 @@ public void addDataFile(DataFile dataFile) {
dataFiles.add(dataFile);
newDataFiles.add(dataFile);
dataFilesHaveChanged = true;
removeExistingFileFromContainer(AsicManifest.XML_PATH);
if (!isNewContainer()) {
removeExistingFileFromContainer(AsicManifest.XML_PATH);
}
}

@Override
@@ -500,6 +502,7 @@ public void removeSignature(Signature signature) {
removeExistingSignature((AsicSignature) signature);
}
} else {
newSignatures.remove(signature);
signatures.remove(signature);
}
}
@@ -508,27 +511,21 @@ public void removeSignature(Signature signature) {
@Deprecated
public void removeSignature(int signatureId) {
LOGGER.debug("Removing signature from index " + signatureId);
if (!isNewContainer()) {
Signature signature = signatures.get(signatureId);
if (signature != null) {
removeSignature(signature);
}
} else {
signatures.remove(signatureId);
Signature signature = signatures.get(signatureId);
if (signature != null) {
removeSignature(signature);
}

}

@Override
public void removeDataFile(String fileName) {
validateDataFilesRemoval();
LOGGER.info("Attempting to remove data file: {}", fileName);

for (DataFile dataFile : dataFiles) {
String name = dataFile.getName();
if (StringUtils.equals(fileName, name)) {
dataFiles.remove(dataFile);
LOGGER.debug("Data file has been removed");
removeDataFileFromContainer(dataFile);
LOGGER.info("Data file named '{}' has been removed", fileName);
return;
}
}
@@ -538,12 +535,22 @@ public void removeDataFile(String fileName) {
@Override
public void removeDataFile(DataFile file) {
validateDataFilesRemoval();
LOGGER.info("Attempting to remove data file: {}", file.getName());

boolean wasRemovalSuccessful = dataFiles.remove(file);
boolean wasRemovalSuccessful = removeDataFileFromContainer(file);
if (!wasRemovalSuccessful) {
throw new DataFileNotFoundException(file.getName());
}
LOGGER.info("Data file named '{}' has been removed", file.getName());
}

private boolean removeDataFileFromContainer(DataFile dataFile) {
if (!isNewContainer()) {
removeExistingFileFromContainer(dataFile.getName());
containerParseResult.getDataFiles().remove(dataFile);
containerParseResult.getDetachedContents().remove(dataFile.getDocument());
}
newDataFiles.remove(dataFile);
return dataFiles.remove(dataFile);
}

private boolean isNewContainer() {

0 comments on commit d9241f8

Please sign in to comment.
You can’t perform that action at this time.