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:36 UTC

svn commit: r1797951 - /pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java

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

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

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

Modified: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java?rev=1797951&r1=1797950&r2=1797951&view=diff
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java (original)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/ShowSignature.java Wed Jun  7 15:40:36 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,11 +94,11 @@ public final class ShowSignature
         else
         {
             String password = args[0];
-            String infile = args[1];
+            File infile = new File(args[1]);
             PDDocument document = null;
             try
             {
-                document = PDDocument.load(new File(infile), password);
+                document = PDDocument.load(infile, password);
                 for (PDSignature sig : document.getSignatureDictionaries())
                 {
                     COSDictionary sigDict = sig.getCOSObject();
@@ -116,6 +117,29 @@ public final class ShowSignature
                     }
 
                     System.out.println("Signature found");
+
+                    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] + 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("Name:     " + sig.getName());
                     System.out.println("Modified: " + sdf.format(sig.getSignDate().getTime()));
                     String subFilter = sig.getSubFilter();
@@ -197,7 +221,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
@@ -212,7 +237,17 @@ public final class ShowSignature
         X509Certificate certFromSignedData = new JcaX509CertificateConverter().getCertificate(certificateHolder);
         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");
@@ -223,6 +258,31 @@ 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 sigEx)
+        {
+            return false;
+        }
+        catch (InvalidKeyException keyEx)
+        {
+            return false;
+        }
+    }
+    
     /**
      * This will print a usage message.
      */