[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案
[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案

引言
国密算法(SM2/SM3/SM4)在金融、政务等领域广泛应用,但开发者在集成gmssl库实现SM2签名时,常遇到与第三方工具(如OpenSSL、国密网关)验证不兼容的问题。本文深入剖析签名验证失败的五大核心原因,并提供可复现的代码解决方案,助你快速定位问题。
一、问题场景复现
使用gmssl生成SM2签名后,通过第三方工具(如OpenSSL命令行、其他语言SDK)验证时,返回“签名无效”或“格式错误”。例如:
# gmssl生成签名代码
from gmssl import sm2, funcsm2_crypt = sm2.CryptSM2(private_key=private_key, public_key=public_key)
sign = sm2_crypt.sign(message.encode(), func.random_hex(32))# 第三方工具验证失败
openssl pkeyutl -verify -in message.bin -sigfile sign.bin -pubin -inkey pubkey.pem
# 输出: Signature Verification Failure
二、五大核心原因与解决方案
1. 签名格式不兼容(ASN.1 vs 原始R/S拼接)
-
问题分析
gmssl默认生成的签名是ASN.1 DER编码格式(如3045022100...),而多数第三方工具要求64字节的R/S拼接值(如r=32字节, s=32字节)。 -
解决方案
方法一:关闭ASN.1编码,直接输出R+S拼接sm2_crypt = sm2.CryptSM2(private_key=private_key, public_key=public_key, asn1=False) sign = sm2_crypt.sign(message.encode(), random_k) # 输出为64字节十六进制方法二:手动解析ASN.1签名(需
asn1crypto库)from asn1crypto import coreder_sign = bytes.fromhex(sign) parsed = core.parse(der_sign) r = parsed.native['r'] s = parsed.native['s'] raw_sign = f"{r:064x}{s:064x}" # 拼接为64字节
2. 公钥/私钥格式错误
-
问题分析
- SM2公钥应为非压缩格式(前缀
04+ X + Y,共65字节,130字符十六进制)。 - 私钥应为32字节(64字符十六进制)。
- SM2公钥应为非压缩格式(前缀
-
解决方案
检查密钥格式:# 正确公钥示例 public_key = "04" + "x" * 128 # 130字符# 正确私钥示例 private_key = "f" * 64 # 64字符使用gmssl生成标准密钥对:
sm2_crypt = sm2.CryptSM2() private_key = sm2_crypt.generate_private_key() # 自动生成64字符私钥 public_key = sm2_crypt.generate_public_key() # 自动生成130字符公钥
3. 消息哈希处理不一致
-
问题分析
gmssl的sign()方法默认对消息自动计算SM3哈希,而第三方工具可能要求传入原始消息或手动哈希后的值。 -
解决方案
手动计算SM3哈希后签名:from gmssl import sm3msg = "原始消息".encode() hash_msg = sm3.sm3_hash(func.bytes_to_list(msg)) # 返回64字符哈希值 hash_bytes = bytes.fromhex(hash_msg)sign = sm2_crypt.sign(hash_bytes, random_k) # 传入哈希值而非原始消息
4. 随机数k生成不安全
-
问题分析
SM2签名依赖随机数k,若使用弱随机源(如random库),可能导致私钥泄露。 -
解决方案
使用密码学安全随机数生成器:import secretsrandom_k = secrets.token_hex(32) # 生成32字节安全随机数
5. 第三方工具验证命令错误
- 正确验证流程示例(OpenSSL)
# 1. 保存消息和签名(原始R+S拼接格式) echo -n "hello" > message.bin echo -n "a1b2..." | xxd -r -p > sign.bin # 替换为实际签名值# 2. 转换为PEM格式公钥(假设公钥为04...) echo "-----BEGIN PUBLIC KEY-----" > pubkey.pem echo "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE..." >> pubkey.pem # 替换为Base64编码公钥 echo "-----END PUBLIC KEY-----" >> pubkey.pem# 3. 执行验证 openssl pkeyutl -verify -in message.bin -sigfile sign.bin -pubin -inkey pubkey.pem
三、完整修复代码示例
from gmssl import sm2, func
import secrets
import tkinter as tk
from tkinter import messageboxclass SM2SignApp:def __init__(self):# 初始化GUI组件(省略布局代码)self.sm2_input = tk.Text()self.sm2_public_key = tk.Text()self.sm2_private_key = tk.Text()self.sm2_output = tk.Text()def sm2_sign(self):try:# 获取输入input_text = self.sm2_input.get("1.0", tk.END).strip().encode('utf-8')public_key = self.sm2_public_key.get("1.0", tk.END).strip()private_key = self.sm2_private_key.get("1.0", tk.END).strip()if not public_key or not private_key:messagebox.showerror("错误", "请先生成密钥对")return# 使用非ASN.1格式签名sm2_crypt = sm2.CryptSM2(private_key=private_key, public_key=public_key, asn1=False # 关键参数!!!)random_k = secrets.token_hex(32) # 安全随机数sign = sm2_crypt.sign(input_text, random_k)# 输出签名self.sm2_output.delete("1.0", tk.END)self.sm2_output.insert(tk.END, sign)except Exception as e:messagebox.showerror("错误", str(e))
四、总结与避坑指南
- 签名格式优先选择R/S拼接,禁用ASN.1编码(
asn1=False)。 - 严格校验密钥格式,公钥必须含
04前缀,私钥为64字符。 - 统一哈希处理逻辑,确认第三方工具是否需要原始消息或哈希值。
- 使用安全随机数,避免
random库,改用secrets或操作系统级随机源。 - 验证工具参数匹配,包括编码格式、哈希算法、密钥类型等。
附录:常见问题速查表
| 现象 | 可能原因 | 快速检测方法 |
|---|---|---|
| 签名长度不为64字符 | ASN.1编码未关闭 | 检查asn1=False参数 |
| 公钥验证失败 | 缺少04前缀或长度错误 | 查看公钥是否为130字符 |
| 相同消息每次签名不同 | 随机数k正常生效 | 此为SM2特性,非错误 |
| OpenSSL返回格式错误 | 签名未转换为二进制 | 使用xxd -r -p转换签名 |
如果本教程帮助您解决了问题,请点赞❤️收藏⭐支持!欢迎在评论区留言交流技术细节!欲了解更深密码学知识,请订阅《密码学实战》专栏 → 密码学实战
相关文章:
[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案
[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案 引言 国密算法(SM2/SM3/SM4)在金融、政务等领域广泛应用,但开发者在集成gmssl库实现SM2签名时,常遇到与第三方工具(如OpenSSL、国密网关)验证不…...
JavaScript模块化开发:CommonJS、AMD到ES模块
引言 在Web开发的早期阶段,JavaScript代码通常被编写在一个庞大的文件中或分散在多个脚本标签里,这种方式导致了全局变量污染、依赖关系难以管理、代码复用困难等问题。随着Web应用日益复杂,模块化编程成为了解决这些问题的关键。本文将带您…...
【k8s系列1】一主两从结构的环境准备
环境准备 虚拟机软件准备及安装,这里就不详细展开了,可以看文章:【一、虚拟机vmware安装】 linux环境准备及下载,下载镜像centOS7.9,以前也有写过这个步骤的文章,可以看:【二、安装centOS】 开始进入正题…...
dubbo SPI插件扩展点使用
参考:SPI插件扩展点 Dubbo SPI概述 使用IoC容器帮助管理组件的生命周期、依赖关系注入等是很多开发框架的常用设计,Dubbo中内置了一个轻量版本的IoC容器,用来管理框架内部的插件,实现包括插件实例化、生命周期、依赖关系自动注入…...
青少年编程与数学 02-016 Python数据结构与算法 26课题、生物信息学算法
青少年编程与数学 02-016 Python数据结构与算法 26课题、生物信息学算法 一、序列比对算法二、基因表达分析算法三、蛋白质结构预测算法四、系统生物学模型构建算法五、单细胞分析算法六、遗传关联分析算法七、机器学习与数据挖掘算法八、数据可视化算法九、代谢组学分析算法十…...
【Rust 精进之路之第2篇-初体验】安装、配置与 Hello Cargo:踏出 Rust 开发第一步
系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 **作者:**码觉客 发布日期: 2025-04-20 引言:磨刀不误砍柴工,装备先行! 在上一篇文章中,我们一起探索了 Rust 诞生的缘由&…...
洛谷题目:P7775 [COCI 2009/2010 #2] VUK 题解 (本题简)
题目传送门: P7775 [COCI 2009/2010 #2] VUK - 洛谷 (luogu.com.cn) 前言: 这道题的核心目标是找出狼从起点 V 到终点 J 的路径,使得狼在途中离它最近的树的距离的最小值最大。下面为大家详细讲解: #整体思路概述: 这道题我们可以采用“先计算距离,再来二分查找”的…...
腾讯旗下InstantCharacter框架正式开源 可高度个性化任何角色
目前基于学习的主题定制方法主要依赖于 U-Net 架构,但其泛化能力有限,图像质量也大打折扣。同时,基于优化的方法需要针对特定主题进行微调,这不可避免地会降低文本的可控性。为了应对这些挑战,我们提出了 “即时角色”…...
Python爬虫实战:获取fenbi网最新备考资讯
一、引言 1.1 研究背景 伴随互联网技术的迅猛发展,在线教育平台积累了海量备考数据。以粉某网为例,其备考数据涵盖考试资讯、备考资料、用户评价等,对备考者意义重大。然而,获取并分析这些数据颇具挑战,需借助先进的爬虫技术和数据分析方法。 1.2 研究目的 本研究旨在…...
详讲Linux下进程等待
3.进程等待 引言:什么是进程等待 想象有两个小伙伴,一个是 “大强”(父进程 ),一个是 “小强”(子进程 )。大强给小强安排了任务,比如去收集一些石头。 …...
JBoss + WildFly 本地开发环境完全指南
JBoss WildFly 本地开发环境完全指南 本篇笔记主要实现在本地通过 docker 创建 JBoss 和 WildFly 服务器这一功能,基于红帽的禁制 EAP 版本的重新分发,所以我这里没办法放 JBoss EAP 的 zip 文件。WildFly 是免费开源的版本,可以在红帽官网找…...
【网络原理】TCP协议如何实现可靠传输(确认应答和超时重传机制)
目录 一. TCP协议 二. 确定应答 三. 超时重传 一. TCP协议 1)端口号 源端口号:发送方端口号目的端口号:接收方端口号 16位(2字节)端口号,可以表示的范围(0~65535) 源端口和目的…...
【国家能源集团生态协作平台-注册/登录安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...
Java表达式1.0
Java开发工具 在当今的Java开发领域,IntelliJ IDEA已然成为了众多开发者心目中的首选利器,它被广泛认为是目前Java开发效率最快的IDE工具。这款备受瞩目的开发工具是由JetBrains公司精心打造的,而JetBrains公司总部位于风景如画的捷克共和国首…...
idea中导入从GitHub上克隆下来的springboot项目解决找不到主类的问题
第一步:删除目录下的.idea和target,然后用idea打开 第二步:如果有需要,idea更换jdk版本 原文链接:https://blog.csdn.net/m0_74036731/article/details/146779040 解决方法(idea中解决)&#…...
Android音视频开发
Android Framework 与音视频技术深度解析 一、Android音视频架构全景 ▶ 四层架构协同┌──────────────┐│ 应用层 │ ▶ MediaPlayer/ExoPlayer/Camera2 API调用└──────┬───────┘┌──────▼───────┐│ 框架层 │…...
【AI论文】CLIMB:基于聚类的迭代数据混合自举语言模型预训练
摘要:预训练数据集通常是从网络内容中收集的,缺乏固有的领域划分。 例如,像 Common Crawl 这样广泛使用的数据集并不包含明确的领域标签,而手动整理标记数据集(如 The Pile)则是一项劳动密集型工作。 因此&…...
Linux操作系统--环境变量
目录 基本概念: 常见环境变量: 查看环境变量的方法: 测试PATH 测试HOME 和环境变量相关的命令 环境变量的组织方式:编辑 通过代码如何获取环境变量 通过系统调用获取或设置环境变量 环境变量通常具有全局属性 基本概念…...
Jenkins 多分支管道
如果您正在寻找一个基于拉取请求或分支的自动化 Jenkins 持续集成和交付 (CI/CD) 流水线,本指南将帮助您全面了解如何使用 Jenkins 多分支流水线实现它。 Jenkins 的多分支流水线是设计 CI/CD 工作流的最佳方式之一,因为它完全基于 git(源代…...
精益数据分析(9/126):如何筛选创业路上的关键数据指标
精益数据分析(9/126):如何筛选创业路上的关键数据指标 大家好!在创业的漫漫长路中,数据就像一盏明灯,指引着我们前行的方向。但要让这盏灯发挥作用,关键在于找到那些真正有价值的数据指标。今天…...
C语言之图像文件的属性
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 图像文件属性提取系统设计与实现 目录 设计题目设计内容系统分析总体设计详细设计程序实现…...
LeetCode hot 100—分割等和子集
题目 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 示例 1: 输入:nums [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。…...
高等数学同步测试卷 同济7版 试卷部分 上 做题记录 上册期中同步测试卷 B卷
上册期中同步测试卷 B卷 一、单项选择题(本大题共5小题,每小题3分,总计15分) 1. 2. 3. 4. 5. 由f(2/n), n→∞可知 2/n→0, 即x→0. 二、填空题(本大题共5小题,每小题3分,总计15分) 6. 7. 8. 9. 10. 三、求解下列各题(本大题共5小…...
【算法】快速排序、归并排序(非递归版)
目录 一、快速排序(非递归) 1.原理 2.实现 2.1 stack 2.2 partition(array,left,right) 2.3 pivot - 1 > left 二、归并排序(非递归) 1.原理 2.实现 2.1 gap 2.1.1 i 2*gap 2.1.2 gap * 2 2.1.3 gap < array.…...
python-将文本生成音频
将文本生成音频通常需要结合 文本转语音(TTS,Text-to-Speech) 工具或库来实现,比如 Google TTS (gtts)、Amazon Polly、Microsoft Azure TTS 等。 一、使用 Google TTS (gtts) 将文本生成音频 gtts 是一个简单易用的 Python 库&a…...
[王阳明代数讲义]语言模型核心代码调研
语言模型核心代码调研 基于Consciciteation的才气张量持续思考综述将文本生成建模为才气张量网络扩散过程,实现非自回归推理通过才气张量的群-拓扑流形交叉注意力实现多模态推理,将输入压缩到低维空间持续迭代提出「条件计算提前终止」机制,…...
4月19日记(补)算了和周日一块写了 4月20日日记
周六啊 昨天晚上又玩的太嗨了。睡觉的时候有点晚了,眼睛疼就没写日记。现在补上 实际上现在是20号晚上八点半了。理论上来说应该写今天的日记。 周六上午打比赛啦,和研究生,输了,我是替补没上场。没关系再练一练明天就可以变强…...
trivy开源安全漏洞扫描器——筑梦之路
开源地址:https://github.com/aquasecurity/trivy.git 可扫描的对象 容器镜像文件系统Git存储库(远程)虚拟机镜像Kubernetes 在容器镜像安全方面使用广泛,其他使用相对较少。 能够发现的问题 正在使用的操作系统包和软件依赖项…...
【实战中提升自己】内网安全部署之dot1x部署 本地与集成AD域的主流方式(附带MAC认证)
1 dot1x部署【用户名密码认证,也可以解决私接无线AP等功能】 说明:如果一个网络需要通过用户名认证才能访问内网,而认证失败只能访问外网与服务器,可以部署dot1x功能。它能实现的效果是,当内部用户输入正常的…...
[matlab]南海地形眩晕图代码
[matlab]南海地形眩晕图代码 请ChatGPT帮写个南海地形眩晕图代码 图片 图片 代码 .rtcContent { padding: 30px; } .lineNode {font-size: 12pt; font-family: "Times New Roman", Menlo, Monaco, Consolas, "Courier New", monospace; font-style: n…...
