/** * Switches to the previous revision. * * @throws IOException * @throws GeneralSecurityException */ public void switchToPreviousRevision() throws IOException, GeneralSecurityException { LOGGER.info("Switching to previous revision."); latestRevision = false; dss = reader.getCatalog().getAsDict(PdfName.DSS); Calendar cal = pkcs7.getTimeStampDate(); if (cal == null) cal = pkcs7.getSignDate(); // TODO: get date from signature signDate = cal.getTime(); List<String> names = fields.getSignatureNames(); if (names.size() > 1) { signatureName = names.get(names.size() - 2); reader = new PdfReader(fields.extractRevision(signatureName)); this.fields = reader.getAcroFields(); names = fields.getSignatureNames(); signatureName = names.get(names.size() - 1); pkcs7 = coversWholeDocument(); LOGGER.info( String.format( "Checking %ssignature %s", pkcs7.isTsp() ? "document-level timestamp " : "", signatureName)); } else { LOGGER.info("No signatures in revision"); pkcs7 = null; } }
/** * Checks if the signature covers the whole document and throws an exception if the document was * altered * * @return a PdfPKCS7 object * @throws GeneralSecurityException */ protected PdfPKCS7 coversWholeDocument() throws GeneralSecurityException { PdfPKCS7 pkcs7 = fields.verifySignature(signatureName); if (fields.signatureCoversWholeDocument(signatureName)) { LOGGER.info("The timestamp covers whole document."); } else { throw new VerificationException(null, "Signature doesn't cover whole document."); } if (pkcs7.verify()) { LOGGER.info("The signed document has not been modified."); return pkcs7; } else { throw new VerificationException( null, "The document was altered after the final signature was applied."); } }
/** * Creates a VerificationData object for a PdfReader * * @param reader a reader for the document we want to verify. * @throws GeneralSecurityException */ public LtvVerifier(PdfReader reader) throws GeneralSecurityException { super(null); this.reader = reader; this.fields = reader.getAcroFields(); List<String> names = fields.getSignatureNames(); signatureName = names.get(names.size() - 1); this.signDate = new Date(); pkcs7 = coversWholeDocument(); LOGGER.info( String.format( "Checking %ssignature %s", pkcs7.isTsp() ? "document-level timestamp " : "", signatureName)); }
/** * Verifies a document level timestamp. * * @throws GeneralSecurityException * @throws IOException */ public List<VerificationOK> verifySignature() throws GeneralSecurityException, IOException { LOGGER.info("Verifying signature."); List<VerificationOK> result = new ArrayList<VerificationOK>(); // Get the certificate chain Certificate[] chain = pkcs7.getSignCertificateChain(); verifyChain(chain); // how many certificates in the chain do we need to check? int total = 1; if (CertificateOption.WHOLE_CHAIN.equals(option)) { total = chain.length; } // loop over the certificates X509Certificate signCert; X509Certificate issuerCert; for (int i = 0; i < total; ) { // the certificate to check signCert = (X509Certificate) chain[i++]; // its issuer issuerCert = null; if (i < chain.length) issuerCert = (X509Certificate) chain[i]; // now lets verify the certificate LOGGER.info(signCert.getSubjectDN().getName()); List<VerificationOK> list = verify(signCert, issuerCert, signDate); if (list.size() == 0) { try { signCert.verify(signCert.getPublicKey()); if (latestRevision && chain.length > 1) { list.add( new VerificationOK( signCert, this.getClass(), "Root certificate in final revision")); } if (list.size() == 0 && verifyRootCertificate) { throw new GeneralSecurityException(); } else if (chain.length > 1) list.add( new VerificationOK( signCert, this.getClass(), "Root certificate passed without checking")); } catch (GeneralSecurityException e) { throw new VerificationException( signCert, "Couldn't verify with CRL or OCSP or trusted anchor"); } } result.addAll(list); } // go to the previous revision switchToPreviousRevision(); return result; }