Search in sources :

Example 1 with COSFilterInputStream

use of org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream in project pdfbox by apache.

the class ShowSignature method showSignature.

private void showSignature(String[] args) throws IOException, GeneralSecurityException, TSPException, CertificateVerificationException {
    if (args.length != 2) {
        usage();
    } else {
        String password = args[0];
        File infile = new File(args[1]);
        // use old-style document loading to disable leniency
        // see also https://www.pdf-insecurity.org/
        RandomAccessReadBufferedFile raFile = new RandomAccessReadBufferedFile(infile);
        // If your files are not too large, you can also download the PDF into a byte array
        // with IOUtils.toByteArray() and pass a RandomAccessBuffer() object to the
        // PDFParser constructor.
        PDFParser parser = new PDFParser(raFile, password);
        try (PDDocument document = parser.parse(false)) {
            for (PDSignature sig : document.getSignatureDictionaries()) {
                COSDictionary sigDict = sig.getCOSObject();
                byte[] contents = sig.getContents();
                // we're doing this as a stream, to be able to handle huge files
                try (FileInputStream fis = new FileInputStream(infile);
                    InputStream signedContentAsStream = new COSFilterInputStream(fis, sig.getByteRange())) {
                    System.out.println("Signature found");
                    if (sig.getName() != null) {
                        System.out.println("Name:     " + sig.getName());
                    }
                    if (sig.getSignDate() != null) {
                        System.out.println("Modified: " + sdf.format(sig.getSignDate().getTime()));
                    }
                    String subFilter = sig.getSubFilter();
                    if (subFilter != null) {
                        switch(subFilter) {
                            case "adbe.pkcs7.detached":
                            case "ETSI.CAdES.detached":
                                verifyPKCS7(signedContentAsStream, contents, sig);
                                break;
                            case "adbe.pkcs7.sha1":
                                {
                                    // example: PDFBOX-1452.pdf
                                    CertificateFactory factory = CertificateFactory.getInstance("X.509");
                                    ByteArrayInputStream certStream = new ByteArrayInputStream(contents);
                                    Collection<? extends Certificate> certs = factory.generateCertificates(certStream);
                                    System.out.println("certs=" + certs);
                                    @SuppressWarnings({ "squid:S5542", "lgtm [java/weak-cryptographic-algorithm]" }) MessageDigest md = MessageDigest.getInstance("SHA1");
                                    try (DigestInputStream dis = new DigestInputStream(signedContentAsStream, md)) {
                                        while (dis.read() != -1) {
                                        // do nothing
                                        }
                                    }
                                    byte[] hash = md.digest();
                                    verifyPKCS7(new ByteArrayInputStream(hash), contents, sig);
                                    break;
                                }
                            case "adbe.x509.rsa_sha1":
                                {
                                    // example: PDFBOX-2693.pdf
                                    COSString certString = (COSString) sigDict.getDictionaryObject(COSName.CERT);
                                    // TODO this could also be an array.
                                    if (certString == null) {
                                        System.err.println("The /Cert certificate string is missing in the signature dictionary");
                                        return;
                                    }
                                    byte[] certData = certString.getBytes();
                                    CertificateFactory factory = CertificateFactory.getInstance("X.509");
                                    ByteArrayInputStream certStream = new ByteArrayInputStream(certData);
                                    Collection<? extends Certificate> certs = factory.generateCertificates(certStream);
                                    System.out.println("certs=" + certs);
                                    X509Certificate cert = (X509Certificate) certs.iterator().next();
                                    try {
                                        if (sig.getSignDate() != null) {
                                            cert.checkValidity(sig.getSignDate().getTime());
                                            System.out.println("Certificate valid at signing time");
                                        } else {
                                            System.err.println("Certificate cannot be verified without signing time");
                                        }
                                    } catch (CertificateExpiredException ex) {
                                        System.err.println("Certificate expired at signing time");
                                    } catch (CertificateNotYetValidException ex) {
                                        System.err.println("Certificate not yet valid at signing time");
                                    }
                                    if (CertificateVerifier.isSelfSigned(cert)) {
                                        System.err.println("Certificate is self-signed, LOL!");
                                    } else {
                                        System.out.println("Certificate is not self-signed");
                                        if (sig.getSignDate() != null) {
                                            @SuppressWarnings("unchecked") Store<X509CertificateHolder> store = new JcaCertStore(certs);
                                            SigUtils.verifyCertificateChain(store, cert, sig.getSignDate().getTime());
                                        }
                                    }
                                    break;
                                }
                            case "ETSI.RFC3161":
                                // e.g. PDFBOX-1848, file_timestamped.pdf
                                verifyETSIdotRFC3161(signedContentAsStream, contents);
                                // verifyPKCS7(hash, contents, sig) does not work
                                break;
                            default:
                                System.err.println("Unknown certificate type: " + subFilter);
                                break;
                        }
                    } else {
                        throw new IOException("Missing subfilter for cert dictionary");
                    }
                    int[] byteRange = sig.getByteRange();
                    if (byteRange.length != 4) {
                        System.err.println("Signature byteRange must have 4 items");
                    } else {
                        long fileLen = infile.length();
                        long rangeMax = byteRange[2] + (long) byteRange[3];
                        // multiply content length with 2 (because it is in hex in the PDF) and add 2 for < and >
                        int contentLen = contents.length * 2 + 2;
                        if (fileLen != rangeMax || byteRange[0] != 0 || byteRange[1] + contentLen != byteRange[2]) {
                            // a false result doesn't necessarily mean that the PDF is a fake
                            // see this answer why:
                            // https://stackoverflow.com/a/48185913/535646
                            System.out.println("Signature does not cover whole document");
                        } else {
                            System.out.println("Signature covers whole document");
                        }
                        checkContentValueWithFile(infile, byteRange, contents);
                    }
                }
            }
            analyseDSS(document);
        } catch (CMSException | OperatorCreationException ex) {
            throw new IOException(ex);
        }
        System.out.println("Analyzed: " + args[1]);
    }
}
Also used : CertificateNotYetValidException(java.security.cert.CertificateNotYetValidException) CertificateExpiredException(java.security.cert.CertificateExpiredException) CollectionStore(org.bouncycastle.util.CollectionStore) KeyStore(java.security.KeyStore) Store(org.bouncycastle.util.Store) JcaCertStore(org.bouncycastle.cert.jcajce.JcaCertStore) JcaCertStore(org.bouncycastle.cert.jcajce.JcaCertStore) COSString(org.apache.pdfbox.cos.COSString) PDSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature) CertificateFactory(java.security.cert.CertificateFactory) RandomAccessReadBufferedFile(org.apache.pdfbox.io.RandomAccessReadBufferedFile) MessageDigest(java.security.MessageDigest) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) COSString(org.apache.pdfbox.cos.COSString) COSDictionary(org.apache.pdfbox.cos.COSDictionary) DigestInputStream(java.security.DigestInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) COSFilterInputStream(org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream) FileInputStream(java.io.FileInputStream) DigestInputStream(java.security.DigestInputStream) InputStream(java.io.InputStream) PDFParser(org.apache.pdfbox.pdfparser.PDFParser) COSFilterInputStream(org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) X509Certificate(java.security.cert.X509Certificate) ByteArrayInputStream(java.io.ByteArrayInputStream) PDDocument(org.apache.pdfbox.pdmodel.PDDocument) Collection(java.util.Collection) RandomAccessReadBufferedFile(org.apache.pdfbox.io.RandomAccessReadBufferedFile) File(java.io.File) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate) CMSException(org.bouncycastle.cms.CMSException)

Example 2 with COSFilterInputStream

use of org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream in project pdfbox by apache.

the class COSWriter method getDataToSign.

/**
 * Return the stream of PDF data to be signed. Clients should use this method only to create
 * signatures externally. {@link #write(PDDocument)} method should have been called prior. The
 * created signature should be set using {@link #writeExternalSignature(byte[])}.
 * <p>
 * When {@link SignatureInterface} instance is used, COSWriter obtains and writes the signature
 * itself.
 * </p>
 *
 * @return data stream to be signed
 * @throws IllegalStateException if PDF is not prepared for external signing
 * @throws IOException if input data is closed
 */
public InputStream getDataToSign() throws IOException {
    if (incrementPart == null || incrementalInput == null) {
        throw new IllegalStateException("PDF not prepared for signing");
    }
    // range of incremental bytes to be signed (includes /ByteRange but not /Contents)
    int incPartSigOffset = (int) (signatureOffset - incrementalInput.length());
    int afterSigOffset = incPartSigOffset + (int) signatureLength;
    int[] range = { 0, incPartSigOffset, afterSigOffset, incrementPart.length - afterSigOffset };
    return new SequenceInputStream(new RandomAccessInputStream(incrementalInput), new COSFilterInputStream(incrementPart, range));
}
Also used : SequenceInputStream(java.io.SequenceInputStream) COSFilterInputStream(org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream) RandomAccessInputStream(org.apache.pdfbox.io.RandomAccessInputStream)

Aggregations

COSFilterInputStream (org.apache.pdfbox.pdmodel.interactive.digitalsignature.COSFilterInputStream)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 SequenceInputStream (java.io.SequenceInputStream)1 DigestInputStream (java.security.DigestInputStream)1 KeyStore (java.security.KeyStore)1 MessageDigest (java.security.MessageDigest)1 Certificate (java.security.cert.Certificate)1 CertificateExpiredException (java.security.cert.CertificateExpiredException)1 CertificateFactory (java.security.cert.CertificateFactory)1 CertificateNotYetValidException (java.security.cert.CertificateNotYetValidException)1 X509Certificate (java.security.cert.X509Certificate)1 Collection (java.util.Collection)1 COSDictionary (org.apache.pdfbox.cos.COSDictionary)1 COSString (org.apache.pdfbox.cos.COSString)1 RandomAccessInputStream (org.apache.pdfbox.io.RandomAccessInputStream)1 RandomAccessReadBufferedFile (org.apache.pdfbox.io.RandomAccessReadBufferedFile)1