title: iText7 References old BouncyCastle Library
body: <p>Ok, I'm trying to execute a test Java program compiled against iText (7) and BouncyCastle (154) jar files. Everything works swimmingly until I try to add an OCSP response when calling the signDetached function.</p>
  
  <p>My code is basically this piece of code from the iText website: </p>
  
  <p><a href="http://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-3#855-c3_07_signwithocsp.java" rel="nofollow noreferrer">http://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-3#855-c3_07_signwithocsp.java</a></p>
  
  <p>With my certificate and password details replaced where necessary. It all compiles ok but when I run it, the Java code falls over with the following error:</p>
  
  <blockquote>
    <p>Exception in thread "main" java.lang.NoClassDefFoundError:
    org.bouncycastle.ocsp.RevokedStatus at
    com.itextpdf.signatures.OcspClientBouncyCastle.getEncoded(OcspClientBouncyCastle.java:148)
    at com.itextpdf.signatures.PdfSigner.signDetached(PdfSigner.java:510)
    at DECSignHello.DoSign(DECSignHello.java:314) at
    DECSignHello.main(DECSignHello.java:125) Caused by:
    java.lang.ClassNotFoundException: org.bouncycastle.ocsp.RevokedStatus
    at java.net.URLClassLoader.findClass(URLClassLoader.java:600) at
    java.lang.ClassLoader.loadClassHelper(ClassLoader.java:777) at
    java.lang.ClassLoader.loadClass(ClassLoader.java:750) at
    sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:326) at
    java.lang.ClassLoader.loadClass(ClassLoader.java:731) ... 4 more</p>
  </blockquote>
  
  <p>When I dig a little deeper I see that iText7 is using a java class called <code>OcspClientBouncyCastle</code> that references a class file from a much older BouncyCastle implementation (something prior to 151 - haven't identified exactly which version it is yet that contains this class). The class it's referencing is <code>org.bouncycastle.ocsp.RevokedStatus</code>. The code that's causing the problem is this:</p>
  
  <p><code>status instanceof org.bouncycastle.ocsp.RevokedStatus</code></p>
  
  <p>On line 148 of <code>OcspClientBouncyCastle.java</code>. It doesn't exist in any BouncyCastle jar file from 151 and above...</p>
  
  <p>The same iText class <code>OcspClientBouncyCastle.java</code> file seems to also use the newer BouncyCastle classes found in the path <code>org.bouncycastle.cert.ocsp.*</code> for everything else BouncyCastle related so it appears as if it's using two different BouncyCastle implementations. At least that's what it looks like to me.</p>
  
  <p>It's causing my OCSP testing to fall over because when I get an invalid OCSP response from my service provider (which expected because I'm using a revoked certificate to test with) the class referenced by the <code>OcspClientBouncyCastle.java</code> source code is not found in the classpath - so it all falls over with an untrappable error.</p>
  
  <p>Now, I can get around this in a manner of speaking by doing manual OCSP verification using a valid class from the 154 BouncyCastle implementation as follows:</p>
  
  <pre>
  BasicOCSPResp l_resp = l_ocsp_client.getBasicOCSPResp(l_other_cert, l_root_cert, l_ocsp_url);
  SingleResp[] l_response = l_resp.getResponses();
  </pre>
  
  <p>and so on...</p>
  
  <p>However, as soon as I use the iText7 <code>PdfSigner.signDetached</code> function (passing and instance of <code>OcspClientBouncyCastle</code> for the OCSP client parameter) then the <code>OcspClientBouncyCastle.java</code> code is invoked and the 'old' class is used.</p>
  
  <p>I suppose I could get around that error by including the older (yet to be identified) BouncyCastle jar files in my classpath but that seems like such a cluttered solution.</p>
  
  <p>I could also edit the <code>OcspClientBouncyCastle.java</code> file and correct the errant function to use a newer implementation of the BouncyCastle functions but that seems like overkill too.</p>
  
  <p>I should mention that I'm working in an AIX environment on the command line. So no Java development tools/environment - just <code>vi</code> and I'm building my classpath (at compile and run time) manually and executing my code using ksh shell scripts.</p>
  
  <p>So, after all of that, I guess my question is this: Can anyone think of a reasonable reason why iText would implement the class <code>OcspClientBouncyCastle</code> this way?</p>
  
  <p>I'm a long-time follower/user of this forum but this is my first time posting anything. I realise my 'question' is rather broad in scope so apologies upfront for that.</p>
  
  <p>Herewith the sample code:</p>
  
  <pre><code>/*
   * This class is part of the white paper entitled
   * "Digital Signatures for PDF documents"
   * written by Bruno Lowagie
   * 
   * For more info, go to: http://itextpdf.com/learn
   */
  package signatures.chapter3;
  
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.security.GeneralSecurityException;
  import java.security.KeyStore;
  import java.security.PrivateKey;
  import java.security.Security;
  import java.security.cert.Certificate;
  import java.util.Properties;
  
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  import com.itextpdf.text.DocumentException;
  import com.itextpdf.text.pdf.security.DigestAlgorithms;
  import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
  import com.itextpdf.text.pdf.security.OcspClient;
  import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
  
  public class C3_07_SignWithOCSP extends C3_01_SignWithCAcert {
      public static final String SRC = "src/main/resources/hello.pdf";
      public static final String DEST = "results/chapter3/hello_cacert_ocsp.pdf";
  
      public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
          Properties properties = new Properties();
          properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
          String path = properties.getProperty("PRIVATE");
          char[] pass = properties.getProperty("PASSWORD").toCharArray();
  
          BouncyCastleProvider provider = new BouncyCastleProvider();
          Security.addProvider(provider);
          KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
          ks.load(new FileInputStream(path), pass);
          String alias = (String)ks.aliases().nextElement();
          PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
          Certificate[] chain = ks.getCertificateChain(alias);
          OcspClient ocspClient = new OcspClientBouncyCastle();
          C3_07_SignWithOCSP app = new C3_07_SignWithOCSP();
          app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test", "Ghent", 
                  null, ocspClient, null, 0);
      }
  
  } 
  C3_08_GetTsaUrl.java 
  /*
   * This class is part of the white paper entitled
   * "Digital Signatures for PDF documents"
   * written by Bruno Lowagie
   * 
   * For more info, go to: http://itextpdf.com/learn
   */
  package signatures.chapter3;
  
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.security.GeneralSecurityException;
  import java.security.KeyStore;
  import java.security.Security;
  import java.security.cert.Certificate;
  import java.security.cert.X509Certificate;
  import java.util.Properties;
  
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  import com.itextpdf.text.pdf.security.CertificateUtil;
  
  public class C3_08_GetTsaUrl {
      public static void main(String[] args) throws IOException, GeneralSecurityException {
          Properties properties = new Properties();
          properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
          String path = properties.getProperty("PRIVATE");
          char[] pass = properties.getProperty("PASSWORD").toCharArray();
  
          BouncyCastleProvider provider = new BouncyCastleProvider();
          Security.addProvider(provider);
          KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
          ks.load(new FileInputStream(path), pass);
          String alias = (String)ks.aliases().nextElement();
          Certificate[] chain = ks.getCertificateChain(alias);        
          for (int i = 0; i &lt; chain.length; i++) {
              X509Certificate cert = (X509Certificate)chain[i];
              System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
              System.out.println(CertificateUtil.getTSAURL(cert));
          }
      }
  }
  </code></pre>