3

I am getting the following error on trying to sign a pdf using code sample 2.2 in Bruno Lowagie's white paper: Digital Signatures for PDF Documents

Exception in thread "main" java.lang.NoClassDefFoundError: org/bouncycastle/cert/X509CertificateHolder
at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:143)
at com.howtodoinjava.demo.poi.PDFSign.sign(PDFSign.java:77)
at com.howtodoinjava.demo.poi.PDFSign.main(PDFSign.java:51)

Caused by: java.lang.ClassNotFoundException: org.bouncycastle.cert.X509CertificateHolder......

line 77 contains this line of code:MakeSignature.signDetached(appearance, digest, signature, chain,null, null, null, 0, subfilter);

line 51 contains this line:

app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256,
provider.getName(), CryptoStandard.CMS, "Test 1", "Harare");

code

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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 org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;


/**
 *
 * @author hdear
 */
public class PDFSign {
public static final String KEYSTORE = "C:\\Program Files\\Java\\jdk1.8.0_05\\bin\\ks";
public static final char[] PASSWORD = "hubert".toCharArray();
public static final String SRC = "Hello World.pdf";
public static final String DEST = "Hello World_signed%s.pdf";
public static void main(String[] args)
throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
PDFSign app = new PDFSign();
app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256,
provider.getName(), CryptoStandard.CMS, "Test 1", "Harare");
app.sign(SRC, String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA512,
provider.getName(), CryptoStandard.CMS, "Test 2", "Harare");
app.sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256,
provider.getName(), CryptoStandard.CADES, "Test 3", "Harare");
app.sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160,
provider.getName(), CryptoStandard.CADES, "Test 4", "Harare");
}
public void sign(String src, String dest,
Certificate[] chain, PrivateKey pk, String digestAlgorithm, String provider,
CryptoStandard subfilter, String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature =
new PrivateKeySignature(pk, digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain,null, null, null, 0, subfilter);
}
}

Anyone to help?

Mandar Pandit
  • 2,171
  • 5
  • 36
  • 58
Hubert Dear
  • 41
  • 1
  • 3
  • Duplicate of http://stackoverflow.com/questions/17973970/how-to-solve-java-lang-noclassdeffounderror – Dinal Jun 11 '14 at 11:10

2 Answers2

8

I had same exception. I had only one bouncycastle dependency: bcprov-jdk15on and when I looked inside the jar there was no X509CertificateHolder. I've added another dependency: bcpkix-jdk15on (according to solution found here) and it works :)

My working maven dependencies:

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.49</version>
        <type>jar</type>
        <scope>compile</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.49</version>
        <type>jar</type>
        <scope>compile</scope>
        <optional>true</optional>
    </dependency>
shebik
  • 653
  • 9
  • 10
0

When you get a NoClassDefFoundError, there is a problem with your CLASSPATH.

  • Either you didn't include the necessary BouncyCastle jars into your CLASSPATH. In that case, it's normal that your application can't find the org/bouncycastle/cert/X509CertificateHolder class: it's not there. Remedy: add the appropriate BouncyCastle jars to your CLASSPATH.
  • Or you have more than one version of BouncyCastle in your CLASSPATH. In this case, you have an ambiguity: your application doesn't know which of the multiple X509CertificateHolder classes it should pick. Remedy: remove all versions of BouncyCastle from your CLASSPATH, except the one you need.
  • Or you have the wrong version of BouncyCastle in your CLASSPATH. Maybe a version where X509CertificateHolder is absent or where it exists in another package. Remedy: replace that jar with the version of BouncyCastle you need.

How do you know which version of BouncyCastle is needed? When you downloaded iText, you downloaded a specific version of iText. This version comes with a POM file. In this POM file, you can find the iText version number and all the dependencies. You'll find the BouncyCastle version number you need in that file.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • Hie Bruno, thanks for the insights. I have the Bounty Castle in my classpath, all other calls to the library are perfectly working which means maybe the problem here is that I am using versions of itext and Bouncy Castle which are not compatible with each other as you hinted in your third suggestion above. I'm still getting the same error after i have removed the Bounty Castle I had and replaced it with the one I downloaded from the path you gave me above. I'm using itext 5.5.0. Any idea which Bounty Castle version is compatible with the version of itext I am using? – Hubert Dear Jun 11 '14 at 12:18
  • Which iText version do you use? Which BC version do you use? BC has a history of having major changes between one minor version and the next one... – mkl Jun 11 '14 at 13:42
  • iText version 5.5.0. I have tried the example with Bounty Castle 1.3-1.5 and I have been getting the same error.Do you know of any versions of Bounty Castle and iText perfectly compatible with each other? I could try using those. – Hubert Dear Jun 11 '14 at 14:30
  • iText 5.5.0 has a dependency on BouncyCastle 1.49. Have you tried that one? – Michaël Demey Jun 12 '14 at 08:02
  • @MichaëlDemey, yes I have tried on itext 5.5.0 with BC 1.49 provider. Do you have any BC itext version pair which you have used before signing and worked well? Maybe if i try a par that has already worked well on someone I may be able to narrow down the root cause of the bug. – Hubert Dear Jun 13 '14 at 09:11
  • You have a `NoClassDefFoundError`. This is not an error caused by a programming error, but a configuration problem. Configuration problems are hard to solve remotely. Try this: take a completely different computer. Start from scratch with a new installation of Java. Try the example from my book with the appropriate iText and BC jars. Does the problem persist? – Bruno Lowagie Jun 13 '14 at 11:27
  • Yes I have tried with a fresh installation itext 5.5.0 and BC 1.49 provider. Still no joy the challenge persists. I tried unpacking the BC provider packages, surely the class X509CertificateHolder is not available in that path. – Hubert Dear Jun 16 '14 at 15:02
  • Having the exact same issue here. –  Oct 20 '15 at 17:25