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
