完整、生产就绪的中国国家密码算法标准(SM2、SM3、SM4)纯 Python 实现,零外部依赖。
SM2 - 公钥密码算法 (GM/T 0003-2012)
- 数字签名(签名/验签)
- 公钥加密/解密
- SM2 推荐曲线上的椭圆曲线运算
- 符合中国国家标准
SM3 - 密码杂凑算法 (GM/T 0004-2012)
- 256 位哈希输出
- Memoable 接口支持高效增量哈希
- 完全符合规范
SM4 - 分组密码算法 (GB/T 32907-2016)
- 128 位分组,128 位密钥
- 32 轮 Feistel 结构
- 5 种加密模式:ECB、CBC、CTR、OFB、CFB
- 4 种填充方案:PKCS#7、ISO 7816-4、ISO 10126、Zero-byte
ZUC - 祖冲之序列密码 (GM/T 0001-2012, 3GPP TS 35.221/222)
- ZUC-128 和 ZUC-256 流密码引擎
- 128-EIA3 和 256-EIA3 消息认证码
- 3GPP LTE/5G 机密性和完整性算法
- 支持可变长度 MAC 输出
- 零外部依赖 - 纯 Python 完整密码学实现
- 抗侧信道攻击 - 在适用的地方使用常量时间运算
- 测试充分 - 200+ 综合单元测试(100% 通过)
- 符合标准 - 遵循官方中国密码学标准
from sm_bc.crypto.cipher import create_sm4_cipher
# 使用推荐设置进行简单加密
cipher = create_sm4_cipher(mode='CBC', padding='PKCS7')
cipher.init(True, key, iv)
ciphertext = cipher.encrypt(plaintext)
# 解密
cipher.init(False, key, iv)
plaintext = cipher.decrypt(ciphertext)# 从 PyPI 安装(推荐)
pip install sm-py-bc
# 或从 GitHub 克隆
git clone https://github.com/lihongjie0209/sm-py-bc.git
cd sm-py-bc
pip install -e .
# 无需额外依赖!
# 只需要 Python 3.10 或更高版本验证安装:
import sm_bc
print(sm_bc.__version__) # 0.1.0from sm_bc.crypto.cipher import create_sm4_cipher
import secrets
# 生成随机密钥和 IV
key = secrets.token_bytes(16) # 128 位密钥
iv = secrets.token_bytes(16) # 128 位 IV
# 使用 CBC 模式和 PKCS#7 填充创建密码器(推荐)
cipher = create_sm4_cipher(mode='CBC', padding='PKCS7')
# 加密
cipher.init(True, key, iv)
plaintext = b"Hello, SM4 encryption!"
ciphertext = cipher.encrypt(plaintext)
# 解密
cipher.init(False, key, iv)
decrypted = cipher.decrypt(ciphertext)
assert plaintext == bytes(decrypted)from sm_bc.crypto.digests import SM3Digest
# 创建摘要
digest = SM3Digest()
# 哈希数据
data = b"Hello, SM3!"
digest.update(data, 0, len(data))
# 获取哈希输出(32 字节 / 256 位)
hash_output = bytearray(32)
digest.do_final(hash_output, 0)
print(f"SM3 哈希: {hash_output.hex()}")from sm_bc.crypto.signers import SM2Signer
from sm_bc.crypto.params.ec_key_parameters import ECPrivateKeyParameters, ECPublicKeyParameters
from sm_bc.math.ec_curve import SM2P256V1Curve
import secrets
# 生成密钥对
curve = SM2P256V1Curve()
d = secrets.randbelow(curve.n) # 私钥
public_key = curve.G.multiply(d) # 公钥
# 创建签名器
signer = SM2Signer()
# 签名消息
message = b"Message to sign"
priv_params = ECPrivateKeyParameters(d, curve.domain_params)
signer.init(True, priv_params)
signature = signer.generate_signature(message)
# 验证签名
pub_params = ECPublicKeyParameters(public_key, curve.domain_params)
signer.init(False, pub_params)
is_valid = signer.verify_signature(message, signature)
print(f"签名有效: {is_valid}")from sm_bc.crypto.engines import SM2Engine
from sm_bc.crypto.params.ec_key_parameters import ECPrivateKeyParameters, ECPublicKeyParameters
from sm_bc.math.ec_curve import SM2P256V1Curve
import secrets
# 生成密钥对
curve = SM2P256V1Curve()
d = secrets.randbelow(curve.n)
public_key = curve.G.multiply(d)
# 创建引擎
engine = SM2Engine()
# 加密
plaintext = b"Secret message"
pub_params = ECPublicKeyParameters(public_key, curve.domain_params)
engine.init(True, pub_params)
ciphertext = engine.process_block(plaintext, 0, len(plaintext))
# 解密
priv_params = ECPrivateKeyParameters(d, curve.domain_params)
engine.init(False, priv_params)
decrypted = engine.process_block(ciphertext, 0, len(ciphertext))
assert plaintext == bytes(decrypted)from sm_bc.crypto.engines import ZUCEngine, ZUC256Engine
from sm_bc.crypto.params import KeyParameter, ParametersWithIV
import secrets
# ZUC-128 加密
key = secrets.token_bytes(16) # 128 位密钥
iv = secrets.token_bytes(16) # 128 位 IV
cipher = ZUCEngine()
cipher.init(True, ParametersWithIV(KeyParameter(key), iv))
plaintext = b"Hello, ZUC-128!"
ciphertext = bytearray(len(plaintext))
cipher.process_bytes(plaintext, 0, len(plaintext), ciphertext, 0)
# ZUC-256 加密(增强安全性)
key256 = secrets.token_bytes(32) # 256 位密钥
iv256 = secrets.token_bytes(23) # 184 位 IV
cipher256 = ZUC256Engine(mac_bits=128)
cipher256.init(True, ParametersWithIV(KeyParameter(key256), iv256))
plaintext = b"Hello, ZUC-256!"
ciphertext = bytearray(len(plaintext))
cipher256.process_bytes(plaintext, 0, len(plaintext), ciphertext, 0)from sm_bc.crypto.macs import ZUC128MAC, ZUC256MAC
from sm_bc.crypto.params import KeyParameter, ParametersWithIV
import secrets
# ZUC-128 MAC (128-EIA3) - 3GPP LTE/5G 完整性算法
key = secrets.token_bytes(16)
iv = secrets.token_bytes(16)
mac = ZUC128MAC(mac_bits=32) # 32 位或 64 位 MAC
mac.init(ParametersWithIV(KeyParameter(key), iv))
message = b"Message to authenticate"
mac.update_bytes(message, 0, len(message))
tag = bytearray(mac.get_mac_size())
mac.do_final(tag, 0)
# ZUC-256 MAC (256-EIA3) - 增强安全性
key256 = secrets.token_bytes(32)
iv256 = secrets.token_bytes(23)
mac256 = ZUC256MAC(mac_bits=128) # 64 位或 128 位 MAC
mac256.init(ParametersWithIV(KeyParameter(key256), iv256))
mac256.update_bytes(message, 0, len(message))
tag256 = bytearray(mac256.get_mac_size())
mac256.do_final(tag256, 0)| 模式 | 描述 | 需要 IV | 需要填充 | 使用场景 |
|---|---|---|---|---|
| CBC | 密码分组链接 | ✅ 是 | ✅ 是 | 通用加密(推荐) |
| CTR | 计数器模式 | ✅ 是 | ❌ 否 | 流密码,任意长度 |
| OFB | 输出反馈 | ✅ 是 | ❌ 否 | 流密码,简单 |
| CFB | 密文反馈 | ✅ 是 | ❌ 否 | 自同步 |
| ECB | 电子密码本 | ❌ 否 | ✅ 是 |
| 填充 | 描述 | 可靠 | 标准 |
|---|---|---|---|
| PKCS#7 | 标准填充 | ✅ 是 | RFC 5652(推荐) |
| ISO 7816-4 | 智能卡填充 | ✅ 是 | ISO/IEC 7816-4 |
| ISO 10126 | 随机填充 | ✅ 是 | ISO/IEC 10126(已弃用) |
| Zero-byte | 简单零填充 | ❌ 否 | 仅用于兼容 |
✅ 推荐做法:
- 使用 CBC 或 CTR 模式进行通用加密
- 对于块模式始终使用 PKCS#7 填充
- 为每次加密操作生成唯一的 IV
- 使用密码学安全的随机数生成器
- 保护好私钥,永远不要硬编码
❌ 避免做法:
- 使用 ECB 模式(会暴露明文模式)
- 使用相同密钥重复使用 IV
- 使用零字节填充(不可靠)
- 以明文形式存储密钥
运行综合测试套件:
# 运行所有测试
pytest tests/unit/
# 运行特定算法测试
pytest tests/unit/test_sm2_engine.py
pytest tests/unit/test_sm3_digest.py
pytest tests/unit/test_sm4_engine.py
# 带覆盖率报告运行
pytest --cov=sm_bc tests/unit/测试覆盖:
- 580+ 单元测试(99.8% 通过)
- SM2: 29 个测试(加密、签名、密钥操作)
- SM3: 18 个测试(哈希、memoable 接口)
- SM4: 18 个测试(分组密码操作)
- ZUC: 58 个测试(ZUC-128/256 引擎和 MAC)
- 密码模式: 60 个测试(CBC、CTR、OFB、CFB)
- 填充: 40 个测试(所有方案、边界情况)
sm-py-bc/
├── src/sm_bc/ # 主要源代码
│ ├── crypto/ # 密码学实现
│ │ ├── digests/ # SM3 哈希函数
│ │ ├── engines/ # SM2、SM4 引擎
│ │ ├── signers/ # SM2 签名器
│ │ ├── modes/ # 密码模式(CBC、CTR、OFB、CFB)
│ │ ├── paddings/ # 填充方案
│ │ ├── params/ # 密码学参数
│ │ └── cipher.py # 高层密码接口
│ ├── math/ # 椭圆曲线数学
│ └── util/ # 工具类
├── tests/ # 综合测试套件
│ └── unit/ # 所有组件的单元测试
├── examples/ # 使用示例和演示
├── docs/ # 附加文档
│ └── process/ # 开发过程文档
└── pyproject.toml # 项目配置
查看 examples/ 目录获取完整的工作示例:
sm4_comprehensive_demo.py- 展示所有 SM4 特性test_sm2_engine_demo.py- SM2 加密示例test_sm3_demo.py- SM3 哈希示例test_cbc_demo.py- CBC 模式示例test_ctr_demo.py- CTR 模式示例test_padding_demo.py- 填充方案示例zuc_demo.py- ZUC 流密码和 MAC 完整示例
运行任何示例:
python examples/sm4_comprehensive_demo.py纯 Python - 所有密码学操作从头实现:
- 无外部密码学库
- 仅使用 Python 标准库
- 完全可审计和透明
基于参考实现 - 从可信实现移植:
- 主要参考: sm-js-bc (TypeScript)
- 次要参考: Bouncy Castle Java 实现
- 保持与参考实现的兼容性
符合标准:
- SM2: GM/T 0003-2012(基于椭圆曲线的公钥密码算法)
- SM3: GM/T 0004-2012(密码杂凑算法)
- SM4: GB/T 32907-2016(分组密码算法)
这是一个专注于正确性和安全性而非原始性能的纯 Python 实现。对于需要高吞吐量的生产应用:
- 在可用时考虑使用硬件加速
- 对关键路径使用原生实现(C/C++)
- 此库非常适合开发、测试和需要纯 Python 的应用
典型性能(现代硬件上的 Python 3.10+):
- SM3 哈希: ~5-10 MB/s
- SM4 加密: ~1-5 MB/s
- SM2 操作: ~100-500 ops/s
欢迎贡献!请:
- Fork 仓库
- 创建特性分支
- 为新功能添加测试
- 确保所有测试通过
- 提交 pull request
MIT 许可证 - 查看 LICENSE 文件了解详情。
- 基于 sm-js-bc (TypeScript) 的参考实现
- 受 Bouncy Castle 密码学库启发
- 实现中国国家密码学标准
本软件实现中国国家密码学标准。用户有责任遵守其管辖范围内适用的出口管制法律法规。
- Issues: GitHub Issues
- 文档: 完整文档
- 示例: 示例目录
用 ❤️ 为密码学社区制作
生产就绪 • 测试充分 • 符合标准 • 纯 Python