"AT least one signature is invalid" 使用 itext 从 pdf 中删除签名后出现错误消息
"AT least one signature is invalid" error message after removing signature from pdf using itext
我有一个带有多个签名的数字签名 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 上出现以下错误 reader
"At least one of the signatures is invalid"
您不能从已签名文档的字典中删除键,并希望签名保持有效。您只能删除最后添加的签名。如果一个文档被多人签名,而你想删除第一个签名,所有后续签名都将被破坏。
这张图片解释了原因:
此图显示每个新的数字签名都保持原始字节不变。每个新签名都会添加新字节。 Rev1 表示具有 1 个数字签名的文档的字节。 Rev2 表示具有 2 个数字签名的文档的字节。第二个数字签名对 Rev1 进行完整签名。如果您删除第一个签名,第二个签名将失效。
数字签名是一种特殊类型的表单域。使用 iText,您可以像这样获取 PDF 签名表单字段的名称:
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
您只能删除覆盖整个文档的签名,例如,如果我们有 "sig1"
、"sig2"
和 "sig3"
(按顺序添加),则只有 fields.signatureCoversWholeDocument("sig3")
将 return 为真。
你可以像这样得到总的修订数:fields.getTotalRevisions()
和一个特定的修订像这样:fields.getRevision("sig1")
(前提是有一个名为"sig1"
的签名字段)。
假设图像代表您的文档,并且您必须删除 1 个签名,那么您只能通过删除在修订 3 (Rev3) 中添加的所有字节来删除第三个签名。对于 iText,这意味着回到修订版 2 (Rev2)。该修订版是使用签名字段 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"
签名的文件,没有创建 "sig3"
.
时添加的字节
我有一个带有多个签名的数字签名 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 上出现以下错误 reader "At least one of the signatures is invalid"
您不能从已签名文档的字典中删除键,并希望签名保持有效。您只能删除最后添加的签名。如果一个文档被多人签名,而你想删除第一个签名,所有后续签名都将被破坏。
这张图片解释了原因:
此图显示每个新的数字签名都保持原始字节不变。每个新签名都会添加新字节。 Rev1 表示具有 1 个数字签名的文档的字节。 Rev2 表示具有 2 个数字签名的文档的字节。第二个数字签名对 Rev1 进行完整签名。如果您删除第一个签名,第二个签名将失效。
数字签名是一种特殊类型的表单域。使用 iText,您可以像这样获取 PDF 签名表单字段的名称:
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
您只能删除覆盖整个文档的签名,例如,如果我们有 "sig1"
、"sig2"
和 "sig3"
(按顺序添加),则只有 fields.signatureCoversWholeDocument("sig3")
将 return 为真。
你可以像这样得到总的修订数:fields.getTotalRevisions()
和一个特定的修订像这样:fields.getRevision("sig1")
(前提是有一个名为"sig1"
的签名字段)。
假设图像代表您的文档,并且您必须删除 1 个签名,那么您只能通过删除在修订 3 (Rev3) 中添加的所有字节来删除第三个签名。对于 iText,这意味着回到修订版 2 (Rev2)。该修订版是使用签名字段 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"
签名的文件,没有创建 "sig3"
.