Hello Guys,

I've reviewed the whole mailing list but couldn't locate any thread where
people could sign a PDF properly 
working with Java and using a smart card without direct access to the both:
private key and middleware. All
 threads I've found have the final message like "Please, help!". 

Of course, I've read and used all ideas proposed at
http://itextpdf.sourceforge.net/howtosign.html.
I've bought the book iText in Action, Second Edition - there is no real
explanation how to sign without private key.

"Page 404 Listing 12.19
Let’s pretend you don’t have access to the private key, so you pass null to
the set-
Crypto() method . You use the setExternalDigest() method to reserve space in
the
signature dictionary for keys whose content isn’t known yet. You don’t close
the Pdf-
Stamper, but you preClose() the signature appearance. Then you create a
Signature
object using the private key;"

How can we operate with private key if we assumed "Let’s pretend you don’t
have access to the private key"? Or did I miss something?

Please notice I do not claim. The book is really good and I am happy that
I've bought this one.
I just want to understand can I really use iText for working with smart
card?

I have an OMNI smart card which doesn't have any middleware for Java except
.so module. 
So, I've written a PERL script which actually gets the hash, copies it to
the smart card, 
signes it with private key (RSA2048), outputs the result - just a signed
digest which is not in PKCS#7 format.

My Java application does following:

1. Load certificates SHA256withRSA

CertificateFactory factory = CertificateFactory.getInstance("X509");
X509Certificate certificate1
=(X509Certificate)factory.generateCertificate(new
FileInputStream(certPath1));
Certificate[] certs = new Certificate[2];
certs[0] = certificate1;
X509Certificate certificate2
=(X509Certificate)factory.generateCertificate(new
FileInputStream(certPath2));
certs[1] = certificate2;

2.Initialize reader, stamper.

PdfReader reader = new PdfReader(fileIn);
PdfStamper stamper = PdfStamper.createSignature(reader, fout, '\0',  null,
true);
PdfSignatureAppearance sap = stamper.getSignatureAppearance();

3.Configure SignatureAppearance

sap.setSignDate(new GregorianCalendar());
sap.setCrypto(null, certs, null,
PdfSignatureAppearance.SELF_SIGNED/*WINCER_SIGNED*/);
sap.setReason("Debugging the signing process");
sap.setLocation("Location");
sap.setContact("Contact address");
sap.setExternalDigest(new byte[513], new byte[20], "RSA");
sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);

4. Create signature dictionary

PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE,
PdfName.ADBE_PKCS7_DETACHED);
dic.setName(PdfPKCS7.getSubjectFields((X509Certificate)certs[0]).getField("CN"));
if (sap.getSignDate()!= null) dic.setDate(new PdfDate(sap.getSignDate()));
if (sap.getReason()!= null) dic.setReason(sap.getReason());
if (sap.getLocation() != null) dic.setLocation(sap.getLocation());
if (sap.getContact() != null) dic.setContact(sap.getContact());
sap.setCryptoDictionary(dic);

5. Reserve space for CONTENTS

int csize = 15000;
HashMap<PdfName, Integer> exc = new HashMap();
exc.put(PdfName.CONTENTS, csize * 2 + 2);
sap.preClose(exc);

6. Calculate content stream digest

MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte buf[] = new byte[8192];
int n;
InputStream inp = sap.getRangeStream();
while ((n = inp.read(buf)) > 0) {
 messageDigest.update(buf, 0, n);
 fTmp1.write(buf, 0, n);//tmp - data for digest
}

byte hash[] = messageDigest.digest();

7.  Running PERL script and get the value of signed hash as is (not in
PKCS#7 format)
byte[] signedHashBytes = Base64.decodeBase64(signedHash);

8. And the most interesting part - create PKCS#7 object

Calendar cal = sap.getSignDate();
byte[] ocsp = null;
String url = PdfPKCS7.getOCSPURL((X509Certificate) certs[0]);
if (url != null && url.length() > 0) {
     final OcspClientBouncyCastle ocspClient = new
OcspClientBouncyCastle((X509Certificate) certs[0],
     (X509Certificate) certs[1], url);
     ocsp = ocspClient.getEncoded();
}


PdfPKCS7 sig = new PdfPKCS7(null, certs, null, "SHA256", null, false);
sig.setExternalDigest(hash, signedHashBytes, "RSA");

PdfLiteral pdfLiteral = (PdfLiteral) dic.get(PdfName.CONTENTS);
byte[] outc = new byte[(pdfLiteral.getPosLength() - 2) / 2];

byte[] ssig = sig.getEncodedPKCS7(null, cal, null, ocsp);

Arrays.fill(outc,(byte)0);

System.arraycopy(ssig, 0, outc, 0, ssig.length);
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
sap.close(dic2);

9.Result

And as the result this code output PDF which Adobe believes was modified and
hence signature is not valid:
"The document has been altered or corrupted since it was signed"

Can you advice what's wrong with code?

Any help would be appreciated! 

Kind regards,
Andriy.




-- 
View this message in context: 
http://itext-general.2136553.n4.nabble.com/HASH-SMARTCARD-and-PKCS-7-detached-tp3047252p3047252.html
Sent from the iText - General mailing list archive at Nabble.com.

------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Many questions posted to this list can (and will) be answered with a reference 
to the iText book: http://www.itextpdf.com/book/
Please check the keywords list before you ask for examples: 
http://itextpdf.com/themes/keywords.php

Reply via email to