️️️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践20241212
🛡️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践
✨ 引言
在当下的数据安全环境中,SM4作为中国国家密码算法的代表性选择,被广泛应用于金融、通信和政府领域。然而,在实际开发中,即便是开源加密库也可能隐藏深层次的问题,开发者常常需要对其功能和实现逻辑进行严格审查。最近,我在使用 gmssl 库实现 SM4 加密算法时,因填充逻辑问题陷入了困境。经过深入排查与修复,我不仅解决了问题,本文记录了一次真实的调试经历,揭示了如何高效定位并修复开源加密库gmssl中的潜在bug,还总结了一些通用的代码实践和调试经验。
🎯 本文要点:
- 揭示 gmssl 填充问题的根本原因。
- 提供填充问题的修复方法与多种实现风格。
- 分享 SM4 加解密的高效实现与最佳实践。
无论你是初学者还是资深开发者,相信这篇文章都能对你有所启发。
🛠️ 问题背景
🔑 关于 gmssl 库与 SM4 算法
gmssl 是一款支持国密标准的开源加密库,而 SM4 算法是其中的核心对称加密算法,应用场景广泛:
- 数据保护:如金融交易数据。
- 通信安全:如内网通信。
- 身份验证:如国密 HTTPS。
💡 填充模式:
- PKCS7 填充:主流且成熟,适合通用场景。
- ZERO 填充:用于固定长度数据流,但对边界场景要求更高。
❌ 遇到的问题
在调用 gmssl 解密时,程序报错如下:
TypeError: 'int' object is not iterable
🕵️ 问题定位
错误来自 gmssl 的填充移除函数 zero_unpadding:
zero_unpadding = lambda data, i=1: data[:-i] if data[-i] == 0 else i + 1
⚠️ 问题核心:
当数据未包含零填充时,data[-i] != 0,函数直接返回了整数 i + 1,而非预期的字节列表,导致后续处理失败。
🛠️ 修复方案
🚀 重新设计 zero_unpadding 函数
方法 1️⃣:普通函数实现
def zero_unpadding(data: list) -> list:"""Remove ZERO padding from decrypted dataArgs:data: List of bytes with ZERO paddingReturns:List of bytes with padding removedExamples:[1,2,3,0,0,0] -> [1,2,3][1,2,0,3,0,0] -> [1,2,0,3]"""if not data:return datafor i in range(len(data) - 1, -1, -1):if data[i] != 0:return data[:i + 1]return []```
我们设计了一组测试用例,覆盖常见场景:
```python
def test_zero_unpadding():"""测试零填充移除函数的各种情况"""test_data = [([1, 2, 3, 0, 0, 0], [1, 2, 3]), # 标准情况:末尾有零填充([1, 2, 3], [1, 2, 3]), # 无填充([0, 0, 0], []), # 全零([], []), # 空列表([1, 2, 0, 3, 0, 0], [1, 2, 0, 3]), # 中间有零([0, 1, 2, 0, 0], [0, 1, 2]), # 开头有零([1, 0, 2, 0, 0], [1, 0, 2]), # 中间和末尾都有零([255, 0, 0, 0], [255]), # 大数值测试]for input_data, expected in test_data:result = zero_unpadding(input_data)print(f"Input: {input_data}")print(f"Expected: {expected}")print(f"Got: {result}")assert result == expected, f"Test failed: expected {expected}, got {result}"print("✓ Test passed\n")# 运行测试
try:test_zero_unpadding()print("All tests passed successfully! 🎉")
except AssertionError as e:print(f"Test failed: {e}")
✅ 测试结果
/opt/anaconda3/envs/kids_tutor_env/bin/python /Users/xyl/Documents/git_src/kids-tutor-and-efficiency-scripts/study_md5/test.py
Input: [1, 2, 3, 0, 0, 0]
Expected: [1, 2, 3]
Got: [1, 2, 3]
✓ Test passedInput: [1, 2, 3]
Expected: [1, 2, 3]
Got: [1, 2, 3]
✓ Test passedInput: [0, 0, 0]
Expected: []
Got: []
✓ Test passedInput: []
Expected: []
Got: []
✓ Test passedInput: [1, 2, 0, 3, 0, 0]
Expected: [1, 2, 0, 3]
Got: [1, 2, 0, 3]
✓ Test passedInput: [0, 1, 2, 0, 0]
Expected: [0, 1, 2]
Got: [0, 1, 2]
✓ Test passedInput: [1, 0, 2, 0, 0]
Expected: [1, 0, 2]
Got: [1, 0, 2]
✓ Test passedInput: [255, 0, 0, 0]
Expected: [255]
Got: [255]
✓ Test passedAll tests passed successfully! 🎉进程已结束,退出代码为 0
结果汇总
所有测试用例都通过了,这证明我们的 zero_unpadding 函数完全符合预期。让我们总结一下测试覆盖的场景:
- 1.标准填充场景:[1,2,3,0,0,0]>[1,2,3]
验证正常的未尾零填充移除 - 2.无填充场景:[1,2,3]>[1,2,3]验证对无填充数据的正确处理
- 3.全零场景:[0,0,0]→>[]验证极端情况:全是填充
- 4.空列表场景:[]>[]
验证边界情况:空输入 - 5.中间包含零场景:[1,2,0,3,0,0]>[1,2,0,3]验证保留数据中的有效零值
- 6.开头包含零场景:[0,1,2,0,0]>[0,1,2]
验证保留开头的有效零值 - 7.混合零场景:[1,0,2,0,0]>[1,0,2]验证同时处理有效零和填充零
- 8.大值测试:[255,0,0,0]>[255]
验证对大数值的处理
这些测试结果表明该实现:
✅ 正确处理所有边界情况
✅ 保留数据中的有效零值
✅ 只移除末尾的填充零
✅ 处理各种数值范围
✅ 行为稳定且可预测
这个实现现在可以安全地用在您的 SM4 加密解密过程中了!
⭐ 优秀实践分享:SM4 加解密核心代码
🔐 核心函数实现
加密与解密核心逻辑
def encrypt_sm4_hex(key: str, value: str) -> str:"""SM4 HEX模式加密"""crypt_sm4 = CryptSM4(mode=SM4_ENCRYPT, padding_mode=1)crypt_sm4.set_key(bytes.fromhex(key), SM4_ENCRYPT)encrypted_value = crypt_sm4.crypt_ecb(bytes.fromhex(value))return encrypted_value.hex().upper()def decrypt_sm4_hex(key: str, encrypted_value: str) -> str:"""SM4 HEX模式解密"""crypt_sm4 = CryptSM4(mode=SM4_DECRYPT, padding_mode=1)crypt_sm4.set_key(bytes.fromhex(key), SM4_DECRYPT)decrypted_value = crypt_sm4.crypt_ecb(bytes.fromhex(encrypted_value))return decrypted_value.hex().upper()
📋 实用测试用例
def test_sm4_encryption():key = 'B94D4DC157B96C52994D4DC157B96C52'data = '28EE57035300CD6594C868EA0DBE8E75'# 测试加密encrypted = encrypt_sm4_hex(key, data)print(f"Encrypted: {encrypted}")# 测试解密decrypted = decrypt_sm4_hex(key, encrypted)print(f"Decrypted: {decrypted}")# 验证加解密是否一致assert data == decrypted, "加解密结果不一致!"print("SM4加解密测试通过!")
⚙️ 实际运行输出
Encrypted: 7B88F55214451C45E9C80B62F354ADDF
Decrypted: 28EE57035300CD6594C868EA0DBE8E75
SM4加解密测试通过!
⭐ 关键实践与总结
📌 优化代码的实用技巧
1.函数多实现
- 针对功能性函数,提供不同风格的实现(如普通函数、列表推导式、lambda表达式)。
2. 边界处理: - 针对空数据、全零数据等特殊场景,确保逻辑鲁棒性。
3. 统一日志格式: - 记录详细的输入输出,特别是加解密的中间值。
logger.info(f"Input Key: {key}")
logger.info(f"Input Data: {value}")
logger.info(f"Encrypted Value: {encrypted}")
📌 最佳实践分享
1. 日志驱动调试:
- 在调试过程中记录关键输入、输出和状态变化,有助于快速定位问题。
2. 单元测试覆盖率: - 设计测试用例时覆盖正常、异常和边界场景。
3. 选择主流填充模式: - 如非特殊需求,优先使用 PKCS7 填充。
📝 总结与启发
通过这次 gmssl 填充问题的修复,我深刻体会到:
1. 开源库需谨慎使用: 尤其是小众库,可能存在实现细节问题。
2. 代码设计需注重鲁棒性:边界检查、输入输出验证是关键。
3. 问题解决后需复盘总结:将经验分享出来,不仅能帮助他人,也能提升自己。
希望这篇文章能为你的项目开发提供参考。如果你有类似的经历,欢迎留言交流!让我们在技术道路上共同进步!😊
🔗 互动话题
- 你在使用加密库时踩过哪些坑?如何解决的?
- 你对 SM4 或 gmssl 库有其他疑问或经验吗?
期待你的分享! 🎉
相关文章:

️️️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践20241212
🛡️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践 ✨ 引言 在当下的数据安全环境中,SM4作为中国国家密码算法的代表性选择,被广泛应用于金融、通信和政府领域。然而,在实际开发中,即便是开…...

深度学习实验十四 循环神经网络(1)——测试简单循环网络的记忆能力和梯度爆炸实验
目录 一、数据集构建 1.1数据集的构建函数 1.2加载数据集并划分 1.3 构建Dataset类 二、模型构建 2.1嵌入层 2.2SRN层 2.3模型汇总 三、模型训练 3.1 训练指定长度的数字预测模型 3.2 损失曲线展示 四、模型评价 五、修改 附完整可运行代码 实验大体步骤&#x…...

AWS re:Invent 发布新的数据库产品 Aurora DSQL; NineData SQL编程大赛开始; 腾讯云支持PostgreSQL 17
重要更新 1. AWS re:Invent 发布新的数据库产品 Aurora DSQL ,提供了跨区域、强一致、多区域读写的能力,同时具备99.999%(多区域部署)的可用性,兼容PostgreSQL;同时发布的还有 DynamoDB 也提供类似的跨区域…...

STM32 OLED屏幕驱动详解
一、介绍 OLED是有机发光二极管,又称为有机电激光显示(Organic Electroluminescence Display, OLED)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广…...
Python字符串常用操作
Python字符串常用操作 一、字符串的切片 1.1、通过下标及下标范围取值 my_str myNameIsTaichi value1 my_str[2] # 正向 N value2 my_str[-5] # 反向 从 -1 开始 a字符串分割,语法:string[end: step] start:头下标,以0开…...

Redis 生产问题(重要)
缓存穿透 什么是缓存穿透? 缓存穿透说简单点就是大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力…...

前端 —— Git
Git安装 下载安装包 【免费】前端前置-Git安装包资源-CSDN文库 安装 ‘git‘不是内部或外部命令及Git 的保姆级安装教程(保姆级教程)_git不是内部或外部命令-CSDN博客 vscode添加gitbash终端 setting.json "terminal.integrated.profiles.win…...

【GL006】Linux 之 shell
目录 一、shell 指令 1.1 体验shell指令 1.2 命令格式 1.3 shell中的通配符 1.4 输入输出重定向 1.5 命令置换 1.6 基本系统维护命令 1.7 Linux的进程管理命令 1.8 文件系统相关命令 1.9 Linux网络配置管理 二、shell 编程 2.1 shell 脚本的基础知识 2.2 shell 变…...

JS听到了强运的回响
正则表达式 介绍 正则表达式是用于匹配字符串中字符组合的模式,在JS中,正则表达式也是对象 通常用来查找,替换那些符合正则表达式的文本 就是筛选出符合条件的一类人 比如说 有人喜欢玩艾斯爱慕,那他喜欢的就是这一类人&…...

Linux下MySQL的简单使用
Linux下MySQL的简单使用 导语MySQL安装与配置 MySQL安装密码设置 MySQL管理 命令 myisamchkmysql其他 常见操作 C语言访问MYSQL 连接例程错误处理使用SQL 总结参考文献 导语 这一章是MySQL的使用,一些常用的MySQL语句属于本科阶段内容,然后是C语言和M…...
.net core使用AutoMapper
AutoMapper 是一个用于 .NET 平台的对象映射工具,它简化了不同对象类型之间的转换过程。在软件开发中,尤其是在分层架构的应用程序里,常常需要在不同的对象模型之间进行数据传递,例如从数据库实体到视图模型、DTO(数据…...

nmap详解
Nmap(Network Mapper)是一个开放源代码的网络探测和安全审核的工具。由于它的功能强大,被广泛应用于网络安全领域。以下是Nmap的一些主要功能及其在实战中的应用举例。 Nmap的主要功能: 端口扫描:检测目标主机上开放…...
CentOS7环境安装php
直接安装 yum -y install php CentOS7默认安装是php5,现在php已有8.3版本 先查看php -v 版本 如果是低版本,可以删除 yum remove php yum remove php-fpm yum remove php-common 一、添加REMI存储库 yum install epel-release yum install -y …...

基于深度学习的猫狗识别系统【深度学习课设】
🏆 作者简介:席万里 ⚡ 个人网站:https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜,同时略懂Vue与React前端技术,也了解一点微信小程序开发。 🍻 对计算机充满兴趣,愿意并且希望学习更多的技…...
字体子集化实践探索
最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试 方案一:node.js做子集化 fontmin 缺点是也需要集…...

A1017 基于Java+JSP+SQL Server+servlet的二手购物平台的设计与实现
二手购物平台 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 摘 要 计算机以及网络技术的飞速发展,网络的应用在全国乃至全球日益普及,随着人们的思想水平和生活水平的提高,网络已经是人们必不可少的一部分。人们的…...

Simdroid-EC:液冷仿真新星,助力新能源汽车电机控制器高效散热
近年来,新能源电动车的销量呈现出快速增长的态势。据统计,2024 年1-10月中国新能源汽车销量达728万辆,同比增长37.8%。 电机控制器在新能源汽车中对于保障动力和安全性能扮演着至关重要的角色,其核心部件IGBT(绝缘栅双…...

C语言——实现并求出两个数的最大公约数
问题描述:求出两个数的最大公约数 //求两个数的最大公约数 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h>int main() {int a,b;printf("请您输入两个数 a 和 b\n");scanf…...

今天你学C++了吗?——C++中的类与对象(日期类的实现)——实践与知识的碰撞❤
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...

享元模式的理解和实践
在软件开发中,性能优化是一个永恒的话题。在追求高性能的过程中,减少内存的使用是一项重要的任务。享元模式(Flyweight Pattern)就是一种用于减少内存使用量的设计模式,它特别适用于存在大量重复对象的场景。本文将详细…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...