我正在尝试通过HWCryto - https://github.com/open-eid/hwcrypto.js/wiki/ModernAPI - 在Struts2应用程序中添加对数字签名的支持。 我首先尝试按照Bruno Lowagie的书创建一个空的签名
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();
}
之后我得到pdf输出并创建一个我将发送到智能卡的新哈希
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();
}
最后生成了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();
}
有谁能请我指出我做错了什么?
答案 0 :(得分:1)
终于设法解决了我的问题。将空签名存储到PDF中并重新创建输出流是罪魁祸首。管理从头到尾使用相同的输出流并且它起作用。 这个链接 - https://github.com/sueastside/BEIDSign/blob/master/beidsign-service/src/main/java/be/redtree/beid/services/SignatureServiceImpl.java - 确实对我有所帮助。 谢谢mkl你的时间。