使用TCPDF签名PDF后添加TSA时间戳致签名无效问题咨询
问题背景
我用PHP的TCPDF给PDF签名,签名本身显示正常,但将Base64格式的PDF发送至TSA添加时间戳后,签名失效,Adobe提示「字节范围无效」。具体情况:
- 使用签名级别2
- 用其他已签名文档测试TSA,功能正常
- 采用PEM格式公私钥
- 推测问题出在签名流程,但无法定位具体原因
时间戳添加前后的ByteRange信息:
添加前:/ByteRange[0 1208654 1220398 12856]
添加后:/ByteRange[0 1208655 1220399 12856]
核心原因分析
从ByteRange的数值变化来看,添加时间戳后前两个数值各加1,说明PDF的字节数在Base64转换、传输或TSA处理环节被修改,破坏了签名时计算的字节范围校验逻辑。
具体排查&修复步骤
规范Base64转换流程
TCPDF生成的签名PDF是二进制文件,转Base64时必须直接对原始二进制内容调用base64_encode(),禁止先转成字符串再编码(比如用file_get_contents()读文件时不要加TEXT模式)。发送给TSA前解码Base64,必须用base64_decode()严格还原二进制,不能引入额外换行、空格或编码转换。跳过手动Base64环节,直接用TCPDF集成TSA
手动处理Base64容易引入字节变化,建议直接在TCPDF签名时配置TSA参数,让框架自动完成签名+时间戳流程,示例代码:$pdf->setSignature( 'file://path/to/private_key.pem', 'file://path/to/certificate.pem', 'your_passphrase', '', 3, // 启用时间戳支持的签名标志 array( 'url' => 'https://your-tsa-server-url', 'username' => '', // 若TSA需验证则填写 'password' => '' ) );检查TSA处理时的PDF结构修改
虽然其他文档测试正常,但当前PDF可能存在TSA自动调整的结构(比如字典顺序整理、额外换行插入)。可以用二进制对比工具,直接对比TSA返回的PDF和原始签名PDF的字节差异,定位被修改的具体内容。验证签名后PDF的完整性
签名完成后直接保存二进制PDF文件,跳过Base64转换环节,直接发送给TSA测试。如果此时签名不失效,说明问题出在Base64的编码/解码或传输过程中。确认ByteRange计算逻辑
PDF的ByteRange总和必须等于整个文件的字节数。添加时间戳后数值加1,说明有单个额外字节被插入(比如HTTP传输时的Content-Type设置错误,用了文本类型而非application/pdf),需排查传输环节的头部设置。
内容的提问来源于stack exchange,提问作者itar_

