From 0876981fd70fdab07f7c3e1666cf77071b5fe03d Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Wed, 2 Oct 2013 10:28:30 +0200 Subject: + added PKCS7 detached siganture standard via keystore + added simple verification implementation --- signature-standards/sigs-pcks7detached/.gitignore | 1 + .../sigs-pcks7detached/build.gradle | 34 +++++++++ .../sigs/pkcs7detached/PKCS7DetachedSigner.java | 88 ++++++++++++++++++++++ .../sigs/pkcs7detached/PKCS7DetachedVerifier.java | 74 ++++++++++++++++++ .../pdfas/sigs/pkcs7detached/package-info.java | 8 ++ 5 files changed, 205 insertions(+) create mode 100644 signature-standards/sigs-pcks7detached/.gitignore create mode 100644 signature-standards/sigs-pcks7detached/build.gradle create mode 100644 signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java create mode 100644 signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedVerifier.java create mode 100644 signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/package-info.java (limited to 'signature-standards') 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/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java new file mode 100644 index 00000000..864a31d1 --- /dev/null +++ b/signature-standards/sigs-pcks7detached/src/main/java/at/gv/egiz/pdfas/sigs/pkcs7detached/PKCS7DetachedSigner.java @@ -0,0 +1,88 @@ +package at.gv.egiz.pdfas.sigs.pkcs7detached; + +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.SignedDataStream; +import iaik.cms.SignerInfo; +import iaik.cms.SubjectKeyID; +import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; +import iaik.x509.X509Certificate; +import iaik.x509.X509ExtensionException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +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 PKCS7DetachedSigner implements IPlainSigner { + + PrivateKey privKey; + X509Certificate cert; + + public PKCS7DetachedSigner(String file, String alias, String kspassword, + String keypassword, String type) throws PdfAsException { + try { + IAIK.getInstance(); + ECCProvider.addAsProvider(); + KeyStore ks = KeyStore.getInstance(type); + ks.load(new FileInputStream(file), kspassword.toCharArray()); + privKey = (PrivateKey) ks.getKey(alias, keypassword.toCharArray()); + cert = new X509Certificate(ks.getCertificate(alias).getEncoded()); + } catch (Throwable e) { + throw new PdfAsException("Failed to get KeyStore", e); + } + } + + public X509Certificate getCertificate() { + return cert; + } + + public byte[] sign(byte[] input) throws SignatureException, IOException { + try { + SignedDataStream signed_data_stream = new SignedDataStream( + new ByteArrayInputStream(input), SignedDataStream.EXPLICIT); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + signed_data_stream.addCertificates(new Certificate[] { cert }); + + SubjectKeyID subjectKeyId = new SubjectKeyID(cert); + SignerInfo signer1 = new SignerInfo(subjectKeyId, + AlgorithmID.sha256, privKey); + signed_data_stream.addSignerInfo(signer1); + InputStream data_is = signed_data_stream.getInputStream(); + if (signed_data_stream.getMode() == SignedDataStream.EXPLICIT) { + byte[] buf = new byte[1024]; + int r; + while ((r = data_is.read(buf)) > 0) { + // do something useful + } + } + signed_data_stream.writeTo(baos); + return baos.toByteArray(); + } catch (NoSuchAlgorithmException e) { + throw new SignatureException(e); + } catch (X509ExtensionException e) { + throw new SignatureException(e); + } + } + + 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 verify(byte[] contentData, byte[] signatureContent) + throws PdfAsException { + try { + List result = new ArrayList(); + 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 getFiters() { + List result = new ArrayList(); + 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 -- cgit v1.2.3