Commit d5de6bcc authored by Tobias Wich's avatar Tobias Wich
Browse files

Refactor and add function to get document hash

parent 67cb8424
/target/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.ecsec.reqesidta</groupId>
<artifactId>PadesPOC</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-pades</artifactId>
<version>5.3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId> dss-utils-apache-commons</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.futuretrust.sigs</groupId>
<artifactId>sigs-schema</artifactId>
<version>1.3.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-token</artifactId>
<version>5.3.2</version>
<type>jar</type>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeScope>provided</excludeScope>
</configuration>
</execution>
</executions>
</plugin>
<modelVersion>4.0.0</modelVersion>
<groupId>de.ecsec.reqesidta</groupId>
<artifactId>PadesPOC</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- Netbeans config properties -->
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.tab-size>4</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.tab-size>
<org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap>none</org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap>
<org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width>4</org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width>
<org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab>4</org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab>
<org-netbeans-modules-editor-indent.CodeStyle.project.tab-size>4</org-netbeans-modules-editor-indent.CodeStyle.project.tab-size>
<org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width>120</org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width>
<org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs>false</org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs>
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
</properties>
<repositories>
<repository>
<id>ec.europa.eu</id>
<url>https://ec.europa.eu/cefdigital/artifact/repository/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-pades</artifactId>
<version>5.3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-utils-apache-commons</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-token</artifactId>
<version>5.3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeScope>provided</excludeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- <classpathPrefix>lib</classpathPrefix> -->
<!-- <mainClass>test.org.Cliente</mainClass> -->
</manifest>
<manifestEntries>
<Class-Path>lib/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- <classpathPrefix>lib</classpathPrefix> -->
<!-- <mainClass>test.org.Cliente</mainClass> -->
</manifest>
<manifestEntries>
<Class-Path>lib/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package de.skidentity.padestest;
import de.skidentity.visualsignature.CertificateTextFormatter;
import de.skidentity.visualsignature.ImageCreationException;
import de.skidentity.visualsignature.PAdESReasonBuilder;
import de.skidentity.visualsignature.VisibleSignatureImageCreator;
import de.skidentity.visualsignature.VisualSignaturePositioner;
import eu.europa.esig.dss.DSSDocument;
import eu.europa.esig.dss.DigestAlgorithm;
import eu.europa.esig.dss.InMemoryDocument;
import eu.europa.esig.dss.SignatureLevel;
import eu.europa.esig.dss.SignatureValue;
import eu.europa.esig.dss.ToBeSigned;
import eu.europa.esig.dss.pades.PAdESSignatureParameters;
import eu.europa.esig.dss.pades.SignatureImageParameters;
import eu.europa.esig.dss.pades.SignatureImageTextParameters;
import eu.europa.esig.dss.pades.signature.PAdESService;
import eu.europa.esig.dss.validation.CommonCertificateVerifier;
import eu.europa.esig.dss.x509.CertificateToken;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;
import oasis.names.tc.dssx._1_0.profiles.pades.schema_.ImageType;
import oasis.names.tc.dssx._1_0.profiles.pades.schema_.SignaturePositionType;
import oasis.names.tc.dssx._1_0.profiles.pades.schema_.VisibleSignatureConfiguration;
import oasis.names.tc.dssx._1_0.profiles.pades.schema_.VisibleSignatureItemsType;
import org.apache.commons.io.IOUtils;
import org.slf4j.LoggerFactory;
/**
*
* @author Sebastian Schuberth
*/
public class Client {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Client.class);
private DSSDocument toSignDocument;
private final PAdESService service = new PAdESService(new CommonCertificateVerifier());
private BufferedImage bufferedImage;
private final PAdESSignatureParameters parameters = new PAdESSignatureParameters();
public Client() {
}
public void setExampleDocument() {
try {
File doc = FileUtility.getFileFromRessourceFolder("/123.pdf");
byte[] bytes = IOUtils.toByteArray(new FileInputStream(doc));
toSignDocument = new InMemoryDocument(bytes);
} catch (IOException | URISyntaxException ex) {
LOG.error(ex.getMessage(), ex);
}
}
public void incorporateVisualSignature() {
VisibleSignatureConfiguration vsc = new VisibleSignatureConfiguration();
SignaturePositionType sigPos = new SignaturePositionType();
sigPos.setWidth(BigInteger.valueOf(172));
sigPos.setHeight(BigInteger.valueOf(53));
sigPos.setPage("1");
sigPos.setX(BigInteger.valueOf(50));
sigPos.setY(BigInteger.valueOf(50));
vsc.setSignaturePosition(sigPos);
try {
VisibleSignatureItemsType vsit = new VisibleSignatureItemsType();
ImageType it = new ImageType();
File image = FileUtility.getFileFromRessourceFolder("/visual-signature.png");
it.setData(createImage(image));
vsit.setImage(it);
vsc.setVisibleSignatureItems(vsit);
SignatureImageParameters imageParameters = new SignatureImageParameters();
SignatureImageTextParameters textParameters = new SignatureImageTextParameters();
VisualSignaturePositioner vsp = new VisualSignaturePositioner(imageParameters, toSignDocument, vsc);
vsp.setImagePosition(parameters);
textParameters.setBackgroundColor(Color.WHITE);
imageParameters.setTextParameters(textParameters);
imageParameters.setRotation(SignatureImageParameters.VisualSignatureRotation.AUTOMATIC);
((PAdESSignatureParameters) parameters).setSignatureImageParameters(imageParameters);
this.bufferedImage = ImageIO.read(new ByteArrayInputStream(it.getData()));
} catch (IOException | URISyntaxException ex) {
LOG.error(ex.getMessage(), ex);
}
}
public void setBasicParameters() {
parameters.setSignatureLevel(SignatureLevel.PAdES_BASELINE_B);
parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
}
public void updateCertData(CertificateToken certToken, CertificateToken[] certChain) {
Date today = Calendar.getInstance().getTime();
List<String> assertions = parameters.bLevel().getSignedAssertions();
String name = "";
if (assertions != null && !assertions.isEmpty()) {
String assertion = assertions.get(0);
PAdESReasonBuilder reasonBuilder = new PAdESReasonBuilder(assertion);
String reason = reasonBuilder.getReason();
name = reasonBuilder.getName();
System.out.println("Reason: " + reason);
this.addReason(reason);
}
parameters.setSigningCertificate(certToken);
parameters.setCertificateChain(certChain);
parameters.bLevel().setSigningDate(today);
SignatureImageParameters imageParameters = ((PAdESSignatureParameters) parameters).getSignatureImageParameters();
if (imageParameters != null) {
//create visual signature
SignatureImageTextParameters textParameters = imageParameters.getTextParameters();
String text;
if (certToken != null && certToken.getCertificate() != null) {
text = new CertificateTextFormatter(certToken.getCertificate(), today).getFormattedCertificateText(name);
} else {
text = "test";
}
Dimension signatureBox = new Dimension(imageParameters.getWidth(), imageParameters.getHeight());
VisibleSignatureImageCreator vsic = new VisibleSignatureImageCreator(signatureBox);
try {
imageParameters.setImage(vsic.createVisualSignatureImage(this.bufferedImage, text));
} catch (ImageCreationException ex) {
LOG.error(ex.getMessage(), ex);
}
textParameters.setText(""); //remove text again, lest DSS uses its own implementation for text drawing
}
}
public DigestAlgorithm getDigestAlgorithm() {
return parameters.getDigestAlgorithm();
}
public ToBeSigned prepareTBS() {
ToBeSigned tbs = service.getDataToSign(toSignDocument, parameters);
return tbs;
}
public DSSDocument incorporateSignatureValueIntoDocument(SignatureValue signatureValue) {
DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
return signedDocument;
}
public void saveSignedDocument(DSSDocument doc) throws IOException, URISyntaxException {
// doc.save("/path/to/download/or/whatever/folder"); // adjust to your needs
}
private void addReason(String reason) {
String oldReason = ((PAdESSignatureParameters) parameters).getReason();
String newReason = reason;
if (oldReason != null) {
newReason = oldReason + " " + reason;
}
((PAdESSignatureParameters) parameters).setReason(newReason);
}
private static byte[] createImage(File file) throws IOException {
ByteArrayOutputStream out;
try (InputStream fis = new FileInputStream(file)) {
BufferedImage bufferedImage = ImageIO.read(fis);
int width = bufferedImage.getWidth(), height = bufferedImage.getHeight();
BufferedImage img = new BufferedImage(width, height, ColorSpace.TYPE_RGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(Color.WHITE);
g2.clearRect(0, 0, width, height);
g2.drawImage(bufferedImage, 0, 0, width, height, null);
out = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", out);
}
return out.toByteArray();
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package reqesidta.padestest;
import eu.europa.esig.dss.DSSDocument;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.DigestAlgorithm;
import eu.europa.esig.dss.InMemoryDocument;
import eu.europa.esig.dss.SignatureLevel;
import eu.europa.esig.dss.SignatureValue;
import eu.europa.esig.dss.ToBeSigned;
import eu.europa.esig.dss.pades.PAdESSignatureParameters;
import eu.europa.esig.dss.pades.SignatureImageParameters;
import eu.europa.esig.dss.pades.SignatureImageTextParameters;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.validation.CommonCertificateVerifier;
import eu.europa.esig.dss.x509.CertificateToken;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.Date;
import javax.imageio.ImageIO;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reqesidta.visualsignature.CertificateTextFormatter;
import reqesidta.visualsignature.ImageCreationException;
import reqesidta.visualsignature.ImageType;
import reqesidta.visualsignature.SignaturePositionType;
import reqesidta.visualsignature.VisibleSignatureConfiguration;
import reqesidta.visualsignature.VisibleSignatureImageCreator;
import reqesidta.visualsignature.VisibleSignatureItemsType;
import reqesidta.visualsignature.VisualSignaturePositioner;
/**
*
* @author Sebastian Schuberth
*/
public class Client {
private static final Logger LOG = LoggerFactory.getLogger(Client.class);
private DSSDocument toSignDocument;
private final CustomPadesService service = new CustomPadesService(new CommonCertificateVerifier());
private BufferedImage bufferedImage;
private final PAdESSignatureParameters parameters = new PAdESSignatureParameters();
Date today = Calendar.getInstance().getTime();
public Client() {
}
public Date getToday() {
return today;
}
public void setExampleDocument() {
try {
File doc = FileUtility.getFileFromRessourceFolder("/123.pdf");
byte[] bytes = IOUtils.toByteArray(new FileInputStream(doc));
toSignDocument = new InMemoryDocument(bytes);
} catch (IOException | URISyntaxException ex) {
LOG.error(ex.getMessage(), ex);
}
}
private void incorporateVisualSignature(CertificateToken certToken, CertificateToken[] certChain) {
VisibleSignatureConfiguration vsc = new VisibleSignatureConfiguration();
SignaturePositionType sigPos = new SignaturePositionType();
sigPos.setWidth(BigInteger.valueOf(172));
sigPos.setHeight(BigInteger.valueOf(53));
sigPos.setPage("1");
sigPos.setX(BigInteger.valueOf(50));
sigPos.setY(BigInteger.valueOf(50));
vsc.setSignaturePosition(sigPos);
try {
VisibleSignatureItemsType vsit = new VisibleSignatureItemsType();
ImageType it = new ImageType();
File image = FileUtility.getFileFromRessourceFolder("/visual-signature.png");
it.setData(createImage(image));
vsit.setImage(it);
vsc.setVisibleSignatureItems(vsit);
SignatureImageParameters imageParameters = new SignatureImageParameters();
SignatureImageTextParameters textParameters = new SignatureImageTextParameters();
VisualSignaturePositioner vsp = new VisualSignaturePositioner(imageParameters, toSignDocument, vsc);
vsp.setImagePosition(parameters);
textParameters.setBackgroundColor(Color.WHITE);
imageParameters.setTextParameters(textParameters);
imageParameters.setRotation(SignatureImageParameters.VisualSignatureRotation.AUTOMATIC);
((PAdESSignatureParameters) parameters).setSignatureImageParameters(imageParameters);
this.bufferedImage = ImageIO.read(new ByteArrayInputStream(it.getData()));
} catch (IOException | URISyntaxException ex) {
LOG.error(ex.getMessage(), ex);
}
String name = "";
SignatureImageParameters imageParameters = ((PAdESSignatureParameters) parameters).getSignatureImageParameters();
if (imageParameters != null) {
//create visual signature
SignatureImageTextParameters textParameters = imageParameters.getTextParameters();
String text;
if (certToken != null && certToken.getCertificate() != null) {
text = new CertificateTextFormatter(certToken.getCertificate(), today).getFormattedCertificateText(name);
} else {
text = "test";
}
Dimension signatureBox = new Dimension(imageParameters.getWidth(), imageParameters.getHeight());
VisibleSignatureImageCreator vsic = new VisibleSignatureImageCreator(signatureBox);
try {
imageParameters.setImage(vsic.createVisualSignatureImage(this.bufferedImage, text));
} catch (ImageCreationException ex) {
LOG.error(ex.getMessage(), ex);
}
textParameters.setText(""); //remove text again, lets DSS uses its own implementation for text drawing
}
}
public void setBasicParameters() {
parameters.setSignatureLevel(SignatureLevel.PAdES_BASELINE_B);
parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
parameters.bLevel().setSigningDate(today);
String timestampHash = Utils.toHex(DSSUtils.digest(DigestAlgorithm.SHA1, Long.toString(today.getTime()).getBytes()));
parameters.setSignatureName("ReQESIDTA_" + timestampHash);
}
public void updateCertData(CertificateToken certToken, CertificateToken[] certChain, boolean addVisibleSignature) {
parameters.setSigningCertificate(certToken);
parameters.setCertificateChain(certChain);
if (addVisibleSignature) {
incorporateVisualSignature(certToken, certChain);
}
}
public DigestAlgorithm getDigestAlgorithm() {
return parameters.getDigestAlgorithm();
}
public DSSDocument getToSignDoc() {
return toSignDocument;
}
public byte[] getDocHash() {
byte[] docHash = service.getDocumentDigest(toSignDocument, parameters);
return docHash;
}
public ToBeSigned getTBSData() {
ToBeSigned tbs = service.getDataToSign(toSignDocument, parameters);
return tbs;
}
public DSSDocument saveSignatureValue(SignatureValue signatureValue) {
DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
return signedDocument;
}
public void saveSignedDocument(DSSDocument doc) throws IOException, URISyntaxException {
// doc.save("/path/to/download/or/whatever/folder"); // adjust to your needs
}
private void addReason(String reason) {
String oldReason = ((PAdESSignatureParameters) parameters).getReason();
String newReason = reason;
if (oldReason != null) {
newReason = oldReason + " " + reason;
}
((PAdESSignatureParameters) parameters).setReason(newReason);
}
private static byte[] createImage(File file) throws IOException {
ByteArrayOutputStream out;
try (InputStream fis = new FileInputStream(file)) {
BufferedImage bufferedImage = ImageIO.read(fis);
int width = bufferedImage.getWidth(), height = bufferedImage.getHeight();
BufferedImage img = new BufferedImage(width, height, ColorSpace.TYPE_RGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(Color.WHITE);
g2.clearRect(0, 0, width, height);
g2.drawImage(bufferedImage, 0, 0, width, height, null);
out = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", out);
}
return out.toByteArray();
}
}