签名与密钥库的Java
我创建了一个证书使用keytool:签名与密钥库的Java
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是无效的:“有包含在此签名的格式或信息错误”
有什么问题,证书或签名? 感谢您的帮助 萨拉
的事业“有包含在该签名的格式或信息错误,”验证失败消息是你的代码放在一个裸体PKCS1签名值,其中一个成熟的CMS签名容器预计:
你,一方面利用SELF_SIGNED
在sap.setCrypto
这表明你想创建一个adbe.x509.rsa_sha1辅助过滤签名,而在另一方面,子过滤设置为adbe.pkcs7.detached在您的PdfSignature
构造函数中。
这不符合所有,adbe.x509.rsa_sha1使用裸PKCS1签名值,而adbe.pkcs7.detached使用CMS签名的容器。
这应该回答你的问题“有什么问题,certificare或签名?” ......
根据你同时发现在行动一iText的副本,第2版解决方案的注释。
请注意,虽然iText签名API已经大幅扩展。如果您正在使用iText 5.5.x,则应该下载并阅读由Bruno Lowagie(iText Software)撰写的白皮书Digital Signatures for PDF Documents。2008年(SOTA在其发布而不是的时间了),数字签名的PDF文档重点:
虽然从的iText在行动代码,第二版,根据ISO 32000-1仍集中在签名根据PAdES签名,同时也包含在ISO 32000-2:2017中。
为什么直接构建哈希以签名和嵌入数字签名而不是使用itext支持?有很多可能的失败点。例如,你不包括认证链到pdf – pedrofb
如果我打电话给一个外部服务器(例如阿鲁巴CA),我只发送散列,签署pdf的代码工作正常。但是,如果我使用keytool生成证书,pdf是不正确的。我还添加了证书链: sap.setCrypto((PrivateKey)keyStore.getKey(“sara”,“password”.toCharArray()),keyStore.getCertificate(“sara”)。getCertificateChain(),null,PdfSignatureAppearance.SELF_SIGNED ); 但存在同样的问题。 – Sara
不要在评论中包含代码,它很难阅读。只需编辑你自己的问题。你应该包括所有相关的代码,包括你如何计算'hashToSign'。但是,如果您的代码与外部CA一起使用,而不是使用自签名证书,那么问题可能就在那里。检查您的证书是否正确生成 – pedrofb