/** * 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."); } }
/** * 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; }
/** * Checks the certificates in a certificate chain: are they valid on a specific date, and do they * chain up correctly? * * @param chain * @throws GeneralSecurityException */ public void verifyChain(Certificate[] chain) throws GeneralSecurityException { // Loop over the certificates in the chain for (int i = 0; i < chain.length; i++) { X509Certificate cert = (X509Certificate) chain[i]; // check if the certificate was/is valid cert.checkValidity(signDate); // check if the previous certificate was issued by this certificate if (i > 0) chain[i - 1].verify(chain[i].getPublicKey()); } LOGGER.info("All certificates are valid on " + signDate.toString()); }
/** * 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)); }
/** * Parses content read from a java.io.Reader object. * * @param reader the content * @throws IOException */ public void parse(final Reader reader) throws IOException { LOGGER.info( "Please note, there is a more extended version of the HTMLWorker available in the iText XMLWorker"); SimpleXMLParser.parse(this, null, reader, true); }