From 7b402478784fe7237ade7c32d07f034fd7083bb7 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Mon, 24 Nov 2014 15:45:18 +0100 Subject: verification changes --- .../pdfas/lib/impl/verify/IntegrityVerifier.java | 122 ++++++++++++++---- .../at/gv/egiz/pdfas/lib/util/SignatureUtils.java | 136 +++++++++++++++------ 2 files changed, 192 insertions(+), 66 deletions(-) (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IntegrityVerifier.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IntegrityVerifier.java index bb0f3268..9142bc68 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IntegrityVerifier.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IntegrityVerifier.java @@ -2,9 +2,12 @@ package at.gv.egiz.pdfas.lib.impl.verify; import iaik.asn1.ObjectID; import iaik.asn1.structures.AlgorithmID; +import iaik.asn1.structures.Attribute; import iaik.cms.ContentInfo; import iaik.cms.SignedData; import iaik.cms.SignerInfo; +import iaik.smime.ess.SigningCertificate; +import iaik.smime.ess.SigningCertificateV2; import iaik.x509.X509Certificate; import java.io.ByteArrayInputStream; @@ -16,6 +19,7 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException; import at.gv.egiz.pdfas.lib.api.Configuration; @@ -26,25 +30,25 @@ public class IntegrityVerifier implements IVerifier { private static final Logger logger = LoggerFactory .getLogger(IntegrityVerifier.class); - + public List verify(byte[] signature, byte[] signatureContent, Date verificationTime) throws PdfAsException { try { List result = new ArrayList(); - - SignedData signedData = new SignedData(signatureContent, new AlgorithmID[] { - AlgorithmID.sha256, AlgorithmID.sha1, AlgorithmID.ripeMd160, AlgorithmID.ripeMd160_ISO - }); - ContentInfo ci = new ContentInfo(new ByteArrayInputStream(signature - )); + + SignedData signedData = new SignedData(signatureContent, + new AlgorithmID[] { AlgorithmID.sha256, AlgorithmID.sha1, + AlgorithmID.ripeMd160, AlgorithmID.ripeMd160_ISO }); + ContentInfo ci = new ContentInfo( + new ByteArrayInputStream(signature)); if (!ci.getContentType().equals(ObjectID.cms_signedData)) { throw new PdfAsException("error.pdf.verify.01"); } - //SignedData signedData = (SignedData)ci.getContent(); - //signedData.setContent(contentData); + // SignedData signedData = (SignedData)ci.getContent(); + // signedData.setContent(contentData); signedData.decode(ci.getContentInputStream()); - + // get the signer infos SignerInfo[] signerInfos = signedData.getSignerInfos(); // verify the signatures @@ -53,33 +57,97 @@ public class IntegrityVerifier implements IVerifier { try { // verify the signature for SignerInfo at index i X509Certificate signer_cert = signedData.verify(i); - logger.info("Signature Algo: {}, Digest {}", - signedData.getSignerInfos()[i].getSignatureAlgorithm(), + + // Verify signing Certificate + Attribute signedCertificate = signerInfos[0] + .getSignedAttribute(ObjectID.signingCertificate); + + if (signedCertificate == null) { + signedCertificate = signerInfos[0] + .getSignedAttribute(ObjectID.signingCertificateV2); + if (signedCertificate == null) { + logger.error("Signature ERROR missing signed Signing Certificate: "); + + throw new SignatureException("Signature ERROR missing signed Signing Certificate"); + } else { + // Validate signingCertificate2 + try { + SigningCertificateV2 signingCert = (SigningCertificateV2) signedCertificate + .getAttributeValue(); + + if (signingCert + .isSignerCertificate(signer_cert)) { + // OK + logger.debug("Found and verified SigningCertificateV2"); + } else { + logger.error("Signature ERROR certificate missmatch: "); + + throw new SignatureException("Signature ERROR certificate missmatch"); + } + } catch (Throwable e) { + logger.error("Signature ERROR wrong encoding for ESSCertIDv2"); + + throw new SignatureException("Signature ERROR wrong encoding for ESSCertIDv2"); + } + } + } else { + // Validate signingCertificate + try { + SigningCertificate signingCert = (SigningCertificate) signedCertificate + .getAttributeValue(); + if (signingCert.isSignerCertificate(signer_cert)) { + // OK + logger.debug("Found and verified SigningCertificate"); + } else { + logger.error("Signature ERROR certificate missmatch"); + + throw new SignatureException("Signature ERROR certificate missmatch"); + } + } catch (Throwable e) { + logger.error("Signature ERROR wrong encoding for ESSCertIDv2"); + + throw new SignatureException("Signature ERROR wrong encoding for ESSCertIDv2", e); + } + } + + logger.info("Signature Algo: {}, Digest {}", signedData + .getSignerInfos()[i].getSignatureAlgorithm(), signedData.getSignerInfos()[i].getDigestAlgorithm()); // 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); - verifyResult.setValueCheckCode(new SignatureCheckImpl(0, "OK")); - verifyResult.setManifestCheckCode(new SignatureCheckImpl(99, "not checked")); - verifyResult.setCertificateCheck(new SignatureCheckImpl(99, "not checked")); + verifyResult.setValueCheckCode(new SignatureCheckImpl(0, + "OK")); + verifyResult.setManifestCheckCode(new SignatureCheckImpl( + 99, "not checked")); + verifyResult.setCertificateCheck(new SignatureCheckImpl(99, + "not checked")); verifyResult.setVerificationDone(true); } 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(), ex); - - verifyResult.setSignerCertificate( - signedData.getCertificate(signerInfos[i].getSignerIdentifier())); - verifyResult.setValueCheckCode(new SignatureCheckImpl(1, "failed to check signature")); - verifyResult.setManifestCheckCode(new SignatureCheckImpl(99, "not checked")); - verifyResult.setCertificateCheck(new SignatureCheckImpl(99, "not checked")); + logger.info( + "Signature ERROR from signer: " + + signedData.getCertificate( + signerInfos[i] + .getSignerIdentifier()) + .getSubjectDN(), ex); + + verifyResult.setSignerCertificate(signedData + .getCertificate(signerInfos[i] + .getSignerIdentifier())); + verifyResult.setValueCheckCode(new SignatureCheckImpl(1, + "failed to check signature")); + verifyResult.setManifestCheckCode(new SignatureCheckImpl( + 99, "not checked")); + verifyResult.setCertificateCheck(new SignatureCheckImpl(99, + "not checked")); verifyResult.setVerificationDone(false); - verifyResult.setVerificationException(new PdfAsSignatureException("failed to check signature", ex)); + verifyResult + .setVerificationException(new PdfAsSignatureException( + "failed to check signature", ex)); } result.add(verifyResult); } @@ -91,7 +159,7 @@ public class IntegrityVerifier implements IVerifier { } public void setConfiguration(Configuration config) { - + } @Override diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java index 14dbdd16..ef5df8b1 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java @@ -1,19 +1,30 @@ package at.gv.egiz.pdfas.lib.util; +import iaik.asn1.CodingException; +import iaik.asn1.ObjectID; +import iaik.asn1.structures.Attribute; import iaik.cms.CMSException; import iaik.cms.SignedData; import iaik.cms.SignerInfo; +import iaik.smime.ess.ESSCertID; +import iaik.smime.ess.ESSCertIDv2; +import iaik.smime.ess.SigningCertificate; +import iaik.smime.ess.SigningCertificateV2; import iaik.x509.X509Certificate; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.security.SignatureException; +import java.security.cert.CertificateException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.exceptions.ErrorConstants; import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException; +import at.gv.egiz.pdfas.common.utils.StreamUtils; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; @@ -21,66 +32,113 @@ public class SignatureUtils implements ErrorConstants { private static final Logger logger = LoggerFactory .getLogger(SignatureUtils.class); - - public static VerifyResult verifySignature(byte[] signature, byte[] input) throws PDFASError { - //List results = new ArrayList(); + + public static VerifyResult verifySignature(byte[] signature, byte[] input) + throws PDFASError { + // List results = new ArrayList(); try { SignedData signedData = new SignedData(new ByteArrayInputStream( signature)); signedData.setContent(input); - + // get the signer infos SignerInfo[] signerInfos = signedData.getSignerInfos(); if (signerInfos.length == 0) { logger.error("Invalid signature (no signer information)"); throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG); } - + if (signerInfos.length != 1) { logger.error("Invalid signature (multiple signer information)"); throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG); } // verify the signatures - //for (int i = 0; i < signerInfos.length; i++) { - VerifyResultImpl verifyResult = new VerifyResultImpl(); - //results.add(verifyResult); - try { - logger.debug("Signature Algo: {}, Digest {}", signedData - .getSignerInfos()[0].getSignatureAlgorithm(), - signedData.getSignerInfos()[0].getDigestAlgorithm()); - // verify the signature for SignerInfo at index i - X509Certificate signer_cert = signedData.verify(0); - // if the signature is OK the certificate of the - // signer is returned - logger.debug("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.error( - "Signature ERROR from signer: " - + signedData.getCertificate( - signerInfos[0] - .getSignerIdentifier()) - .getSubjectDN(), ex); - - verifyResult.setSignerCertificate(signedData - .getCertificate(signerInfos[0] - .getSignerIdentifier())); - throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, ex); + // for (int i = 0; i < signerInfos.length; i++) { + VerifyResultImpl verifyResult = new VerifyResultImpl(); + // results.add(verifyResult); + try { + logger.debug("Signature Algo: {}, Digest {}", + signedData.getSignerInfos()[0].getSignatureAlgorithm(), + signedData.getSignerInfos()[0].getDigestAlgorithm()); + // verify the signature for SignerInfo at index i + X509Certificate signer_cert = signedData.verify(0); + + // Must include Signing Certificate! + Attribute signedCertificate = signerInfos[0] + .getSignedAttribute(ObjectID.signingCertificate); + + if (signedCertificate == null) { + signedCertificate = signerInfos[0] + .getSignedAttribute(ObjectID.signingCertificateV2); + if (signedCertificate == null) { + logger.error("Signature ERROR missing signed Signing Certificate: "); + + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG); + } else { + // Validate signingCertificate2 + try { + SigningCertificateV2 signingCert = (SigningCertificateV2)signedCertificate.getAttributeValue(); + + if (signingCert.isSignerCertificate(signer_cert)) { + // OK + logger.debug("Found and verified SigningCertificateV2"); + } else { + logger.error("Signature ERROR certificate missmatch: "); + + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG); + } + } catch (Throwable e) { + logger.error("Signature ERROR wrong encoding for ESSCertIDv2:"); + + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, e); + } + } + } else { + // Validate signingCertificate + try { + SigningCertificate signingCert = (SigningCertificate)signedCertificate.getAttributeValue(); + if (signingCert.isSignerCertificate(signer_cert)) { + // OK + logger.debug("Found and verified SigningCertificate"); + } else { + logger.error("Signature ERROR certificate missmatch"); + + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG); + } + } catch (Throwable e) { + logger.error("Signature ERROR wrong encoding for ESSCertIDv2"); + + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, e); + } } - - return verifyResult; - //} + + // if the signature is OK the certificate of the + // signer is returned + logger.debug("Signature OK"); + verifyResult.setSignerCertificate(signer_cert); + + } catch (SignatureException ex) { + // if the signature is not OK a SignatureException + // is thrown + logger.error( + "Signature ERROR from signer: " + + signedData.getCertificate( + signerInfos[0].getSignerIdentifier()) + .getSubjectDN(), ex); + + verifyResult.setSignerCertificate(signedData + .getCertificate(signerInfos[0].getSignerIdentifier())); + throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, ex); + } + + return verifyResult; + // } } catch (CMSException e) { throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, e); } catch (IOException e) { throw new PDFASError(ERROR_SIG_INVALID_BKU_SIG, e); } - - + } } -- cgit v1.2.3