I am trying through HWCryto - https://github.com/open-eid/hwcrypto.js/wiki/ModernAPI - to add support in a Struts2 application to digital signing. Trying to follow Bruno Lowagie's book first i create an empty signature
CertificateFactory certFactory;
try {
certFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream in = new ByteArrayInputStream(certDecoded);
cert = (X509Certificate) certFactory.generateCertificate(in);
} catch (CertificateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Calendar cal = Calendar.getInstance();
int estimatedSize = 8192;
PdfSignatureAppearance sap = pdfStamper.getSignatureAppearance();
sap.setVisibleSignature("sig");
sap.setCertificate(cert);
sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
sap.setSignDate(cal);
ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE,
PdfName.ADBE_PKCS7_DETACHED);
try {
MakeSignature.signExternalContainer(sap, external, 8192);
pdfStamper.close();
pdfReader.close();
} catch (GeneralSecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (DocumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
After that i get the pdf output and create a new hash that i will send to smartcard
byte [] alteredPDF=output.toByteArray();
ExternalDigest externalDigest = new ExternalDigest() {
@Override
public MessageDigest getMessageDigest(String hashAlgorithm) throws GeneralSecurityException {
return DigestAlgorithms.getMessageDigest(hashAlgorithm, "BC");
}
};
PdfSignatureAppearance sapFinal = null;
try {
ByteArrayOutputStream outputFinal = new ByteArrayOutputStream();
pdfReader = new PdfReader(new ByteArrayInputStream(alteredPDF));
pdfStamper = PdfStamper.createSignature(pdfReader, outputFinal, '\0');
sapFinal = pdfStamper.getSignatureAppearance();
sapFinal.setVisibleSignature("sig");
sapFinal.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
sapFinal.setCertificate(cert);
sapFinal.setSignDate(cal);
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setReason(sap.getReason());
dic.setLocation(sap.getLocation());
String certInfo = cert.getSubjectX500Principal().getName();
dic.setName(certInfo.substring(certInfo.indexOf("CN=") + 3,
certInfo.indexOf(",OU", certInfo.indexOf("CN=") + 3)));
dic.setSignatureCreator(sap.getSignatureCreator());
dic.setContact(sap.getContact());
dic.setCert(certDecoded);
dic.setDate(new PdfDate(sap.getSignDate()));
sapFinal.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(estimatedSize * 2 + 2));
sapFinal.preClose(exc);
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
byte[] sh = null;
byte[] hashVal = null;
PdfPKCS7 sgn = null;
try {
sgn = new PdfPKCS7(null, new Certificate[] { cert }, "SHA256", null, externalDigest, false);
InputStream data = sapFinal.getRangeStream();
hashVal = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
sh = sgn.getAuthenticatedAttributeBytes(hashVal, cal, null, null, CryptoStandard.CMS);
sh = MessageDigest.getInstance("SHA256", "BC").digest(sh);
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And finally having the generated sig
sgn.setExternalDigest(sig, null, "RSA");
byte[] encodedSign = null;
try {
System.out.println(Arrays.toString(Hex.decodeHex(hash.toCharArray())));
encodedSign = sgn.getEncodedPKCS7(Hex.decodeHex(hash.toCharArray()), cal, null, null, null,
CryptoStandard.CMS);
} catch (DecoderException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
MakeSignature.signDeferred(pdfReader, "sig", output,
new MyExternalSignatureContainer(encodedSign));
} catch (DocumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (GeneralSecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("called sign pdf");
try {
FileOutputStream outputStream = new FileOutputStream("d:\\debug.pdf");
output.writeTo(outputStream);
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Can anyone please point me to what i am doing wrong?
PdfStamper
outputs serve as inputs to whichPdfReaders
? The flow is not clear. – mkl