You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2017/06/07 15:40:40 UTC

svn commit: r1797952 - /pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java

Author: tilman
Date: Wed Jun  7 15:40:40 2017
New Revision: 1797952

URL: http://svn.apache.org/viewvc?rev=1797952&view=rev
Log:
PDFBOX-3017: detect self-signed certs, tell whether signature covers the whole file, slight refactor

Modified:
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java

Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java?rev=1797952&r1=1797951&r2=1797952&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java (original)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java Wed Jun  7 15:40:40 2017
@@ -24,6 +24,7 @@ import java.security.InvalidKeyException
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
+import java.security.PublicKey;
 import java.security.SignatureException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
@@ -93,8 +94,8 @@ public final class ShowSignature
         else
         {
             String password = args[0];
-            String infile = args[1];
-            try (PDDocument document = PDDocument.load(new File(infile), password))
+            File infile = new File(args[1]);
+            try (PDDocument document = PDDocument.load(infile, password))
             {
                 for (PDSignature sig : document.getSignatureDictionaries())
                 {
@@ -102,18 +103,36 @@ public final class ShowSignature
                     COSString contents = (COSString) sigDict.getDictionaryObject(COSName.CONTENTS);
 
                     // download the signed content
-                    FileInputStream fis = new FileInputStream(infile);
-                    byte[] buf = null;
-                    try
+                    byte[] buf;
+                    try (FileInputStream fis = new FileInputStream(infile))
                     {
                         buf = sig.getSignedContent(fis);
                     }
-                    finally
+
+                    System.out.println("Signature found");
+
+                    int[] byteRange = sig.getByteRange();
+                    if (byteRange.length != 4)
                     {
-                        fis.close();
+                        System.err.println("Signature byteRange must have 4 items");
+                    }
+                    else
+                    {
+                        long fileLen = infile.length();
+                        long rangeMax = byteRange[2] + byteRange[3];
+                        // multiply content length with 2 (because it is in hex in the PDF) and add 2 for < and >
+                        long contentLen = sigDict.getString(COSName.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
+                            System.out.println("Signature does not cover whole document");
+                        }
+                        else
+                        {
+                            System.out.println("Signature covers whole document");
+                        }    
                     }
 
-                    System.out.println("Signature found");
                     System.out.println("Name:     " + sig.getName());
                     System.out.println("Modified: " + sdf.format(sig.getSignDate().getTime()));
                     String subFilter = sig.getSubFilter();
@@ -186,7 +205,8 @@ public final class ShowSignature
      * @throws OperatorCreationException
      */
     private void verifyPKCS7(byte[] byteArray, COSString contents, PDSignature sig)
-            throws CMSException, CertificateException, StoreException, OperatorCreationException
+            throws CMSException, CertificateException, StoreException, OperatorCreationException,
+                   NoSuchAlgorithmException, NoSuchProviderException
     {
         // inspiration:
         // http://stackoverflow.com/a/26702631/535646
@@ -202,6 +222,16 @@ public final class ShowSignature
         System.out.println("certFromSignedData: " + certFromSignedData);
         certFromSignedData.checkValidity(sig.getSignDate().getTime());
         
+        if (isSelfSigned(certFromSignedData))
+        {
+            System.err.println("Certificate is self-signed, LOL!");
+        }
+        else
+        {
+            System.out.println("Certificate is not self-signed");
+            // todo rest of chain
+        }
+
         if (signerInformation.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certFromSignedData)))
         {
             System.out.println("Signature verified");
@@ -212,6 +242,27 @@ public final class ShowSignature
         }
     }
 
+    // https://svn.apache.org/repos/asf/cxf/tags/cxf-2.4.1/distribution/src/main/release/samples/sts_issue_operation/src/main/java/demo/sts/provider/cert/CertificateVerifier.java
+
+    /**
+     * Checks whether given X.509 certificate is self-signed.
+     */
+    private boolean isSelfSigned(X509Certificate cert)
+            throws CertificateException, NoSuchAlgorithmException, NoSuchProviderException
+    {
+        try
+        {
+            // Try to verify certificate signature with its own public key
+            PublicKey key = cert.getPublicKey();
+            cert.verify(key);
+            return true;
+        }
+        catch (SignatureException | InvalidKeyException sigEx)
+        {
+            return false;
+        }
+    }
+
     /**
      * This will print a usage message.
      */