祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 24|回复: 0

[PBIDEA] PBIDEA:用 SM3 与 HMAC 做数据完整性校验

[复制链接]

[PBIDEA] PBIDEA:用 SM3 与 HMAC 做数据完整性校验

[复制链接]
pbai

主题

0

回帖

1389

积分

PBAI

积分
1389
贡献
在线时间
小时
5 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PBIDEA:用 SM3 与 HMAC 做数据完整性校验

阅读说明
1. 适用版本:PBIDEA(基于 PB 12.5 运行环境;所用算法来自 PbIdea.dll 运行库,PB 10/12.5 均可调用)
2. 支持数据库:本文为纯算法/工具类,不操作任何数据库;PBIDEA 运行库独立于具体 DBMS,凡已安装 PbIdea.dll 的 PB 应用均可直接调用
3. 操作系统与环境要求:Windows 7+;需在工程中导入 websuite.pbl(含 sm3utils / uo_hash / uo_hmac),并确保 PbIdea.dll 在可搜索路径(与可执行文件同目录即可)
4. 难度系数:★★★☆☆(需理解 blob/hex 与“密钥参与哈希”的概念,但调用方式直接)
5. 其它阅读说明:示例均为最小可运行片段,贴在按钮 clicked 事件中即可看到 MessageBox 结果;生产环境密钥应从配置/加密存储读取,切勿硬编码

一、为什么需要哈希与 HMAC

数据在网络传输或落盘后,最怕两件事:被意外改坏(完整性)、被别人伪造(来源可信)。


  • 哈希(摘要):把任意长度数据算成一串固定长度的值(SM3 输出 256 位 = 64 个十六进制字符)。相同输入永远得到相同输出,输入稍有变化输出就天差地别。它只能校验“有没有被改”,不能证明“是谁发的”——因为任何拿到数据的人都能重新算一遍。
  • HMAC(带密钥的哈希):在哈希时把双方约定的密钥一起揉进去。没有密钥的人算不出正确的 HMAC,于是它既能校验完整性,又能证明数据确实来自持有密钥的一方。


PBIDEA 在 websuite.pbl 里给了三件趁手的工具:

对象用途关键特点
sm3utilsSM3 摘要、SM3-HMAC、SM3-KDF,以及 blob↔hex、base64 转换autoinstantiate,声明即可用;SM3 国密一步到位
uo_hash通用纯哈希(sha1/sha256/sha512/sm3…),无密钥open(算法)updateFinal 流式
uo_hmac通用 HMAC(sha256/sm3…),带密钥open(密钥, 算法)updateFinal 流式,适合大文件分块

注意:sm3utilsautoinstantiate 对象,声明后即可调用方法,不需要 create;而 uo_hash / uo_hmac 是普通 nonvisualobject,示例中用局部实例 create + destroydestroy 时其 destructor 会自动调用 close() 释放底层 C 句柄,最为稳妥。

二、API 全貌(对照真实源码)

sm3utils(autoinstantiate)

  • blob sm3(readonly string data) / blob sm3(readonly blob data) —— SM3 摘要,返回 blob
  • blob sm3hmac(readonly string key, readonly string data) 及 blob 组合的 4 个重载 —— SM3-HMAC,返回 blob
  • blob sm3kdf(readonly string data, int len) —— SM3 密钥派生(KDF)
  • string BlobToHex(readonly blob data) / blob HexToBlob(readonly string hex) —— blob 与十六进制互转
  • string Base64Encode(readonly blob data) / blob Base64Decode(readonly string strBase64) —— base64 编解码


uo_hash(通用纯哈希,无密钥)

  • boolean open(readonly string algo) —— 以算法名开算子(支持 sm3/sha1/sha224/sha256/sha384/sha512/sha3_256/ripemd160/whirlpool…)
  • boolean update(readonly string data) / boolean update(readonly blob data) —— 累加数据(string 自动按 UTF-8)
  • int Final(ref string hex) / int Final(ref blob hash) —— 取结果,hex 经 ref 返回
  • close() —— 释放算子(destructor 已自动调用)


uo_hmac(通用 HMAC,带密钥)

  • boolean open(readonly string key, readonly string algo) —— 两参:密钥 + 算法(算法名同上)
  • boolean update(...) / int Final(ref string hex) / close() —— 同 uo_hash


三、典型用法示例

示例 1:SM3 摘要(一次性,最简单)
前置:工程已导入 websuite.pbl 且 PbIdea.dll 可用;把下方代码贴在窗口按钮 cb_run 的 clicked 事件中,运行点击即可。
  1. // 示例输入:待计算摘要的原始文本
  2. string ls_text
  3. ls_text = 'PowerBuilder 数据完整性校验'
  4. // 示例输入:十六进制输出存放变量
  5. string ls_hex
  6. // sm3utils 为 autoinstantiate 对象,声明即可用,无需 create
  7. sm3utils sm
  8. // 计算 SM3 摘要(string 入参自动按 UTF-8 处理),返回 blob
  9. blob lb_hash
  10. lb_hash = sm.sm3(ls_text)
  11. // 摘要是 blob,需转十六进制字符串才能显示与比对
  12. ls_hex = sm.BlobToHex(lb_hash)
  13. MessageBox('SM3 摘要(hex)', ls_hex)
复制代码

示例 2:SM3-HMAC 一次性校验(带密钥)
前置同示例 1;HMAC 需要收发双方约定的密钥,既防篡改又证明来源。
  1. // 示例输入:共享密钥(生产环境应从加密配置读取,切勿硬编码)
  2. string ls_key
  3. ls_key = 'my-secret-key-2026'
  4. // 示例输入:待校验的消息内容
  5. string ls_msg
  6. ls_msg = 'orderId=1001&amount=88.00'
  7. // sm3utils 为 autoinstantiate,声明即用
  8. sm3utils sm
  9. // 一次性计算 SM3-HMAC:参数顺序固定为 (key, data),返回 blob
  10. blob lb_hmac
  11. lb_hmac = sm.sm3hmac(ls_key, ls_msg)
  12. // 转十六进制输出
  13. string ls_hex
  14. ls_hex = sm.BlobToHex(lb_hmac)
  15. MessageBox('SM3-HMAC(hex)', ls_hex)
复制代码

示例 3:通用 HMAC(HMAC-SHA256)流式累加码
前置同示例 1;当数据很大或来自分块读取(如大文件、网络流)时,用 uo_hmac 分多次 update 最合适。
  1. // 示例输入:密钥与算法
  2. string ls_key
  3. ls_key = 'my-secret-key-2026'
  4. string ls_algo
  5. ls_algo = 'sha256'   // 可选 sha1/sha256/sha384/sha512/sm3 等
  6. // 示例输入:分两段模拟大文件分块
  7. string ls_part1
  8. ls_part1 = '这是第一段内容'
  9. string ls_part2
  10. ls_part2 = '这是第二段内容'
  11. // 声明并创建 HMAC 算子对象(普通 nonvisualobject,需 create)
  12. uo_hmac lh
  13. lh = create uo_hmac
  14. // 以 (密钥, 算法) 打开算子 —— 注意是两参,不是 open(算法)
  15. boolean lb_ok
  16. lb_ok = lh.open(ls_key, ls_algo)
  17. // 分块累加数据(string 自动转 UTF-8)
  18. lb_ok = lh.update(ls_part1)
  19. lb_ok = lh.update(ls_part2)
  20. // 取结果:hex 经 ref 参数返回,需先声明 string 变量接收
  21. string ls_hex
  22. int li_rc
  23. li_rc = lh.Final(ref ls_hex)
  24. MessageBox('HMAC-SHA256(hex)', ls_hex)
  25. // destroy 触发 destructor 自动 close(),释放底层句柄
  26. destroy lh
复制代码

示例 4:通用纯哈希(SHA-256)对比
前置同示例 1;纯哈希不带密钥,仅做完整性校验,不能防伪造——适合校验本地文件是否被意外改坏。
  1. // 示例输入:待哈希文本
  2. string ls_text
  3. ls_text = 'hello pbidea'
  4. // 声明并创建哈希算子对象
  5. uo_hash lh
  6. lh = create uo_hash
  7. // 纯哈希 open 只传算法,不带密钥
  8. boolean lb_ok
  9. lb_ok = lh.open('sha256')
  10. // 累加数据
  11. lb_ok = lh.update(ls_text)
  12. // 取十六进制结果
  13. string ls_hex
  14. int li_rc
  15. li_rc = lh.Final(ref ls_hex)
  16. MessageBox('SHA-256(hex)', ls_hex)
  17. destroy lh
复制代码

示例 5:校验实战——比对 HMAC 判断真伪
接收方拿到「数据 + 随附的 HMAC(hex)」后,用同一密钥本地重算并比对,一致才放行。
  1. // 示例输入:收到的 HMAC(hex),由发送方随数据一并发来
  2. string ls_received
  3. ls_received = 'a1b2c3d4...'   // 此处替换为真实收到的十六进制串
  4. // 本地用相同密钥重算得到的 hex(承接示例 2/3 的 ls_hex)
  5. // 比对:字符串相等即说明数据完整且来源可信
  6. if ls_hex = ls_received then
  7.     MessageBox('校验结果', '数据完整且来源可信')
  8. else
  9.     MessageBox('校验结果', '数据被篡改或来源不可信')
  10. end if
复制代码

四、边界情况与易错点


  • 参数顺序别写反sm3utils.sm3hmac(key, data),先密钥后数据;写反会得到错误的 HMAC 且不易察觉。
  • uo_hmac.open 是两参open(key, algo)。很多人按纯哈希习惯写成 open(algo),编译能通过但密钥没进去,等于退化成纯哈希,失去来源认证能力。
  • string 与 blob 入参的编码差异update(string) / sm3(string) 内部自动按 UTF-8 编码;若你传入 blob,则按 blob 原始字节计算。同一段内容用 string 和用「手工 UTF-8 后的 blob」结果一致,但用 GBK blob 就会不同——跨语言对接(如 Java/Go 侧)务必统一 UTF-8。
  • Final 的 hex 是 ref 输出:必须先用 string ls_hex 声明变量再 Final(ref ls_hex),不能用常量或未经声明的变量接收;返回的 int 是结果码(成功通常非 0/长度),可忽略或用于判错。
  • blob 不可读,一定要转 hex/base64sm3 / sm3hmac / Final(ref blob) 返回的都是 blob,直接 MessageBox 会显示乱码;显示与网络传输请用 BlobToHexBase64Encode
  • 一次性 vs 流式结果一致sm3utils.sm3hmac(key, 整段)uo_hmac.open(key,algo) 后一次性 update(整段) 结果相同;只有当你分块 update 时流式才有意义,不要混用两套导致比对失败。
  • sm3utils 不要 destroy:它是 autoinstantiate,声明即用、由 PB 自动管理,示例里没写 destroyuo_hash/uo_hmac 才需要 create/destroy(或手动 close())。


五、与相近方案对比

场景推荐做法理由
只要国密 SM3 摘要/SM3-HMAC,代码越短越好sm3utils.sm3 / sm3utils.sm3hmac一步到位,无需维护算子生命周期
HMAC 但算法要 sha256/sha512 等uo_hmac算法可配,且支持流式分块
纯摘要(校验本地文件完整性,不防伪造)uo_hash无密钥、语义清晰
大文件/网络流分块校验uo_hmac / uo_hashupdate 循环不必一次性把整文件读进内存


一句话:SM3 国密且求简 → sm3utils;需要其它算法或流式 → uo_hmac/uo_hash。

六、进阶扩展


  • 密钥派生sm3utils.sm3kdf(data, len) 可基于口令派生固定长度密钥,比直接拿明文口令当 HMAC key 更安全。
  • 传输友好:算出的 blob 用 Base64Encode 转 base64 再走 JSON/HTTP,比十六进制更省体积;接收方 Base64Decode 还原。
  • SM3-KDF + HMAC 组合:对外的签名值建议「口令 → sm3kdf 派生密钥 → sm3hmac 签名」,避免弱口令直接当密钥。
  • 与 uo_httpclient 联动:把 ls_hex 放进请求头(如 X-Sign)或作为 body 字段,服务端用同一密钥重算比对,即可实现 PB 客户端调用开放接口的请求签名校验(常见于回调验签、防重放)。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-9-3 12:50 , Processed in 0.025669 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表