Skip to content

lihongjie0209/sm-py-bc

Repository files navigation

SM-PY-BC: 纯 Python 国密算法库

完整、生产就绪的中国国家密码算法标准(SM2、SM3、SM4)纯 Python 实现,零外部依赖。

CI PyPI Python 3.10+ License: MIT Tests: 200+ Passing


🎯 特性

✅ 完整的国密算法套件

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% 通过)
  • 符合标准 - 遵循官方中国密码学标准

🚀 易用的高层 API

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.0

🔧 快速开始

SM4 对称加密

from 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)

SM3 密码杂凑

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()}")

SM2 数字签名

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}")

SM2 加密/解密

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)

ZUC 流密码加密

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)

ZUC MAC 消息认证

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

🤝 贡献

欢迎贡献!请:

  1. Fork 仓库
  2. 创建特性分支
  3. 为新功能添加测试
  4. 确保所有测试通过
  5. 提交 pull request

📄 许可证

MIT 许可证 - 查看 LICENSE 文件了解详情。


🙏 致谢

  • 基于 sm-js-bc (TypeScript) 的参考实现
  • 受 Bouncy Castle 密码学库启发
  • 实现中国国家密码学标准

⚖️ 法律声明

本软件实现中国国家密码学标准。用户有责任遵守其管辖范围内适用的出口管制法律法规。


📞 支持


用 ❤️ 为密码学社区制作

生产就绪 • 测试充分 • 符合标准 • 纯 Python

About

SM2/SM3/SM4 implementation in Python based on Bouncy Castle - Pure Python cryptography library

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages