aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2013-10-02 10:28:30 +0200
committerAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2013-10-02 10:28:30 +0200
commit0876981fd70fdab07f7c3e1666cf77071b5fe03d (patch)
tree0661571d1d757383fee936d1c4648d2c31b43ddb
parentadd4460d9619f3586a02ae0d8c028f01903494bc (diff)
downloadpdf-as-4-0876981fd70fdab07f7c3e1666cf77071b5fe03d.tar.gz
pdf-as-4-0876981fd70fdab07f7c3e1666cf77071b5fe03d.tar.bz2
pdf-as-4-0876981fd70fdab07f7c3e1666cf77071b5fe03d.zip
+ added PKCS7 detached siganture standard via keystore
+ added simple verification implementation
-rw-r--r--pdf-as-cli/build.gradle1
-rw-r--r--pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/DeveloperMain.java11
-rw-r--r--pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/TempFileHelper.java14
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java3
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/verify/VerifyResult.java4
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java139
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java8
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/FilterEntry.java28
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IVerifyFilter.java11
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifierDispatcher.java61
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifyResultImpl.java75
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/package-info.java8
-rw-r--r--settings.gradle2
-rw-r--r--signature-standards/sigs-pcks7detached/.gitignore1
-rw-r--r--signature-standards/sigs-pcks7detached/build.gradle34
-rw-r--r--signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java (renamed from pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java)16
-rw-r--r--signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedVerifier.java74
-rw-r--r--signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/package-info.java8
18 files changed, 465 insertions, 33 deletions
diff --git a/pdf-as-cli/build.gradle b/pdf-as-cli/build.gradle
index 48a9b659..f66529ec 100644
--- a/pdf-as-cli/build.gradle
+++ b/pdf-as-cli/build.gradle
@@ -14,6 +14,7 @@ repositories {
dependencies {
compile project (':pdf-as-lib')
compile project (':stamper:stmp-itext')
+ compile project (':signature-standards:sigs-pcks7detached')
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
diff --git a/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/DeveloperMain.java b/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/DeveloperMain.java
index 4b9a4e33..0e114eae 100644
--- a/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/DeveloperMain.java
+++ b/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/DeveloperMain.java
@@ -15,8 +15,9 @@ import at.gv.egiz.pdfas.lib.api.PdfAs;
import at.gv.egiz.pdfas.lib.api.PdfAsFactory;
import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner;
import at.gv.egiz.pdfas.lib.api.sign.SignParameter;
-import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner;
-import at.gv.egiz.pdfas.lib.impl.signing.sig_interface.JKSSigner;
+import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter;
+import at.gv.egiz.pdfas.lib.impl.VerifyParameterImpl;
+import at.gv.egiz.pdfas.sigs.pkcs7detached.PKCS7DetachedSigner;
public class DeveloperMain {
@@ -34,7 +35,7 @@ public class DeveloperMain {
Configuration config = pdfas.getConfiguration();
byte[] data;
try {
- IPlainSigner signer = new JKSSigner(keyStoreFile, keyAlias, keyStorePass, keyPass, keyStoreType);
+ IPlainSigner signer = new PKCS7DetachedSigner(keyStoreFile, keyAlias, keyStorePass, keyPass, keyStoreType);
data = StreamUtils.inputStreamToByteArray(new FileInputStream("/home/afitzek/devel/pdfas_neu/simple.pdf"));
SignParameter parameter = PdfAsFactory.createSignParameter(config, new ByteArrayDataSource(data));
ByteArrayDataSink bads = new ByteArrayDataSink();
@@ -45,6 +46,10 @@ public class DeveloperMain {
FileOutputStream fos = new FileOutputStream("/home/afitzek/devel/pdfas_neu/simple_out.pdf");
fos.write(bads.getData());
fos.close();
+
+ VerifyParameter verify = new VerifyParameterImpl(config, new ByteArrayDataSource(bads.getData()));
+ pdfas.verify(verify);
+
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/TempFileHelper.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/TempFileHelper.java
index 611d7a0b..03cd28f3 100644
--- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/TempFileHelper.java
+++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/TempFileHelper.java
@@ -27,6 +27,8 @@ public class TempFileHelper implements IProfileConstants {
private List<String> tmpFiles = new ArrayList<String>();
+ private boolean needsDeletion = false;
+
public TempFileHelper(ISettings settings) {
initializeMD();
@@ -37,9 +39,12 @@ public class TempFileHelper implements IProfileConstants {
// relatives tmp dir
myTmpDirFile = new File(settings.getWorkingDirectory() + File.separator + myTmpDir);
}
- tmpDir = myTmpDirFile.getAbsolutePath();
+ tmpDir = myTmpDirFile.getAbsolutePath() + File.separator;
} else {
- tmpDir = settings.getWorkingDirectory() + File.separator + TMP_DIR_DEFAULT_VALUE;
+ String uuidString = UUID.randomUUID().toString();
+ logger.debug("Generated UUID " + uuidString);
+ tmpDir = settings.getWorkingDirectory() + File.separator + TMP_DIR_DEFAULT_VALUE + File.separator + getHashedHexString(uuidString) + File.separator;
+ needsDeletion = true;
}
logger.info("TempDirHelper for TempDirectory: " + tmpDir);
@@ -66,6 +71,9 @@ public class TempFileHelper implements IProfileConstants {
try {
File tmpdir = new File(tmpDir);
tmpdir.mkdirs();
+ if(needsDeletion) {
+ tmpdir.deleteOnExit();
+ }
} catch (Throwable e) {
logger.error("Failed to create temporary directory: " + tmpDir, e);
}
@@ -101,7 +109,7 @@ public class TempFileHelper implements IProfileConstants {
public String getStaticFilename() {
String uuidString = UUID.randomUUID().toString();
logger.debug("Generated UUID " + uuidString);
- String tmpFilename = tmpFilePrefix + getHashedHexString(uuidString) + tmpFileSuffix;
+ String tmpFilename = tmpDir + getHashedHexString(uuidString) + tmpFileSuffix;
logger.info("Temporary filename " + tmpFilename);
tmpFiles.add(tmpFilename);
return tmpFilename;
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java
index 0735a0bf..6155a245 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java
@@ -4,9 +4,12 @@ import iaik.x509.X509Certificate;
import java.io.IOException;
+import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.exceptions.SignatureException;
public interface IPlainSigner {
public X509Certificate getCertificate();
public byte[] sign(byte[] input) throws SignatureException, IOException;
+ public String getPDFSubFilter();
+ public String getPDFFilter();
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/verify/VerifyResult.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/verify/VerifyResult.java
index 339f7b15..b9d286c3 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/verify/VerifyResult.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/verify/VerifyResult.java
@@ -1,5 +1,6 @@
package at.gv.egiz.pdfas.lib.api.verify;
+import iaik.x509.X509Certificate;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
public interface VerifyResult {
@@ -47,4 +48,7 @@ public interface VerifyResult {
* certificate.
*/
public boolean isQualifiedCertificate();
+
+
+ public X509Certificate getSignerCertificate();
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java
index 5bda572b..a8cee107 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java
@@ -1,12 +1,24 @@
package at.gv.egiz.pdfas.lib.impl;
+import iaik.cms.CMSException;
+import iaik.cms.CMSParsingException;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
import iaik.x509.X509Certificate;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.OutputStream;
+import java.security.SignatureException;
import java.util.List;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +29,7 @@ import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException;
import at.gv.egiz.pdfas.common.settings.ISettings;
import at.gv.egiz.pdfas.common.settings.Settings;
import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;
+import at.gv.egiz.pdfas.common.utils.StringUtils;
import at.gv.egiz.pdfas.lib.api.Configuration;
import at.gv.egiz.pdfas.lib.api.IConfigurationConstants;
import at.gv.egiz.pdfas.lib.api.PdfAs;
@@ -36,25 +49,28 @@ import at.gv.egiz.pdfas.lib.impl.stamping.StamperFactory;
import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;
import at.gv.egiz.pdfas.lib.impl.status.OperationStatus;
import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;
+import at.gv.egiz.pdfas.lib.impl.verify.IVerifyFilter;
+import at.gv.egiz.pdfas.lib.impl.verify.VerifierDispatcher;
import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
import at.knowcenter.wag.egov.egiz.pdf.TablePos;
import at.knowcenter.wag.egov.egiz.table.Table;
public class PdfAsImpl implements PdfAs, IConfigurationConstants {
- private static final Logger logger = LoggerFactory.getLogger(PdfAsImpl.class);
-
+ private static final Logger logger = LoggerFactory
+ .getLogger(PdfAsImpl.class);
+
private Settings settings;
-
+
public PdfAsImpl(File cfgFile) {
logger.info("Initializing PDF-AS with config: " + cfgFile.getPath());
this.settings = new Settings(cfgFile);
}
-
+
public SignResult sign(SignParameter parameter) throws PdfAsException {
logger.trace("sign started");
-
+
// TODO: verify signParameter
try {
@@ -62,7 +78,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
if (!(parameter.getConfiguration() instanceof ISettings)) {
throw new PdfAsSettingsException("Invalid settings object!");
}
-
+
ISettings settings = (ISettings) parameter.getConfiguration();
OperationStatus status = new OperationStatus(settings, parameter);
PlaceholderConfiguration placeholderConfiguration = status
@@ -76,7 +92,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
.getSignatureProfileID();
logger.info("Selected signature Profile: " + signatureProfileID);
-
+
SignatureProfileConfiguration signatureProfileConfiguration = status
.getSignatureProfileConfiguration(signatureProfileID);
@@ -88,7 +104,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
if (placeholderConfiguration.isGlobalPlaceholderEnabled()) {
// TODO: Do placeholder search
}
-
+
if (requestedSignature.isVisual()) {
logger.info("Creating visual siganture block");
// ================================================================
@@ -98,9 +114,11 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
.createProfile(signatureProfileID, settings);
Table main = TableFactory.createSigTable(
- signatureProfileSettings, MAIN, settings, requestedSignature);
+ signatureProfileSettings, MAIN, settings,
+ requestedSignature);
- IPDFStamper stamper = StamperFactory.createDefaultStamper(settings);
+ IPDFStamper stamper = StamperFactory
+ .createDefaultStamper(settings);
IPDFVisualObject visualObject = stamper.createVisualPDFObject(
status.getPdfObject(), main);
@@ -149,19 +167,22 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
// TODO: Create signature
IPdfSigner signer = PdfSignerFactory.createPdfSigner();
- signer.signPDF(status.getPdfObject(), requestedSignature, status.getSignParamter().getPlainSigner());
-
- //status.getPdfObject().setSignedDocument(status.getPdfObject().getStampedDocument());
-
+ signer.signPDF(status.getPdfObject(), requestedSignature, status
+ .getSignParamter().getPlainSigner());
+
+ // status.getPdfObject().setSignedDocument(status.getPdfObject().getStampedDocument());
+
// ================================================================
// Create SignResult
- SignResultImpl result = new SignResultImpl(status.getSignParamter().getOutput());
- OutputStream outputStream = result.getOutputDocument().createOutputStream();
-
+ SignResultImpl result = new SignResultImpl(status.getSignParamter()
+ .getOutput());
+ OutputStream outputStream = result.getOutputDocument()
+ .createOutputStream();
+
outputStream.write(status.getPdfObject().getSignedDocument());
-
+
outputStream.close();
-
+
return result;
} catch (Throwable e) {
logger.error("sign failed " + e.getMessage(), e);
@@ -172,7 +193,85 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {
}
public List<VerifyResult> verify(VerifyParameter parameter) {
- // TODO Auto-generated method stub
+ try {
+ ISettings settings = (ISettings) parameter.getConfiguration();
+ VerifierDispatcher verifier = new VerifierDispatcher(settings);
+ PDDocument doc = PDDocument.load(new ByteArrayInputStream(parameter
+ .getDataSource().getByteData()));
+
+ COSDictionary trailer = doc.getDocument().getTrailer();
+ COSDictionary root = (COSDictionary) trailer
+ .getDictionaryObject(COSName.ROOT);
+ COSDictionary acroForm = (COSDictionary) root
+ .getDictionaryObject(COSName.ACRO_FORM);
+ COSArray fields = (COSArray) acroForm
+ .getDictionaryObject(COSName.FIELDS);
+ for (int i = 0; i < fields.size(); i++) {
+ COSDictionary field = (COSDictionary) fields.getObject(i);
+ String type = field.getNameAsString("FT");
+ if ("Sig".equals(type)) {
+ logger.trace("Found Signature: ");
+ COSBase base = field.getDictionaryObject("V");
+ COSDictionary dict = (COSDictionary) base;
+
+ logger.debug("Signer: "
+ + dict.getNameAsString("Name"));
+ logger.debug("SubFilter: "
+ + dict.getNameAsString("SubFilter"));
+ logger.debug("Filter: "
+ + dict.getNameAsString("Filter"));
+ logger.debug("Modified: " + dict.getNameAsString("M"));
+ COSArray byteRange = (COSArray) dict
+ .getDictionaryObject("ByteRange");
+
+
+ StringBuilder sb = new StringBuilder();
+ int[] bytes = new int[byteRange.size()];
+ for (int j = 0; j < byteRange.size(); j++) {
+ bytes[j] = byteRange.getInt(j);
+ sb.append(" " + bytes[j]);
+ }
+
+ logger.debug("ByteRange" + sb.toString());
+
+ COSString content = (COSString) dict
+ .getDictionaryObject("Contents");
+ /*logger.trace("Content: "
+ + StringUtils.bytesToHexString(content.getBytes()));*/
+
+ ByteArrayOutputStream contentData = new ByteArrayOutputStream();
+ for (int j = 0; j < bytes.length; j = j + 2) {
+ int offset = bytes[j];
+ int length = bytes[j + 1];
+ contentData.write(parameter.getDataSource()
+ .getByteData(), offset, length);
+ }
+ contentData.close();
+
+ IVerifyFilter verifyFilter =
+ verifier.getVerifier(dict.getNameAsString("Filter"), dict.getNameAsString("SubFilter"));
+
+ verifyFilter.verify(contentData.toByteArray(), content.getBytes());
+
+ /*
+ * Iterator<Map.Entry<COSName, COSBase>> iterator =
+ * dict.entrySet().iterator();
+ *
+ * while(iterator.hasNext()) { Map.Entry<COSName, COSBase>
+ * entry = iterator.next(); System.out.println("Key: "
+ * +entry.getKey().toString());
+ *
+ * }
+ */
+
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (PdfAsException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
return null;
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java
index 82ee57fe..7f16a87a 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java
@@ -8,6 +8,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
+import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.exceptions.SignatureException;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -52,8 +53,8 @@ public class PADESPDFBOXSigner implements IPdfSigner {
new ByteArrayInputStream(pdfObject.getStampedDocument()));
PDSignature signature = new PDSignature();
- signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
- signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);
+ signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default filter
+ signature.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter()));
SignatureProfileSettings signatureProfileSettings = TableFactory
.createProfile(requestedSignature.getSignatureProfileID(),
@@ -62,7 +63,8 @@ public class PADESPDFBOXSigner implements IPdfSigner {
ValueResolver resolver = new ValueResolver();
String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"),
signatureProfileSettings, requestedSignature);
- // TODO: change signature data from certificate
+
+
signature.setName(signerName);
//signature.setLocation("signer location");
signature.setReason("PDF-AS Signatur");
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/FilterEntry.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/FilterEntry.java
new file mode 100644
index 00000000..59b20c97
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/FilterEntry.java
@@ -0,0 +1,28 @@
+package at.gv.egiz.pdfas.lib.impl.verify;
+
+import org.apache.pdfbox.cos.COSName;
+
+public class FilterEntry {
+ private COSName filter;
+ private COSName subFilter;
+
+ public FilterEntry(COSName filter, COSName subfilter) {
+ this.filter = filter;
+ this.subFilter = subfilter;
+ }
+
+ public COSName getFilter() {
+ return filter;
+ }
+ public void setFilter(COSName filter) {
+ this.filter = filter;
+ }
+ public COSName getSubFilter() {
+ return subFilter;
+ }
+ public void setSubFilter(COSName subFilter) {
+ this.subFilter = subFilter;
+ }
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IVerifyFilter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IVerifyFilter.java
new file mode 100644
index 00000000..7aca582b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IVerifyFilter.java
@@ -0,0 +1,11 @@
+package at.gv.egiz.pdfas.lib.impl.verify;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;
+
+public interface IVerifyFilter {
+ public List<VerifyResult> verify(byte[] contentData, byte[] signatureContent) throws PdfAsException;
+ public List<FilterEntry> getFiters();
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifierDispatcher.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifierDispatcher.java
new file mode 100644
index 00000000..0de3a71e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifierDispatcher.java
@@ -0,0 +1,61 @@
+package at.gv.egiz.pdfas.lib.impl.verify;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.common.settings.ISettings;
+
+public class VerifierDispatcher {
+
+ private static final Logger logger = LoggerFactory.getLogger(VerifierDispatcher.class);
+
+ public static final String currentClass = "at.gv.egiz.pdfas.sigs.pkcs7detached.PKCS7DetachedVerifier";
+
+ public Map<String, HashMap<String, IVerifyFilter>> filterMap = new HashMap<String, HashMap<String, IVerifyFilter>>();
+
+ public VerifierDispatcher(ISettings settings) {
+ // TODO: read config build verify filter
+ try {
+ Class<? extends IVerifyFilter> cls = (Class<? extends IVerifyFilter>) Class.forName(currentClass);
+ IVerifyFilter fitler = cls.newInstance();
+ List<FilterEntry> entries = fitler.getFiters();
+ Iterator<FilterEntry> it = entries.iterator();
+ while(it.hasNext()) {
+ FilterEntry entry = it.next();
+ HashMap<String, IVerifyFilter> filters = filterMap.get(entry.getFilter().getName());
+ if(filters == null) {
+ filters = new HashMap<String, IVerifyFilter>();
+ filterMap.put(entry.getFilter().getName(), filters);
+ }
+
+ IVerifyFilter oldFilter = filters.get(entry.getSubFilter().getName());
+
+ if(oldFilter != null) {
+ throw new PdfAsException("Filter allready registered");
+ }
+
+ filters.put(entry.getSubFilter().getName(), fitler);
+ logger.debug("Registered Filter: " + cls.getName() + " for " + entry.getFilter().getName() + "/" + entry.getSubFilter().getName());
+ }
+ } catch(Throwable e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public IVerifyFilter getVerifier(String filter, String subfilter) {
+ HashMap<String, IVerifyFilter> filters = filterMap.get(filter);
+ if(filters == null) {
+ return null;
+ }
+
+ return filters.get(subfilter);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifyResultImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifyResultImpl.java
new file mode 100644
index 00000000..451c1706
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/VerifyResultImpl.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.pdfas.lib.impl.verify;
+
+import iaik.x509.X509Certificate;
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.lib.api.verify.SignatureCheck;
+import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;
+
+public class VerifyResultImpl implements VerifyResult {
+
+ private boolean verificationDone;
+ private boolean qualifiedCertificate;
+ private PdfAsException verificationException;
+ private SignatureCheck certificateCheck;
+ private SignatureCheck valueCheck;
+ private SignatureCheck manifestCheck;
+
+ private X509Certificate signerCertificate;
+
+ public boolean isVerificationDone() {
+ return verificationDone;
+ }
+
+ public void setVerificationDone(boolean value) {
+ this.verificationDone = value;
+ }
+
+ public PdfAsException getVerificationException() {
+ return verificationException;
+ }
+
+ public void setVerificationException(PdfAsException e) {
+ verificationException = e;
+ }
+
+ public SignatureCheck getCertificateCheck() {
+ return certificateCheck;
+ }
+
+ public void setCertificateCheck(SignatureCheck certificateCheck) {
+ this.certificateCheck=certificateCheck;
+ }
+
+ public SignatureCheck getValueCheckCode() {
+ return valueCheck;
+ }
+
+ public void setValueCheckCode(SignatureCheck valueCheck) {
+ this.valueCheck=valueCheck;
+ }
+
+ public SignatureCheck getManifestCheckCode() {
+ return manifestCheck;
+ }
+
+ public void setManifestCheckCode(SignatureCheck manifestCheck) {
+ this.manifestCheck=manifestCheck;
+ }
+
+ public boolean isQualifiedCertificate() {
+ return qualifiedCertificate;
+ }
+
+ public void setQualifiedCertificate(boolean value) {
+ this.qualifiedCertificate = value;
+ }
+
+ public X509Certificate getSignerCertificate() {
+ return signerCertificate;
+ }
+
+ public void setSignerCertificate(X509Certificate signerCertificate) {
+ this.signerCertificate = signerCertificate;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/package-info.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/package-info.java
new file mode 100644
index 00000000..393a65b4
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author afitzek
+ *
+ */
+package at.gv.egiz.pdfas.lib.impl.verify; \ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index f439cf3c..4e98475c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,2 @@
-include "pdf-as-common", "stamper:stmp-itext", "signature-standards:sigs-pades", "pdf-as-lib", "pdf-as-cli"
+include "pdf-as-common", "stamper:stmp-itext", "signature-standards:sigs-pcks7detached", "signature-standards:sigs-pades", "pdf-as-lib", "pdf-as-cli"
diff --git a/signature-standards/sigs-pcks7detached/.gitignore b/signature-standards/sigs-pcks7detached/.gitignore
new file mode 100644
index 00000000..5e56e040
--- /dev/null
+++ b/signature-standards/sigs-pcks7detached/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/signature-standards/sigs-pcks7detached/build.gradle b/signature-standards/sigs-pcks7detached/build.gradle
new file mode 100644
index 00000000..cc0a4e33
--- /dev/null
+++ b/signature-standards/sigs-pcks7detached/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'java'
+apply plugin: 'eclipse'
+
+jar {
+ manifest {
+ attributes 'Implementation-Title': 'Signature Standard PKCS7 Detached', 'Implementation-Version': version
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile project (':pdf-as-lib')
+ compile project (':pdf-as-common')
+ compile group: 'iaik', name: 'iaik_cms', version: '4.1-moa'
+ compile group: 'eu.europa.ec.joinup.egovlabs.pdf-as.iaik', name: 'iaik_jce_eval_signed', version: '4.0'
+ compile group: 'eu.europa.ec.joinup.egovlabs.pdf-as.iaik', name: 'iaik_ecc_eval_signed', version: '2.19'
+ compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
+ testCompile group: 'junit', name: 'junit', version: '4.+'
+}
+
+test {
+ systemProperties 'property': 'value'
+}
+
+uploadArchives {
+ repositories {
+ flatDir {
+ dirs 'repos'
+ }
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java
index 85697436..864a31d1 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java
+++ b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java
@@ -1,4 +1,4 @@
-package at.gv.egiz.pdfas.lib.impl.signing.sig_interface;
+package at.gv.egiz.pdfas.sigs.pkcs7detached;
import iaik.asn1.structures.AlgorithmID;
import iaik.cms.SignedDataStream;
@@ -19,17 +19,19 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
+import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.exceptions.SignatureException;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner;
-public class JKSSigner implements IPlainSigner {
+public class PKCS7DetachedSigner implements IPlainSigner {
PrivateKey privKey;
X509Certificate cert;
- public JKSSigner(String file, String alias, String kspassword,
+ public PKCS7DetachedSigner(String file, String alias, String kspassword,
String keypassword, String type) throws PdfAsException {
try {
IAIK.getInstance();
@@ -75,4 +77,12 @@ public class JKSSigner implements IPlainSigner {
}
}
+ public String getPDFSubFilter() {
+ return PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED.getName();
+ }
+
+ public String getPDFFilter() {
+ return PDSignature.FILTER_ADOBE_PPKLITE.getName();
+ }
+
}
diff --git a/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedVerifier.java b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedVerifier.java
new file mode 100644
index 00000000..7807850b
--- /dev/null
+++ b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedVerifier.java
@@ -0,0 +1,74 @@
+package at.gv.egiz.pdfas.sigs.pkcs7detached;
+
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.x509.X509Certificate;
+
+import java.io.ByteArrayInputStream;
+import java.security.SignatureException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.lib.impl.verify.FilterEntry;
+import at.gv.egiz.pdfas.lib.impl.verify.IVerifyFilter;
+import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl;
+
+public class PKCS7DetachedVerifier implements IVerifyFilter {
+
+ private static final Logger logger = LoggerFactory.getLogger(PKCS7DetachedVerifier.class);
+
+ public List<VerifyResult> verify(byte[] contentData, byte[] signatureContent)
+ throws PdfAsException {
+ try {
+ List<VerifyResult> result = new ArrayList<VerifyResult>();
+ SignedData signedData = new SignedData(new ByteArrayInputStream(
+ signatureContent));
+ signedData.setContent(contentData);
+
+ // get the signer infos
+ SignerInfo[] signerInfos = signedData.getSignerInfos();
+ // verify the signatures
+ for (int i = 0; i < signerInfos.length; i++) {
+ VerifyResultImpl verifyResult = new VerifyResultImpl();
+ try {
+
+ // verify the signature for SignerInfo at index i
+ X509Certificate signer_cert = signedData.verify(i);
+ // if the signature is OK the certificate of the
+ // signer is returned
+ logger.info("Signature OK from signer: "
+ + signer_cert.getSubjectDN());
+ verifyResult.setSignerCertificate(signer_cert);
+ } catch (SignatureException ex) {
+ // if the signature is not OK a SignatureException
+ // is thrown
+ logger.info("Signature ERROR from signer: "
+ + signedData.getCertificate(
+ signerInfos[i].getSignerIdentifier())
+ .getSubjectDN());
+
+ verifyResult.setSignerCertificate(
+ signedData.getCertificate(signerInfos[i].getSignerIdentifier()));
+ }
+ result.add(verifyResult);
+ }
+
+ return result;
+ } catch (Throwable e) {
+ throw new PdfAsException("Verify failed", e);
+ }
+ }
+
+ public List<FilterEntry> getFiters() {
+ List<FilterEntry> result = new ArrayList<FilterEntry>();
+ result.add(new FilterEntry(PDSignature.FILTER_ADOBE_PPKLITE, PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED));
+ return result;
+ }
+
+}
diff --git a/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/package-info.java b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/package-info.java
new file mode 100644
index 00000000..69a99830
--- /dev/null
+++ b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author afitzek
+ *
+ */
+package at.gv.egiz.pdfas.sigs.pkcs7detached; \ No newline at end of file