From 48216bdf6d0e6b8e34d53fe196c4a6a7ec868b93 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Wed, 27 Nov 2013 17:52:36 +0100 Subject: Current working stuff not working --- .../java/at/gv/egiz/pdfas/cli/DeveloperMain.java | 18 +-- .../java/at/gv/egiz/sl/util/BKUSLConnector.java | 2 +- .../java/at/gv/egiz/sl/util/BaseSLConnector.java | 7 +- .../egiz/sl/util/ISignatureConnectorSLWrapper.java | 59 ++++++++- .../at/gv/egiz/pdfas/sigs/pades/PAdESSigner.java | 1 + .../sigs-pcks7detached/build.gradle | 2 + .../sigs/pkcs7detached/PKCS7DetachedSigner.java | 146 +++++++++++++++++---- .../sigs/pkcs7detached/PKCS7DetachedVerifier.java | 28 +++- 8 files changed, 214 insertions(+), 49 deletions(-) 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 ed029aac..3c4cc223 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 @@ -29,8 +29,8 @@ public class DeveloperMain { public static final String keyStoreFile = "/home/afitzek/devel/pdfas_neu/test.p12"; public static final String keyStoreType = "PKCS12"; public static final String keyStorePass = "123456"; - //public static final String keyAlias = "pdf"; - public static final String keyAlias = "ecc_test"; + public static final String keyAlias = "pdf"; + //public static final String keyAlias = "ecc_test"; public static final String keyPass = "123456"; public static void main(String[] args) { @@ -44,13 +44,13 @@ public class DeveloperMain { data = StreamUtils.inputStreamToByteArray(new FileInputStream("/home/afitzek/qr_2.pdf")); SignParameter parameter = PdfAsFactory.createSignParameter(config, new ByteArrayDataSource(data)); ByteArrayDataSink bads = new ByteArrayDataSink(); - parameter.setSignatureProfileId("SIGNATURBLOCK_DE_PDFA"); + parameter.setSignatureProfileId("SIGNATURBLOCK_DE"); parameter.setOutput(bads); - //parameter.setPlainSigner(new PAdESSigner(new BKUSLConnector(config))); - parameter.setPlainSigner(signer); + parameter.setPlainSigner(new PAdESSigner(new BKUSLConnector(config))); + //parameter.setPlainSigner(signer); //parameter.setPlainSigner(new PAdESSigner(new MOAConnector(config))); - - /*StatusRequest request = pdfas.startSign(parameter); + /* + StatusRequest request = pdfas.startSign(parameter); if(request.needCertificate()) { request.setCertificate(signer.getCertificate().getEncoded()); @@ -82,8 +82,8 @@ public class DeveloperMain { fos.write(bads.getData()); fos.close(); - //VerifyParameter verify = new VerifyParameterImpl(config, new ByteArrayDataSource(bads.getData())); - //pdfas.verify(verify); + VerifyParameter verify = new VerifyParameterImpl(config, new ByteArrayDataSource(bads.getData())); + pdfas.verify(verify); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BKUSLConnector.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BKUSLConnector.java index deecae21..414f2854 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BKUSLConnector.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BKUSLConnector.java @@ -130,7 +130,7 @@ public class BKUSLConnector extends BaseSLConnector { try { slRequest = SLMarschaller.marshalToString(of .createCreateCMSSignatureRequest(request)); - logger.debug(slRequest); + //logger.debug(slRequest); String slResponse = performHttpRequestToBKU(slRequest); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BaseSLConnector.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BaseSLConnector.java index e5abc6bd..5a03bbef 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BaseSLConnector.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/BaseSLConnector.java @@ -59,7 +59,7 @@ public abstract class BaseSLConnector implements ISLConnector { int currentdataOff = 0; Arrays.fill(data, (byte)0); - + int[] exclude_range = new int[byteRange.length-2]; for(int i = 0; i < byteRange.length; i = i + 2) { int offset = byteRange[i]; int size = byteRange[i+1]; @@ -68,7 +68,10 @@ public abstract class BaseSLConnector implements ISLConnector { data[offset + j] = signatureData[currentdataOff]; currentdataOff++; } - + if(i + 2 < byteRange.length) { + exclude_range[i] = offset + size; // exclude offset + exclude_range[i+1] = byteRange[i+2]; // exclude size + } } // == MetaInfoType diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java index 8a7950a4..3a998816 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java @@ -1,11 +1,19 @@ package at.gv.egiz.sl.util; +import java.io.ByteArrayInputStream; +import java.security.SignatureException; import java.security.cert.CertificateException; import java.util.Iterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; import iaik.x509.X509Certificate; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; import at.gv.egiz.sl.CreateCMSSignatureRequestType; import at.gv.egiz.sl.CreateCMSSignatureResponseType; import at.gv.egiz.sl.InfoboxAssocArrayPairType; @@ -14,12 +22,15 @@ import at.gv.egiz.sl.InfoboxReadResponseType; public class ISignatureConnectorSLWrapper implements ISignatureConnector { + private static final Logger logger = LoggerFactory + .getLogger(ISignatureConnectorSLWrapper.class); + private ISLConnector connector; - + public ISignatureConnectorSLWrapper(ISLConnector connector) { this.connector = connector; } - + public X509Certificate getCertificate() throws PdfAsException { X509Certificate certificate = null; try { @@ -47,9 +58,47 @@ public class ISignatureConnectorSLWrapper implements ISignatureConnector { } public byte[] sign(byte[] input, int[] byteRange) throws PdfAsException { - CreateCMSSignatureRequestType request = connector.createCMSRequest(input, byteRange); - CreateCMSSignatureResponseType response = connector.sendCMSRequest(request); - + CreateCMSSignatureRequestType request = connector.createCMSRequest( + input, byteRange); + CreateCMSSignatureResponseType response = connector + .sendCMSRequest(request); + try { + SignedData signedData = new SignedData(new ByteArrayInputStream( + response.getCMSSignature())); + + signedData.setContent(input); + + // 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())); + } + } + } catch (Exception e) { + logger.error("ERROR", e); + } + return response.getCMSSignature(); } diff --git a/signature-standards/sigs-pades/src/main/java/at/gv/egiz/pdfas/sigs/pades/PAdESSigner.java b/signature-standards/sigs-pades/src/main/java/at/gv/egiz/pdfas/sigs/pades/PAdESSigner.java index 7fc0081b..6945d9b3 100644 --- a/signature-standards/sigs-pades/src/main/java/at/gv/egiz/pdfas/sigs/pades/PAdESSigner.java +++ b/signature-standards/sigs-pades/src/main/java/at/gv/egiz/pdfas/sigs/pades/PAdESSigner.java @@ -32,6 +32,7 @@ public class PAdESSigner implements IPlainSigner { public String getPDFSubFilter() { return PDSignature.SUBFILTER_ETSI_CADES_DETACHED.getName(); + //return PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED.getName(); } public String getPDFFilter() { diff --git a/signature-standards/sigs-pcks7detached/build.gradle b/signature-standards/sigs-pcks7detached/build.gradle index 6864bc00..d1ea063f 100644 --- a/signature-standards/sigs-pcks7detached/build.gradle +++ b/signature-standards/sigs-pcks7detached/build.gradle @@ -19,6 +19,8 @@ dependencies { 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' + compile group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46' + compile group: 'org.bouncycastle', name: 'bcmail-jdk16', version: '1.46' testCompile group: 'junit', name: 'junit', version: '4.+' } 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 index 25b42f5f..4c4b3621 100644 --- 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 @@ -1,40 +1,54 @@ package at.gv.egiz.pdfas.sigs.pkcs7detached; +import iaik.asn1.ASN1Object; +import iaik.asn1.ObjectID; import iaik.asn1.structures.AlgorithmID; -import iaik.cms.SignedDataStream; +import iaik.asn1.structures.Attribute; +import iaik.asn1.structures.ChoiceOfTime; +import iaik.cms.ContentInfo; +import iaik.cms.IssuerAndSerialNumber; +import iaik.cms.SignedData; import iaik.cms.SignerInfo; -import iaik.cms.SubjectKeyID; +import iaik.cms.Utils; 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.io.OutputStream; import java.security.KeyStore; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; +import java.util.Date; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessable; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import at.gv.egiz.pdfas.common.exceptions.PDFIOException; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException; +import at.gv.egiz.pdfas.common.utils.StringUtils; import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; public class PKCS7DetachedSigner implements IPlainSigner { + private static final Logger logger = LoggerFactory + .getLogger(PKCS7DetachedSigner.class); + PrivateKey privKey; X509Certificate cert; public PKCS7DetachedSigner(String file, String alias, String kspassword, String keypassword, String type) throws PdfAsException { try { - IAIK.getInstance(); + IAIK.addAsProvider(); ECCProvider.addAsProvider(); KeyStore ks = KeyStore.getInstance(type); ks.load(new FileInputStream(file), kspassword.toCharArray()); @@ -49,40 +63,114 @@ public class PKCS7DetachedSigner implements IPlainSigner { return cert; } + class CMSProcessableInputStream implements CMSProcessable { + + InputStream in; + + public CMSProcessableInputStream(InputStream is) { + in = is; + } + + public Object getContent() { + return null; + } + + public void write(OutputStream out) throws IOException, CMSException { + // read the content only one time + byte[] buffer = new byte[8 * 1024]; + int read; + while ((read = in.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + in.close(); + } + } + + private static BouncyCastleProvider provider = new BouncyCastleProvider(); + + /* + * public byte[] sign(byte[] input, int[] byteRange) throws PdfAsException { + * CMSProcessableInputStream content = new CMSProcessableInputStream(new + * ByteArrayInputStream(input)); CMSSignedDataGenerator gen = new + * CMSSignedDataGenerator(); // CertificateChain List + * certList = Arrays.asList(cert); + * + * CertStore certStore = null; try { certStore = + * CertStore.getInstance("Collection", new + * CollectionCertStoreParameters(certList), provider); + * gen.addSigner(privKey, (X509Certificate)certList.get(0), + * CMSSignedGenerator.DIGEST_SHA256); gen.addCertificatesAndCRLs(certStore); + * CMSSignedData signedData = gen.generate(content, false, provider); return + * signedData.getEncoded(); } catch (Exception e) { // should be handled + * e.printStackTrace(); } throw new + * RuntimeException("Problem while preparing signature"); } + */ + public byte[] sign(byte[] input, int[] byteRange) throws PdfAsException { 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 - } + // 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 + // } + // } + // SubjectKeyID subjectKeyId = new SubjectKeyID(cert); + try { + MessageDigest md = MessageDigest.getInstance("SHA256", "IAIK"); + md.update(input); + byte[] sha256 = md.digest(); + logger.info("Message digest: " + StringUtils.bytesToHexString(sha256)); + } catch (Exception e) { + e.printStackTrace(); } - signed_data_stream.writeTo(baos); - return baos.toByteArray(); + IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(cert); + SignerInfo signer1 = new SignerInfo(issuer, AlgorithmID.sha256, + privKey); + + SignedData si = new SignedData(input, SignedData.EXPLICIT); + si.addCertificates(new Certificate[] { cert }); + Attribute signingTime = new Attribute(ObjectID.signingTime, + new ASN1Object[] { new ChoiceOfTime(new Date()) + .toASN1Object() }); + // Attribute signingCert = new + // Attribute(ObjectID.signingCertificateV2, + // new ASN1Object[] { cert.toASN1Object() }); + + Attribute[] attributes = new Attribute[] { signingTime }; + signer1.setSignedAttributes(attributes); + si.addSignerInfo(signer1); + InputStream dataIs = si.getInputStream(); + byte[] buf = new byte[1024]; + int r; + while ((r = dataIs.read(buf)) > 0) + ; // skip data + ContentInfo ci = new ContentInfo(si); + + return ci.getEncoded(); } catch (NoSuchAlgorithmException e) { throw new PdfAsSignatureException("", e); - } catch (X509ExtensionException e) { + } catch (iaik.cms.CMSException e) { + throw new PdfAsSignatureException("", e); + } catch (IOException e) { throw new PdfAsSignatureException("", e); - } catch (IOException e) { - throw new PDFIOException("", 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 index 7e974f3f..e8f0661b 100644 --- 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 @@ -1,10 +1,14 @@ package at.gv.egiz.pdfas.sigs.pkcs7detached; +import iaik.asn1.ObjectID; +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.ContentInfo; import iaik.cms.SignedData; import iaik.cms.SignerInfo; import iaik.x509.X509Certificate; import java.io.ByteArrayInputStream; +import java.io.FileOutputStream; import java.security.SignatureException; import java.util.ArrayList; import java.util.List; @@ -24,21 +28,38 @@ public class PKCS7DetachedVerifier implements IVerifyFilter { private static final Logger logger = LoggerFactory.getLogger(PKCS7DetachedVerifier.class); + public PKCS7DetachedVerifier() { + } + public List verify(byte[] contentData, byte[] signatureContent) throws PdfAsException { try { List result = new ArrayList(); - SignedData signedData = new SignedData(new ByteArrayInputStream( + + SignedData signedData = new SignedData(contentData, new AlgorithmID[] { + AlgorithmID.sha256 + }); + + FileOutputStream fos = new FileOutputStream("/tmp/verify.bin"); + fos.write(signatureContent); + fos.close(); + + ContentInfo ci = new ContentInfo(new ByteArrayInputStream( signatureContent)); - signedData.setContent(contentData); + if (!ci.getContentType().equals(ObjectID.cms_signedData)) { + throw new PdfAsException("No Signed DATA"); + } + //SignedData signedData = (SignedData)ci.getContent(); + //signedData.setContent(contentData); + signedData.decode(ci.getContentInputStream()); + // 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 @@ -69,6 +90,7 @@ public class PKCS7DetachedVerifier implements IVerifyFilter { public List getFiters() { List result = new ArrayList(); result.add(new FilterEntry(PDSignature.FILTER_ADOBE_PPKLITE, PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED)); + result.add(new FilterEntry(PDSignature.FILTER_ADOBE_PPKLITE, PDSignature.SUBFILTER_ETSI_CADES_DETACHED)); return result; } -- cgit v1.2.3