TSHA1Digest = array[0..19] of Byte;
TSHA1Context = record
State: array[0..4] of Cardinal;
Buffer: array[0..63] of Byte;
BufCnt: Cardinal;
Length: UInt64;
end;
procedure SHA1Init(out Ctx: TSHA1Context);
procedure SHA1Update(var Ctx: TSHA1Context; const Buf; BufLen: Cardinal);
procedure SHA1Final(var Ctx: TSHA1Context; out Digest: TSHA1Digest);
function SHA1Bytes(const B: TBytes): TSHA1Digest;
function SHA1Of(const Buf; BufLen: Cardinal): TSHA1Digest;
function SHA1Hex(const Digest: TSHA1Digest): string;
FPdfSha1 用纯 Pascal 实现 SHA-1,除 SysUtils 之外没有其他依赖,因此本库在所有受支持的编译器上保持自包含。压缩函数遵循 FIPS 180-4 6.1,FIPS 180-4 5.1.1 的填充规则先把消息填充到 56 mod 64 字节,再附加八个字节的大端位长度。加载与存储都是逐字节显式的大端序,因此结果在库面向的所有 CPU 上都一致
增量式 SHA1Init / SHA1Update / SHA1Final API 对分块提交的输入做哈希。SHA1Update 把完整的 64 字节块直接交给变换,只把余量缓存在 TSHA1Context 中,因此一次喂入一个大块与分几次喂入相同字节得到相同的摘要
SHA1Bytes 和 SHA1Of 是针对字节数组或给定长度无类型缓冲区的一次性辅助函数;空的 TBytes 会被接受并按空消息哈希。SHA1Hex 把 TSHA1Digest 渲染为小写的 40 字符十六进制字符串,证书指纹通常以这种形式进行比较
| Function | Description |
|---|---|
SHA1Init | 把哈希上下文初始化为 FIPS 180-4 5.3.1 的初始状态,并清空其缓冲区和计数器 |
SHA1Update | 把无类型缓冲区的 BufLen 个字节喂入打开的上下文;长度为零时为空操作 |
SHA1Final | 应用填充与长度块,然后返回 20 字节摘要 |
SHA1Bytes | 对字节数组做一次性哈希 |
SHA1Of | 对给定长度的无类型缓冲区做一次性哈希 |
SHA1Hex | 把摘要格式化为小写的 40 字符十六进制字符串 |
| Type | Description |
|---|---|
TSHA1Digest | 20 字节 SHA-1 摘要,单元中所有哈希入口点的结果类型 |
TSHA1Context | 增量哈希上下文:State 保存五个工作字,Buffer 保存未满的 64 字节消息块,BufCnt 统计缓冲区中当前的字节数,Length 以字节累计消息总长度 |
在本库中 SHA-1 不是签名摘要,也绝不能变成签名摘要。PAdES 栈全程使用 SHA-256 签名,消息摘要、已签名属性和时间戳请求概莫能外。签名路径上的任何环节都不应移到本单元上
FPdfSha1 只为一件事而存在:把证书与 TPadesSignerOptions 携带的 SHA-1 指纹进行匹配。令牌后端拿到的是证书 DER,必须自己做这一比较,因此它用 SHA1Bytes 对 DER 做哈希,再把 SHA1Hex 的结果与配置的指纹进行不区分大小写的比较。在 Windows 上,证书存储区在证书查找期间就完成了指纹解析,因此 Windows 后端从来不需要自己的实现
如果你在为新代码寻找哈希,这里不是通用之选。凡是在意抗碰撞性的场景,包括文档摘要、已签名属性和完整性检查,SHA-1 都不适用。请改用 FPdfSha256;需要更长或其他摘要族时可用 FPdfSha512 或 FPdfSha3