按照上一个问题中给出的答案:在Itext 7中,如何让范围流对pdf进行签名?,我尝试重新实现在Itext 5中工作的两步签名方法,但在尝试重新打开第一步的文档结果时遇到问题(使用PdfReader或pdf阅读器)。(无效文档)
以下是已包含名为“认证”的空签名字段的文档的预签名部分...为什么此步骤的结果无效?
PdfReader reader = new PdfReader(fis);
Path signfile = Files.createTempFile("sign", ".pdf");
FileOutputStream os = new FileOutputStream(signfile.toFile());
PdfSigner signer = new PdfSigner(reader, os, false);
signer.setFieldName("certification"); // this field already exists
signer.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING);
PdfSignatureAppearance sap = signer.getSignatureAppearance();
sap.setReason("Certification of the document");
sap.setLocation("On server");
sap.setCertificate(maincertificate);
BouncyCastleDigest digest = new BouncyCastleDigest();
PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest,false);
//IExternalSignatureContainer like BlankContainer
PreSignatureContainer external = new PreSignatureContainer(PdfName.Adobe_PPKLite,PdfName.Adbe_pkcs7_detached);
signer.signExternalContainer(external, 8192);
byte[] hash=external.getHash();
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null,PdfSigner.CryptoStandard.CMS);// sh will be sent for signature
这是PreSignatureContainer类:
public class PreSignatureContainer implements IExternalSignatureContainer {
private PdfDictionary sigDic;
private byte hash[];
public PreSignatureContainer(PdfName filter, PdfName subFilter) {
sigDic = new PdfDictionary();
sigDic.put(PdfName.Filter, filter);
sigDic.put(PdfName.SubFilter, subFilter);
}
@Override
public byte[] sign(InputStream data) throws GeneralSecurityException {
String hashAlgorithm = "SHA256";
BouncyCastleDigest digest = new BouncyCastleDigest();
try {
this.hash= DigestAlgorithms.digest(data, digest.getMessageDigest(hashAlgorithm));
} catch (IOException e) {
throw new GeneralSecurityException("PreSignatureContainer signing exception",e);
}
return new byte[0];
}
@Override
public void modifySigningDictionary(PdfDictionary signDic) {
signDic.putAll(sigDic);
}
public byte[] getHash() {
return hash;
}
public void setHash(byte hash[]) {
this.hash = hash;
}
}
为什么这一步的结果无效
因为你基本上发现了一个错误…;)
您的示例输入文件具有一个触发 bug 的功能:它使用对象流进行压缩。
当iText处理这样的文件时,它还会尝试将尽可能多的对象放入对象流中。不幸的是,签名字典也是如此。这很不幸,因为在写入整个文件后,它试图将一些信息(以前不可用的)输入到这个字典中,这会损坏压缩对象流。
你可以选择
上面提到的补丁确实是微不足道的,方法< code>PdfSigner.preClose(Map
if (certificationLevel > 0) {
// add DocMDP entry to root
PdfDictionary docmdp = new PdfDictionary();
docmdp.put(PdfName.DocMDP, cryptoDictionary.getPdfObject());
document.getCatalog().put(PdfName.Perms, docmdp); // TODO: setModified?
}
document.close();
< code > crypto dictionary . getpdf object())就是我上面提到的签名字典。在< code>document.close()过程中,它被添加到对象流中,除非它以前已经被写入输出。因此,您只需在< code>close调用之前添加一个调用来刷新该对象,并通过参数表明它不应被添加到对象流中:
cryptoDictionary.getPdfObject().flush(false);
有了该补丁,您的代码返回的PDF就不会再像上面那样损坏了。
顺便说一句,iText 5确实在相应的签名中包含类似的行。
问题内容: 我正在尝试使用Rundeck构建,启动和链接一组Docker容器。简而言之(对于不熟悉docker的用户),启动映像时,它将返回容器ID。我想在启动后续作业时使用此容器ID。 从命令行运行时,它看起来像这样(仅示例!): (请注意在第二个命令行中使用第一个返回值) 此时,将有两个容器在运行。第二个将通过该选项链接到第一个,并且可使用第二个容器内部的主机名 host1 对其进行寻址。公平
我对Spring批处理框架相当陌生。 我在一个作业中创建了两个步骤(我们称之为步骤1和步骤2)。我想把它们并行运行。不仅如此,step2的IteamReader还应该使用step1的itemwriter。 我的第一个问题是,在Spring批量中是否有可能做到这一点?如果是,怎么做? 其次,如果这不可能,还有什么工作可以做呢? 谢了。
null 如果生成错误(文件不一致,文件不存在...),则不能执行 仅供参考,我使用的是没有XML配置的Spring批处理!只有注释:下面是我的作业配置类的样子:
我正在编写一个接收PKCS7数据(从签名的PDF文档中提取)的服务,并需要对其进行验证。 我使用iText7 PdfPKCS7进行验证,但签名验证总是失败。我可以从PKCS7读取所有其他信息(证书、时间戳等,我也用OpenSSL验证了这一点)。只有签名显示为无效。 下面是测试案例: 输出总是: 我想我在进口方面做错了什么,但就是找不到什么... 顺便说一句,验证其他pdf工具(Adobe DC、P
我刚刚创建了DocuSign开发人员帐户。我必须使用签名对PDF进行签名,并用C#将其发送给收件人。我不希望收件人使用https://developers.docusign.com/esign-rest-api/code-examples/code-example-request-a-signature-via-email。我的系统中已经有PDF可用,我需要使用DocuSign API签名并将其发
我需要多次调用webservice并传递使用来自多个表的数据创建的数据 UI->控制器->服务->(获取数据(表1,表2)并运行一些验证)1。如果验证失败-返回错误消息并停止。2.如果验证通过-调用JobLauncher并返回“任务启动”消息。 在异步作业中,我想到遵循2个步骤。 > bulkinsertstep > 我需要调用DB查询2个更多的表(Table3、table4)并创建一个大的数据集