PDF Signing,生成的PDF文档认证无效? (使用外部签名、web-eid、HSM)
PDF Signing, generated PDF Document certification is invalid? (using external signing, web-eid, HSM)
我有一项服务可以对数据进行签名并向我提供签名的哈希值,
它正确生成 PKCS#7 DigestInfo,如 rfc2315#section-9.4
中所述
像这样
上述系统的代码是:https://pastebin.com/b3qZH6xW
//prepare signature
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Ankit");
signature.setLocation("Bhopal, IN");
signature.setReason("Testing");
// TODO extract the above details from the signing certificate? Reason as a parameter?
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
if (accessPermissions == 0)
{
setMDPPermission(document, signature, 3);
}
FileOutputStream fos = new FileOutputStream(new File("signed_file.pdf"));
DetachedPkcs7 detachedPkcs7 = new DetachedPkcs7();
//populate signature options for visible signature. if any.
SignatureOptions signatureOptions = null;
document.addSignature(signature);
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(fos);
InputStream dataToSign = externalSigning.getContent();
byte[] cmsSignature = detachedPkcs7.sign(dataToSign);
externalSigning.setSignature(cmsSignature);
工作流程是这样的
- 获取原始 PDF
- 添加签名字典并获取哈希
- 将散列发送给客户端
- 等待标准输入上的数据。
- 等待客户端发回已签名的哈希,然后提供此数据
到暂停的程序,也就是说,数据被发送到标准输入
程序
- 添加内容管理系统。 :)
我不知道为什么使用此过程生成的 PDF 的签名显示为无效。
客户端或与其通信至少有两个问题:
DigestInfo 结构中假定的哈希算法错误
客户端返回的签名值,当使用签名者证书的 public 密钥解密时,包含此 DigestInfo
结构:
0 81: SEQUENCE {
2 13: SEQUENCE {
4 9: OBJECT IDENTIFIER sha-512 (2 16 840 1 101 3 4 2 3)
15 0: NULL
: }
17 64: OCTET STRING
: '413140d54372f9baf481d4c54e2d5c7bcf28fd6087000280'
: 'e07976121dd54af2'
: }
特别是它声称 SHA512 已用于计算哈希。尽管如此,它包含一个长度为 32 字节的摘要值,因此不能是 SHA512 摘要值!
所以你的主张
I have a service which signs the data and provides me with the signed hash, it correctly generates PKCS#7 DigestInfo as stated in rfc2315#section-9.4
要么不正确,要么您与服务通信的代码向它提供了不正确的数据。
因此,请修复您的客户端或客户端通信组件,使其将正确的摘要算法 OID 引入已签名的 DigestInfo
结构中。
哈希值错误
即使修改了上面的OID,里面的hash值也是错误的,你的PDF的signed ranges的正确SHA256 hash值是
9a75434965d5cf2635eb963752494b408a480effabfca1d87b82e619040dfb4b
因此,请调试您的工具链,找出错误哈希值的来源。
附录:CMS容器的结构
您的解决方案的另一个缺点是生成的 CMS 容器的结构非常简单。特别是它根本不包含签名属性。虽然 CMS 规范允许这样做,但对于许多可能的伪造攻击来说,这是极其不安全的。因此,目前规范中几乎没有任何CMS容器配置文件认为这种签名容器有效。
因此,除非您的签名文档仅在非常受控的环境中使用,并采取组织措施防止这些伪造攻击,否则它们的价值实际上为零。
我有一项服务可以对数据进行签名并向我提供签名的哈希值, 它正确生成 PKCS#7 DigestInfo,如 rfc2315#section-9.4
中所述像这样
上述系统的代码是:https://pastebin.com/b3qZH6xW
//prepare signature
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Ankit");
signature.setLocation("Bhopal, IN");
signature.setReason("Testing");
// TODO extract the above details from the signing certificate? Reason as a parameter?
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
if (accessPermissions == 0)
{
setMDPPermission(document, signature, 3);
}
FileOutputStream fos = new FileOutputStream(new File("signed_file.pdf"));
DetachedPkcs7 detachedPkcs7 = new DetachedPkcs7();
//populate signature options for visible signature. if any.
SignatureOptions signatureOptions = null;
document.addSignature(signature);
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(fos);
InputStream dataToSign = externalSigning.getContent();
byte[] cmsSignature = detachedPkcs7.sign(dataToSign);
externalSigning.setSignature(cmsSignature);
工作流程是这样的
- 获取原始 PDF
- 添加签名字典并获取哈希
- 将散列发送给客户端
- 等待标准输入上的数据。
- 等待客户端发回已签名的哈希,然后提供此数据
到暂停的程序,也就是说,数据被发送到标准输入
程序
- 添加内容管理系统。 :)
我不知道为什么使用此过程生成的 PDF 的签名显示为无效。
客户端或与其通信至少有两个问题:
DigestInfo 结构中假定的哈希算法错误
客户端返回的签名值,当使用签名者证书的 public 密钥解密时,包含此 DigestInfo
结构:
0 81: SEQUENCE {
2 13: SEQUENCE {
4 9: OBJECT IDENTIFIER sha-512 (2 16 840 1 101 3 4 2 3)
15 0: NULL
: }
17 64: OCTET STRING
: '413140d54372f9baf481d4c54e2d5c7bcf28fd6087000280'
: 'e07976121dd54af2'
: }
特别是它声称 SHA512 已用于计算哈希。尽管如此,它包含一个长度为 32 字节的摘要值,因此不能是 SHA512 摘要值!
所以你的主张
I have a service which signs the data and provides me with the signed hash, it correctly generates PKCS#7 DigestInfo as stated in rfc2315#section-9.4
要么不正确,要么您与服务通信的代码向它提供了不正确的数据。
因此,请修复您的客户端或客户端通信组件,使其将正确的摘要算法 OID 引入已签名的 DigestInfo
结构中。
哈希值错误
即使修改了上面的OID,里面的hash值也是错误的,你的PDF的signed ranges的正确SHA256 hash值是
9a75434965d5cf2635eb963752494b408a480effabfca1d87b82e619040dfb4b
因此,请调试您的工具链,找出错误哈希值的来源。
附录:CMS容器的结构
您的解决方案的另一个缺点是生成的 CMS 容器的结构非常简单。特别是它根本不包含签名属性。虽然 CMS 规范允许这样做,但对于许多可能的伪造攻击来说,这是极其不安全的。因此,目前规范中几乎没有任何CMS容器配置文件认为这种签名容器有效。
因此,除非您的签名文档仅在非常受控的环境中使用,并采取组织措施防止这些伪造攻击,否则它们的价值实际上为零。