aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/gv/egiz/pdfas
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas')
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/IntegrityVerifier.java122
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java136
2 files changed, 192 insertions, 66 deletions
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<VerifyResult> verify(byte[] signature, byte[] signatureContent,
Date verificationTime) throws PdfAsException {
try {
List<VerifyResult> result = new ArrayList<VerifyResult>();
-
- 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<VerifyResult> results = new ArrayList<VerifyResult>();
+
+ public static VerifyResult verifySignature(byte[] signature, byte[] input)
+ throws PDFASError {
+ // List<VerifyResult> results = new ArrayList<VerifyResult>();
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);
}
-
-
+
}
}