我有一个PDF文件签名和.p7s文件。我需要从PDF中检索.p7s并共同签署PDF(生成其他.p7s)。 之后我需要再将p7s放入PDF文件中。 当我尝试从PDF获取p7时,我收到此错误: ExceptionConverter:java.security.SignatureException:未初始化用于签名的对象 我的代码:
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
PdfReader pdfReader = new
PdfReader(Files.readAllBytes(inputFile.toPath()));
AcroFields acroFields = pdfReader.getAcroFields();
List<String> signatures = acroFields.getSignatureNames();
for (String name : signatures) {
PdfPKCS7 pdfPkcs7 = acroFields.verifySignature(name, "BC");
Files.write(Paths.get("~/TEST/itext/"+ name +".p7s"),
pdfPkcs7.getEncodedPKCS7());//ERROR HERE!
}
答案 0 :(得分:0)
您希望通过从PDF中提取嵌入式CMS签名容器,为其添加签名并重新嵌入,来共同签署PDF (反号?并行签名?)扩展容器。
这是错误的方法,PDF签名只针对每个PDF签名字段包含一个签名,而我们所讨论的CMS签名容器本质上就是这样一个字段的值,因此每个嵌入式签名容器应只包含一个签名
严格来说,PDF规范允许您使用任意自定义签名方案,只允许使用#34;可互操作的签名&#34;是有限的。因此,具有多个签名的签名容器可以被视为有效的PDF,而不是#34;互操作签名&#34;,即您不应该期望任何其他软件像您一样解释签名。特别是Adobe Acrobat Reader将只识别和显示其中一个签名。
(事实上,一些大型签名解决方案提供商已经在PDF中嵌入了多签名CMS容器。例如,目前我必须处理由嵌入任意CAdES-A签名容器的某个此类提供程序生成的签名(特别是一些有多个签名者)并将这种签名格式称为PDF / CAdES-A,现在我必须向他们的客户解释他们的签名是PDF签名,但不能互操作,即使这个名称PDF / CAdES-A听起来像一些很棒的标准......)
PDF中用于互操作性的多个签名必须按照此草图中可视化的顺序应用:
对于某些背景和更多信息的链接,请参阅this answer
您的代码似乎是iText 5.5.x代码,特别是还没有iText 7.x代码。在这种情况下,您可以按原样使用Digital Signatures for PDF Documents白皮书中的代码{/ 3}}。
一个非常简单的例子:
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm,
String provider, CryptoStandard subfilter, String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
}
(代码示例2.1:使用iText签名的“Hello World”)
由于您的使用案例涉及签署已签名的文档,您只需将PdfStamper.createSignature
行更改为
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', true);
(注意最后的新布尔参数)。此更改导致在追加模式中创建签名,这使得前一版本具有原始签名,而不会使该签名无效。