Solved

Try to sign a document in Java with failure in code.

Posted on 2012-12-21
17
2,898 Views
Last Modified: 2013-01-10
Hi there;

In Java, I am trying to sign a document and fail to do so. I am using:
itextpdf-5.3.3.jar

My code is as follows:

public void sign()
	{
		KeyStore ks = KeyStore.getInstance("pkcs12");
		ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
		String alias = (String)ks.aliases().nextElement();
		PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
		Certificate[] chain = ks.getCertificateChain(alias);
		PdfReader reader = new PdfReader("original.pdf");
		FileOutputStream fout = new FileOutputStream("signed.pdf");
		PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
		PdfSignatureAppearance sap = stp.getSignatureAppearance();
		sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
		sap.setReason("I'm jazz");
		sap.setLocation("Stockholm");
		// comment next line to have an invisible signature
		sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
		stp.close();
	}

Open in new window


my code gives error in the following lines:
sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
	sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);

Open in new window


What to do?

Regards.
0
Comment
Question by:jazzIIIlove
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 3
  • 3
  • +1
17 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 38715416
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38718199
Hi;

The errors are compile time error, not runtime errors.

WINCER_SIGNED cannot be resolved or is not a field.
and the other error is as follows:

setVisibleSignature
The method setVisibleSignature(Rectangle, int, String) in the type PdfSignatureAppearance is not applicable for the arguments (Rectangle, int, null)

Regards.

P.S.
I am just trying to sign the pdf, nothing complicated actually. Just for learning purposes.
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38718288
Hi;

An update: I also tried for the example source code in stackoverflow but the problem is that it uses the old version and when I go for itextpdf package, the above problems emerge again. So, there is no backward compatibility in this.

How can i do this in itextpdf but not in lowagie?

/*
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;
*/

import com.itextpdf.text.pdf.*;


regards.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38718574
You need to find an example for the api you've got. Either that or get the version of the api for which you have the example
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38719077
Hi;

I couldn't find the related example for itextpdf for Java (I found C#.NET version). Can you help me on this?

I also tried to find the jdk of the old version but couldn't find its jar.

Regards.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38719101
Sorry - i have no special knowledge on this. You need to speak to someone who knows about the versions
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38720870
Hi CEHJ;

Thanks for the information.

@TomasHelgi:
Can you help me regarding the class PdfSignatureAppearance as it fails for the crypto settings?

Regards.
0
 
LVL 25

Expert Comment

by:Tomas Helgi Johannsson
ID: 38729143
Hi!

Try to change the line
sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
to
sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, "Some string");

Depending on what kind of certificate you have then also try to change the WINCER_SIGNED to SELF_SIGNED.

And here is an example you could look at and try out.
https://geekcredential.wordpress.com/2010/04/23/how-to-sign-a-pdf-using-itext-and-groovy/comment-page-1/

Regards,
     Tomas Helgi
0
 
LVL 64

Assisted Solution

by:btan
btan earned 500 total points
ID: 38730415
you may want to check out itextpdf latest version
http://itextpdf.com/examples/iia.php?id=222

They have a pdf ebook on digital signature which is a good lead into the topic, the lowagie package is already a past and they leveraging bouncycastle..

Can check out section "2.2 The “Hello World” of digital signing using iText"
http://itextpdf.com/book/digitalsignatures20121017.pdf

But do also note extract for the ebook below:

Pg24

Part 5—PAdES for XML content describes profiles for XAdES signatures. For instance, after
filling an XFA form, which is XML content embedded in a PDF file, a user may sign selected
parts of the form. This isn’t supported in iText yet.

Pg25

In  versions predating iText 5.3.0,  you’d sign a PDF document choosing one of the following parameters for the setCrypto() method:

¿ PdfSignatureAppearance.WINCER_SIGNED— this created a signature with the sub
filter /adbe.pkcs7.sha1.
¿ PdfSignatureAppearance.SELF_SIGNED— this created a signature with the sub
filter /adbe.x509.rsa_sha1.

These options have been removed in 5.3.0 for very specific reasons. The /adbe.pkcs7.sha1 sub filter will be deprecated in PDF 2.0. ISO-32000-2 recommends: “To support backward compatibility, PDF readers should process this value for the /SubFilter key but PDF writers shall not use this value for that key.” iText is a PDF writer, and since iText 5.3.0, we no longer allow the creation of this type of signatures. Please don’t sign any documents using this sub filter anymore.
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38745623
Hi;

Thanks for the help!

I created another jks by issuing:
c:\>keytool -genkey -keyalg RSA -alias "selfsigned" -keystore keystore2.jks -storepass "dummy" -validity 360

my code is as follows:
public void sign()
	{
		try{			
			// String path = properties.getProperty("PRIVATE");
			String keystore_password = "dummy";
			String key_password = "dummy";
			KeyStore ks = KeyStore.getInstance("pkcs12");
			
			ks.load(new FileInputStream("keystore2.jks"), keystore_password.toCharArray());
			
			//ks.load(new FileInputStream("keystore.p12"), keystore_password.toCharArray());
			String alias = (String)ks.aliases().nextElement();
			PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
			Certificate[] chain = ks.getCertificateChain(alias);
			// reader and stamper
			PdfReader reader = new PdfReader("my.pdf");
			FileOutputStream os = new FileOutputStream("my_signed.pdf");
			PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
			// appearance
			PdfSignatureAppearance appearance = stamper .getSignatureAppearance();
			appearance.setImage(Image.getInstance("Image10.jpg"));
			appearance.setReason("I've written this.");
			appearance.setLocation("Foobar");
			appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1,    "first");
			// digital signature
			ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
			ExternalDigest digest = new BouncyCastleDigest();
			MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
		}catch(Exception ex){ex.printStackTrace();}

	}

Open in new window


Now, my error is no longer compile time but runtime as follows:
java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
      at sun.security.util.DerInputStream.getLength(Unknown Source)
      at sun.security.util.DerValue.init(Unknown Source)
      at sun.security.util.DerValue.<init>(Unknown Source)
      at sun.security.pkcs12.PKCS12KeyStore.engineLoad(Unknown Source)
      at java.security.KeyStore.load(Unknown Source)
and line 34 which is ks.load(...) line.

What to do? Any missing section? Should i do something extra?

Regards.
0
 
LVL 64

Accepted Solution

by:
btan earned 500 total points
ID: 38746333
I believe the jks is the culprit. For PKCS#12, they are looking at .p12 or .pfx extension file instead of jks.

We can run keytool -list -keystore <keystore_location> and if you see "Keystore type: JKS" then we are creating the wrong keystore instance type in your code.    

Can use -storetype pkcs12 in the keytool command and test again to see Keystore type. This time should show PKCS#12, then test your existing code again.

Otherwise, can also simply change existing code using either  
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
OR
KeyStore ks = KeyStore.getInstance("JKS");

Below is good post - see "How to generate the keys for the self signed mode").
The article also covers code using JKS or PKCS#12 file () which you may find it useful (if bug comes again).

http://itextpdf.sourceforge.net/howtosign.html
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38746551
Hi;

I think you are right. i changed the keystore instance to JKS and the exception changes as follows:
Exception in thread "main" java.lang.NoClassDefFoundError: org/bouncycastle/jcajce/provider/digest/MD2$Digest

ExternalDigest digest = new BouncyCastleDigest();

As referenced library, i have itext-5.3.3.jar

Now, what should I do to fix this classdeffounderror?

Regards.

P.S. I have as:
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
0
 
LVL 12

Assisted Solution

by:jazzIIIlove
jazzIIIlove earned 0 total points
ID: 38746612
Hi;

Finally, it worked. First I added the bcprov, bcmail, bpg, bcpkix, bctest and then add the following line:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

Thanks for the help.

I will do the verification but really disappointed for such settings and lack of full examples as most of examples don't have the imports or jar references.
0
 
LVL 64

Expert Comment

by:btan
ID: 38746634
Thanks for sharing. glad it helps
0
 
LVL 12

Author Closing Comment

by:jazzIIIlove
ID: 38762290
Bouncycastle references seems to be fundamental for signing the document..
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I was prompted to write this article after the recent World-Wide Ransomware outbreak. For years now, System Administrators around the world have used the excuse of "Waiting a Bit" before applying Security Patch Updates. This type of reasoning to me …
A 2007 NCSA Cyber Security survey revealed that a mere 4% of the population has a full understanding of firewalls. As business owner, you should be part of that 4% that has a full understanding.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
Starting up a Project

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question