我的网络服务器会生成一个pdf,对其进行签名并将其提供给客户端。客户端多次签名(使用Adobe Pro使用不同的令牌),然后将其上传回服务器。
我希望服务器验证它是否是以前由服务器生成的pdf。我读到在应用多个签名时更改了哈希。如何使用iText轻松验证?
答案 0 :(得分:4)
如果正确完成,同一PDF中的多个集成签名将通过增量更新应用,参见信息安全堆栈交换this answer:
因此,在某种程度上你读到的是真的
我读到在应用多个签名时更改了哈希值。
(实际上,整个文件的哈希值会发生变化,除非你的碰撞极不可能),你的初始签名的字节的哈希值仍然适用于,可以是从文档中检索。
因此,根据您要检查的内容以及您仍然拥有的信息,有以下明显选项:
我的网络服务器生成pdf,签名并将其提供给客户
如果您仍然将某个初始签名PDF存储在某个地方(例如在数据库中),并且您想要检查客户端上传回给您的PDF是否基于该PDF,那么您需要做的就是检查客户端和#39;的PDF字节流以您存储的PDF字节开头。
这不需要额外使用加密函数或PDF特定API,只需比较它们的字节或块。
我的网络服务器生成pdf,签名并将其提供给客户
如果您没有将初始签名PDF存储在任何地方,或者您只想检查客户上传回给您的PDF是否基于您签署的许多可能的基本PDF之一,则无法进行直接修订比较或资源非常密集。
在这种情况下,您应该检查文档的初始签名是否
有许多关于如何检查PDF中签名完整性的示例,例如
public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
PdfPKCS7 pkcs7 = fields.verifySignature(name);
System.out.println("Integrity check OK? " + pkcs7.verify());
return pkcs7;
}
public void verifySignatures(String path) throws IOException, GeneralSecurityException {
System.out.println(path);
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
for (String name : names) {
System.out.println("===== " + name + " =====");
verifySignature(fields, name);
}
System.out.println();
}
(来自iText数字签名白皮书的C5_01_SignatureIntegrity.java)
对于你的任务,你实际上可以简单地限制自己只检查第一个签名,但检查其他签名也可能是个好主意。
要检查服务器是否已创建初始签名,请假设您的Web服务器使用专用于此任务的X509证书(或一组已知此类证书)对这些PDF进行签名。
您可以使用从getSigningCertificate
调用第一个签名中检索到的PdfPKCS7
对象的方法verifySignature
来检索用于创建初始签名的证书。您所要做的就是检查证书是否是您专门用于此任务的一个证书(或一组证书)。