我有一个带有多个签名的数字签名pdf。现在我想只删除其中一个签名。我正在使用itext。代码如下:
PdfReader reader = new PdfReader(src_path);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest_path));
{
AcroFields.Item item = stamper.getAcroFields().getFieldItem(fieldname);
ClearSignatureDictionary(item.getMerged(0));
ClearSignatureDictionary(item.getWidget(0));
ClearSignatureDictionary(item.getValue(0));
}
}
private static void ClearSignatureDictionary(PdfDictionary dic)
{
dic.remove(PdfName.AP);
dic.remove(PdfName.AS);
dic.remove(PdfName.V);
dic.remove(PdfName.DV);
dic.remove(PdfName.SV);
dic.remove(PdfName.FF);
dic.put(PdfName.F, new PdfNumber(4));
}
但是当我用删除的签名打开文档时,它在Acrobat阅读器上给出了以下错误 “至少有一个签名无效”
答案 0 :(得分:2)
您无法从签名文档中的字典中删除密钥,并希望签名保持有效。您只能删除添加的最后一个签名。如果文档由多人签名,并且您要删除第一个签名,则所有后续签名都将被破坏。
此图片解释了原因:
此图像显示每个新的数字签名都保持原始字节不变。每个新签名都会添加新字节。 Rev1表示具有1个数字签名的文档的字节。 Rev2表示具有2个数字签名的文档的字节。第二个数字签名完全标志着Rev1。如果您删除第一个签名,则第二个签名将无效。
数字签名是一种特殊类型的表单字段。使用iText,您可以获得PDF的签名表单字段的名称,如下所示:
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
您只能删除涵盖整个文档的签名,例如,如果我们有"sig1"
,"sig2"
和"sig3"
(按此顺序添加),则只有{{1将返回true。
您可以获得这样的修订总数:fields.signatureCoversWholeDocument("sig3")
以及类似的特定修订:fields.getTotalRevisions()
(前提是有一个名为fields.getRevision("sig1")
的签名字段。)< / p>
假设图像代表您的文档,并且您必须删除1个签名,那么您只能通过删除在修订版3(Rev3)中添加的所有字节来删除第三个签名。使用iText,这意味着返回修订版2(Rev2)。该修订是使用签名字段"sig1"
签署的。
您可以像这样提取此修订:
sig2
文件FileOutputStream os = new FileOutputStream("revision2.pdf");
byte bb[] = new byte[1028];
InputStream ip = fields.extractRevision("sig2");
int n = 0;
while ((n = ip.read(bb)) > 0)
os.write(bb, 0, n);
os.close();
ip.close();
将是由revision2.pdf
和"sig1"
签名的文件,不包含创建"sig2"
时添加的字节。