About us | News | Contact
iText ® Licenses Support   
You are here: Home > Forums > iText in Action — Second Edition > Part 3: Essential iText skills > Chapter 12: Protect your PDF
User login
  • Request new password

Problem Using Self-Signed Certificates

Submitted by wu_ninja on Sun, 04/10/2011 - 23:19

Text: iText in Action, 2nd. ed.
Java: 1.6
OS: Windows 7, 64-bit SP 1
Listing: 12.11 pg. 391

Hello

I'm having problems reproducing the example in the 'Creating a Public-Key Encrypted PDF'. I created the self-signed certificate as explained in the text. However, I'm receiving the following runtime error when running the example:

Exception in thread "main" java.lang.NoSuchFieldError: data
at com.itextpdf.text.pdf.PdfPublicKeySecurityHandler.createDERForRecipient(PdfPublicKeySecurityHandler.java:245)
at com.itextpdf.text.pdf.PdfPublicKeySecurityHandler.getEncodedRecipient(PdfPublicKeySecurityHandler.java:191)
at com.itextpdf.text.pdf.PdfPublicKeySecurityHandler.getEncodedRecipients(PdfPublicKeySecurityHandler.java:212)
at com.itextpdf.text.pdf.PdfEncryption.getEncryptionDictionary(PdfEncryption.java:420)
at com.itextpdf.text.pdf.PdfWriter.setEncryption(PdfWriter.java:2008)
at itext.ch12.EncryptWithCertificate.createPdf(EncryptWithCertificate.java:80)
at itext.ch12.EncryptWithCertificate.main(EncryptWithCertificate.java:190)

I've never worked with encryption or certificates before so I have no idea what could be causing this error. Any suggestions?

Thank you.

‹ What permissions are available? Encrypting a Reader-enabled PDF ›
  • Login to post comments

Are you using the right BouncyCastle jars?

Submitted by Bruno Lowagie on Mon, 04/11/2011 - 08:25.

From your stacktrace, I can see that the problem is caused by PKCSObjectIdentifiers.data. The error message tells you that PKCSObjectIdentifiers doesn't have a field named data. However, when I look at my own BouncyCastle jar, I can find:

static final DERObjectIdentifier data = new DERObjectIdentifier(pkcs_7 + ".1");

The fact that your JVM can't find this field, means that you're either using the wrong BouncyCastle jars, or that you forgot to add them to the CLASSPATH. See the WARNING on page 387.

  • Login to post comments

I'm using BouncyCastle 146

Submitted by wu_ninja on Mon, 04/11/2011 - 17:41.

Hello

I observed the warning on pg. 387 and downloaded the latest BouncyCastle libs for my development environment. I'm using JDK 1.6 so I put the 'bcprov-jdk16-146.jar' in my classpath. (Note, this was before I posted to the forum.) Looking at the posted example for EncryptWithCertificate on your website, (http://itextpdf.com/examples/iia.php?id=220) I noticed that you are also using 'bcmail-jdk1.x-xxx' in your classpath so I put that in my classpath as well. I still get the same error. Could you tell me in what package the "static final DERObjectIdentifier data" statement is found so I could verify that it exists? For reference, I'm posting the source code that I'm using. Perhaps there is something else amiss.

package itext.ch12;

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 java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
/**
*
* iText In Action
* Ch. 12 - Protecting PDF
* pg. 391 - Encrypting with public-key
*
* $Date: 2011-04-10 20:06:22 -0400 (Sun, 10 Apr 2011) $
*/

public class EncryptWithCertificate {

/** The resulting PDF */
public static String RESULT1 = "certificate_encryption.pdf";

/** The resulting PDF */
public static String RESULT2 = "certificate_decrypted.pdf";

/** The resulting PDF */
public static String RESULT3 = "certificate_encrypted.pdf";

/**
* A properties file that is PRIVATE.
* You should make your own properties file and adapt this line.
*/
public static String PATH = "key.properties";

/** Some properties used when signing. */
public static Properties properties = new Properties();

/**
* Creates a PDF that is encrypted using two different public certificates.
* @param filename the path to the resulting PDF file
* @throws IOException
* @throws DocumentException
* @throws GeneralSecurityException
*/
public void createPdf(String filename)
throws IOException, DocumentException, GeneralSecurityException {

// step 1
Document document = new Document(PageSize.LETTER);

// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT1));

Certificate cert1 = getPublicCertificate("resources/encryption/farm.cer");
//Certificate cert2 = getPublicCertificate("resources/encryption/foobar.cer");
//Certificate cert2 = getPublicCertificate(properties.getProperty("PUBLIC"));

//writer.setEncryption(new Certificate[]{cert1, cert2},
// new int[]{PdfWriter.ALLOW_PRINTING, PdfWriter.ALLOW_COPY}, PdfWriter.ENCRYPTION_AES_128);

writer.setEncryption(new Certificate[]{ cert1 },
new int[]{ PdfWriter.ALLOW_PRINTING }, PdfWriter.ENCRYPTION_AES_128 );

// step 3
document.open();

// step 4
document.add(new Paragraph("Hello World!"));

// step 5
document.close();
}

/**
* Gets a public certificate from a certificate file.
* @param path the path to the certificate
* @return a Certificate object
* @throws IOException
* @throws CertificateException
*/
public Certificate getPublicCertificate(String path)
throws IOException, CertificateException {

FileInputStream is = new FileInputStream(path);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

X509Certificate cert = (X509Certificate) cf.generateCertificate(is);

return cert;
}

/**
* Gets a private key from a KeyStore.
* @return a PrivateKey object
* @throws GeneralSecurityException
* @throws IOException
*/
public PrivateKey getPrivateKey() throws GeneralSecurityException, IOException {

String path = "resources/encryption/foobar.keystore";

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

ks.load(new FileInputStream(path), "f00b4r".toCharArray());

PrivateKey pk = (PrivateKey)ks.getKey("foobar", "f1lmf3st".toCharArray());

return pk;
}

/**
* Decrypts a PDF that was encrypted using a certificate
* @param src The encrypted PDF
* @param dest The decrypted PDF
* @throws IOException
* @throws DocumentException
* @throws GeneralSecurityException
*/
public void decryptPdf(String src, String dest)
throws IOException, DocumentException, GeneralSecurityException {

PdfReader reader = new PdfReader(src,
getPublicCertificate("resources/encryption/foobar.cer"), getPrivateKey(), "BC");

PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));

stamper.close();
}

/**
* Encrypts a PDF using a public certificate.
* @param src The original PDF document
* @param dest The encrypted PDF document
* @throws IOException
* @throws DocumentException
* @throws CertificateException
*/
public void encryptPdf(String src, String dest)
throws IOException, DocumentException, CertificateException {

PdfReader reader = new PdfReader(src);

PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));

Certificate cert = getPublicCertificate("resources/encryption/foobar.cer");

stamper.setEncryption(new Certificate[]{cert},
new int[]{PdfWriter.ALLOW_PRINTING}, PdfWriter.ENCRYPTION_AES_128);

stamper.close();
}

/**
* Main method.
*
* @param args no arguments needed
* @throws DocumentException
* @throws IOException
* @throws GeneralSecurityException
*/
public static void main(String[] args)
throws IOException, DocumentException, GeneralSecurityException {

Security.addProvider(new BouncyCastleProvider());

properties.load(new FileInputStream(PATH));

EncryptWithCertificate hello = new EncryptWithCertificate();

hello.createPdf(RESULT1);

}

}

  • Login to post comments

BouncyCastle

Submitted by Bruno Lowagie on Tue, 04/12/2011 - 09:36.

The interface PKCSObjectIdentifiers can be found in org.bouncycastle.asn1.pkcs.

  • Login to post comments

BouncyCastle is in classpath

Submitted by wu_ninja on Wed, 04/13/2011 - 18:37.

Hello

I verified that PKCSObjectIdentifiers is indeed in my BouncyCastle jar and that there is a "data" member in that class. The jar is in my classpath and in fact, the example will not compile without it due to the import of "org.bouncycastle.jce.provider.BouncyCastleProvider". I don't think it's an issue with the versions because I tried it with the 1.4 and 1.5 versions and I still receive the error. One other thing to note is I installed the JCE jars as suggested in the FAQ on pg. 392 of the book. Other than that, I'm not sure what the problem could be.

  • Login to post comments

Configuration problem

Submitted by Bruno Lowagie on Thu, 04/14/2011 - 08:31.

It works for me, so you have a configuration problem.
Unless we can literally sit next to you, we can't help you with configuration problems.

Suppose you write some code that doesn't involve iText, can you access the data member? I guess you can't.

Possible reasons:
- the CLASSPATH you use to compile is not the same as the CLASSPATH you use to execute.
- you have more than one version of the BC jars (or the iText jar) in your CLASSPATH
- ...

Try running the example on another system. If it works there, check what's different.

  • Login to post comments

Thank you for your time

Submitted by wu_ninja on Mon, 04/18/2011 - 08:03.

Thank you for your assistance.

  • Login to post comments
Content © 2010 1T3XT BVBA