我使用keytool创建证书:
keytool -genkeypair -alias sara -keyalg RSA -keysize 2048 -keypass
password -keystore "\Sviluppo\JavaKeyStore\keystore.jks" -storepass
12345678 -validity 360 -dname "cn=Sara, ou=***, o=***, l=Padova,
s=Italia, c=IT"
然后我想用这个证书签署一个pdf,我使用Itextpdf来签署一个pdf。 首先,我从密钥库加载私钥和证书:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
File fileKeyStore = new File(pathKeyStore);
FileInputStream fis = new FileInputStream(fileKeyStore);
keyStore.load(fis, "12345678".toCharArray());
final PrivateKey privateKey = (PrivateKey) keyStore.getKey("sara", "password".toCharArray());
final Certificate certificate = keyStore.getCertificate(certID);
然后我打开文件计算哈希签名:
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(pdfInputPath), null);
OutputStream pdfOutputStream = new FileOutputStream(pdfOutputPath);
PdfStamper stp = PdfStamper.createSignature(reader, pdfOutputStream, '\0', tempPathFile, true)
PdfSignatureAppearance sap = stp.getSignatureAppearance();
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setDate(dateNow);
sap.setCryptoDictionary(dic);
sap.setCrypto(privateKey, keyStore.getCertificateChain("sara"), null, PdfSignatureAppearance.SELF_SIGNED);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, (int) (6144 * 2 + 2));
sap.preClose(exc);
然后计算sap.getRangeStream()的哈希值,从密钥库加载证书:
BufferedInputStream bis = new BufferedInputStream(sap.getRangeStream());
MessageDigest digest = MessageDigest.getInstance("SHA-256");
DigestInputStream dis = new DigestInputStream(bis, digest);
byte[] buff = new byte[512];
while (dis.read(buff) != -1) {
;
}
dis.close();
dis = null;
byte[] hashToSign= digest.digest();
bis.close();
我使用密钥库的证书签名:
java.security.Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(hashToSign);
byte[] hashSigned = signature.sign();
结束时关闭pdf:
byte[] paddedSig = new byte[6144];
System.arraycopy(hashSigned, 0, paddedSig, 0, hashSigned.length);
PdfDictionary pdfDictionary = new PdfDictionary();
pdfDictionary.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
sap.close(pdfDictionary);
但签署的pdf无效:“此签名中包含的格式或信息存在错误”
问题是什么,证书或签名? 感谢帮助 萨拉
答案 0 :(得分:0)
&#34;原因是此签名中包含的格式或信息有错误&#34;验证失败消息是您的代码将裸露的PKCS1签名值放在需要完整成熟的CMS签名容器的位置:
您一方面在SELF_SIGNED
中使用sap.setCrypto
,表示您要创建 adbe.x509.rsa_sha1 SubFilter 签名,另一方面,在您的PdfSignature
构造函数中将 SubFilter 设置为 adbe.pkcs7.detached 。
根本不匹配, adbe.x509.rsa_sha1 使用裸露的PKCS1签名值,而 adbe.pkcs7.detached 使用CMS签名容器。
这应该回答您的问题&#34;问题,证书或签名是什么?&#34; ...
根据评论,您同时在行动第2版的iText副本中找到了解决方案。
请注意,iText签名API同时已经大幅扩展。如果您使用的是iText 5.5.x,则应下载并阅读Bruno Lowagie(iText Software)的白皮书Digital Signatures for PDF Documents。
虽然来自 iText in Action,2nd Edition 的代码仍然专注于根据ISO 32000-1:2008签署的签名(SOTA在发布时但不再是), Digital PDF文档的签名侧重于根据PAdES签名,同时已包含在ISO 32000-2:2017中。