使用Swisscom与iText 7进行QES签名前出现哈希不匹配问题
嘿,我之前帮好几个开发者排查过Swisscom QES和iText 7结合时的哈希不匹配问题,咱们一步步拆解可能的原因和解决办法:
先核对PdfSigner的核心配置
首先要确保你在初始化签名流程时,哈希算法完全对齐Swisscom的要求——也就是SHA-256。比如在创建ExternalBlankSignatureContainer的时候,指定的摘要算法必须是DigestAlgorithms.SHA256,不能错写成其他算法。另外,append模式下要保证没有额外修改PDF内容:调用signExternalContainer之后,绝对不能再对原PDF做任何编辑,否则待签数据的结构变了,哈希自然对不上。重点检查哈希的编码格式
这是最常见的坑!很多人会把SHA-256生成的字节数组直接转成十六进制字符串发给Swisscom,但Swisscom的QES API要求的是Base64编码的哈希值,不是十六进制。你可以检查下本地代码:是不是把待签字节流的SHA-256哈希转成了十六进制?如果是,改成Base64编码再和Swisscom那边的预期值对比试试。确认待签数据的正确性
你得保证拿到的是iText准备好的「待签原始数据」,而不是自己重新计算整个PDF的哈希。正确的做法是在ExternalBlankSignatureContainer的sign方法里,把传入的OutputStream替换成ByteArrayOutputStream,捕获iText生成的所有待签字节,再对这个字节数组计算SHA-256哈希。要是你直接对整个PDF文件计算哈希,那肯定和iText准备的待签数据哈希不一样——因为iText会给签名预留空间,待签数据是经过预处理的部分内容,不是整个PDF。核对Swisscom API的参数
调用Swisscom的签名接口时,要确认你指定的哈希算法参数是SHA-256,有没有手滑选成SHA-1或者SHA-512?另外,Swisscom的QES要求包含特定的PKCS#9签名属性,你可以检查iText的PdfSigner有没有设置正确的认证级别(比如setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED)),有没有添加必要的签名元数据,这些属性会被包含在待签数据里,缺了的话哈希也会不匹配。调试小技巧
你可以把本地捕获的待签字节流保存成一个临时文件,用命令行工具比如sha256sum计算它的哈希,和代码里生成的哈希对比,确认代码的哈希计算逻辑没错。如果能拿到Swisscom那边的预期哈希,把它转成字节数组后和本地哈希对比,就能快速定位是编码问题还是数据本身的问题。
备注:内容来源于stack exchange,提问作者Igor Stajic

