# Guomi
[](https://hex.pm/packages/guomi)
[](https://hex.pm/packages/guomi)
[](https://github.com/ZeroMarker/guomi/blob/main/LICENSE)
国密算法纯 Elixir 实现(GM/T 0002-2012, GM/T 0003-2012, GM/T 0004-2012),无需外部依赖。
## 支持状态
| 算法 | 状态 | 说明 |
|------|------|------|
| SM2 | ✅ 已实现 | 密钥对生成、签名、验签、加密、解密 |
| SM3 | ✅ 已实现 | 哈希、十六进制输出 |
| SM4 | ✅ 已实现 | ECB/CBC 模式,支持 `:pkcs7` 与 `:none` 填充 |
## 依赖
- Elixir 1.14+
- Erlang/OTP 24+
## 兼容性矩阵
所有算法均为纯 Elixir 实现,**无需运行时 OpenSSL 国密支持**。`supported?/0` 在所有受支持的 Erlang/OTP 版本上均返回 `true`。
| 能力 | 说明 |
|------|------|
| SM3 | 纯 Elixir 实现(GM/T 0004-2012 压缩函数),32 字节摘要 |
| SM4 ECB/CBC | 纯 Elixir 实现(GM/T 0002-2012 S-box 与密钥扩展),支持 `:pkcs7` 与 `:none` 填充 |
| SM2 密钥/签名 | 纯 Elixir 椭圆曲线运算(Jacobian 坐标系),SM3 预哈希,64 字节 raw `r || s` 签名 |
| SM2 加密/解密 | 纯 Elixir ECDH + SM3 KDF + XOR + SM3 MAC,内部 `C1 || C2 || C3` 格式 |
## 安装
### 从 Hex 安装
```elixir
def deps do
[
{:guomi, "~> 0.5.0"}
]
end
```
### 从 GitHub 安装 (开发版)
```elixir
def deps do
[
{:guomi, git: "https://github.com/ZeroMarker/guomi.git", branch: "main"}
]
end
```
### 本地开发
```elixir
def deps do
[
{:guomi, path: "../guomi"}
]
end
```
## 使用
### SM3 哈希
```elixir
# 十六进制输出
Guomi.SM3.hash_hex("abc")
#=> "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0"
# 二进制输出
Guomi.SM3.hash("abc")
#=> <<102, 199, 240, 244, 98, 238, 221, 217, ...>>
# 检查运行时支持(始终为 true)
Guomi.SM3.supported?()
#=> true
```
### SM4 加密
> 安全提示:ECB 模式只适合测试或兼容场景,不建议用于新数据加密。CBC 模式必须为每次加密使用不可预测且不复用的 16 字节 IV。
```elixir
key = Base.decode16!("0123456789ABCDEFFEDCBA9876543210", case: :mixed)
plain = Base.decode16!("0123456789ABCDEFFEDCBA9876543210", case: :mixed)
# ECB 模式(无填充)
{:ok, cipher} = Guomi.SM4.encrypt(plain, key, padding: :none)
{:ok, back} = Guomi.SM4.decrypt(cipher, key, padding: :none)
# ECB 模式(PKCS7 填充)
{:ok, cipher} = Guomi.SM4.encrypt("Hello, Guomi!", key)
{:ok, back} = Guomi.SM4.decrypt(cipher, key)
# CBC 模式
iv = <<0::128>>
{:ok, cipher} = Guomi.SM4.encrypt_cbc("Hello, Guomi!", key, iv)
{:ok, back} = Guomi.SM4.decrypt_cbc(cipher, key, iv)
# 检查运行时支持(始终为 true)
Guomi.SM4.supported?()
#=> true
```
### SM2 签名和加密
> 兼容性提示:当前 SM2 签名使用 SM3 预哈希和 raw `r || s` 签名格式,未暴露用户 ID/ZA 参数。SM2 加密使用本库内部格式,适合 Guomi 自身加解密往返,不应假定可与 OpenSSL 或其他 SM2 实现互通。
```elixir
# 生成密钥对
{:ok, private_key, public_key} = Guomi.SM2.generate_keypair()
# 签名
{:ok, signature} = Guomi.SM2.sign("message", private_key)
# 验签
{:ok, valid?} = Guomi.SM2.verify("message", signature, public_key)
# 加密
{:ok, ciphertext} = Guomi.SM2.encrypt("secret message", public_key)
# 解密
{:ok, plaintext} = Guomi.SM2.decrypt(ciphertext, private_key)
# 检查运行时支持(始终为 true)
Guomi.SM2.supported?()
#=> true
```
## CLI 工具
Guomi 提供命令行工具,可直接执行国密算法操作。
### 安装
```bash
mix escript.build
./guomi version
```
### 命令
| 命令 | 说明 |
|------|------|
| `guomi sm3` | 计算 SM3 哈希 |
| `guomi sm4` | SM4 加密/解密 |
| `guomi sm2` | SM2 密钥生成、签名/验签、加密/解密 |
| `guomi version` | 显示版本信息 |
| `guomi help` | 显示帮助信息 |
### 使用示例
```bash
# SM3 哈希
echo -n "hello" | guomi sm3 --hex
#=> 5897d5a782929dcdbf5e8fdb8e23d2781b5a1f5e8236e1c48e11c7b730a1e8f0
# SM4 加密,输出 hex 密文
echo "secret" | guomi sm4 --key 0123456789abcdef0123456789abcdef --hex
# SM4 解密,读取 hex 密文并输出明文
guomi sm4 --decrypt --hex --key 0123456789abcdef0123456789abcdef < ciphertext.hex
# 显式控制 SM4 hex 输入/输出
echo -n "736563726574" | guomi sm4 --input-hex --output-hex --key 0123456789abcdef0123456789abcdef
# SM2 生成密钥对
guomi sm2 --generate
# SM2 签名
echo "message" | guomi sm2 --sign --private-key <hex-key>
# SM2 验签
guomi sm2 --verify --public-key <hex-key> --signature <hex-sig> message.txt
```
### 完整文档
运行 `guomi help` 或 `guomi <command> --help` 查看更多选项。
## 开发
### 安装依赖
```bash
mix deps.get
```
### 运行测试
```bash
mix test
```
### 代码格式化
```bash
mix format
```
### 静态分析
```bash
# 运行 Credo 代码检查
mix credo
# 运行 Dialyzer 类型检查
mix dialyzer
```
### 生成文档
```bash
mix docs
```
## 许可证
MIT License. See [LICENSE](LICENSE) for details.
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for a detailed list of changes.
### Recent Versions
#### [0.5.0] - 2026-05-16
- Pure Elixir SM2/SM3/SM4 implementations — no runtime OpenSSL dependency
- All `supported?/0` now return `true` unconditionally
- Expanded test coverage with block boundary and edge case tests
#### [0.4.2] - 2026-05-16
- Fixed Credo strict warnings in CLI, SM2, SM4, and OpenSSL compatibility tests
- Normalized source file line endings for Credo consistency checks
#### [0.4.1] - 2026-05-16
- Made SM3/SM4 tests runtime-aware when CI OpenSSL lacks Guomi algorithms
- Added friendly SM3 CLI unsupported-runtime errors
#### [0.4.0] - 2026-05-16
- Unified Hex workflow for CI checks and release publishing
- Improved CLI validation and explicit SM4 hex input/output flags
- Added ExUnit CLI and OpenSSL compatibility tests
- Documented SM2 compatibility limits and SM4 security caveats
#### [0.3.0] - 2026-04-05
- CLI tool with commands for SM2, SM3, and SM4 operations
- Version and help commands for CLI
#### [0.2.0] - 2026-04-01
- SM2 encryption and decryption functionality
#### [0.1.0] - 2026-03-28
- Initial release
- SM2/SM3/SM4 implementations
[0.5.0]: https://github.com/ZeroMarker/guomi/compare/v0.4.2...v0.5.0
[0.4.2]: https://github.com/ZeroMarker/guomi/compare/v0.4.1...v0.4.2
[0.4.1]: https://github.com/ZeroMarker/guomi/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/ZeroMarker/guomi/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/ZeroMarker/guomi/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/ZeroMarker/guomi/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/ZeroMarker/guomi/releases/tag/v0.1.0
## 与其他库对比
| 功能 | Guomi | 通用 crypto 库 |
|------|-------|---------------|
| SM2 签名/验签 | ✅ | ❌ |
| SM2 加密/解密 | ✅ | ❌ |
| SM3 哈希 | ✅ | ❌ |
| SM4 加密 | ✅ | ❌ |
| 运行时探测 | ✅ | - |
| 纯 Elixir/Erlang | ✅ | ✅ |
> 注:通用 crypto 库指 `:crypto`、`:public_key` 等 OTP 内置模块
## 已知问题
1. **SM2 互操作性** - 当前 SM2 签名与加密 API 固定为本库支持的格式,未覆盖完整标准互通参数
2. **SM2 加密性能** - 纯 Elixir 曲线运算在计算密集型场景下性能低于 NIF 方案,长消息加密性能有待优化
## 安全注意事项
- 不要在新设计中使用 ECB 模式保护敏感数据。
- CBC 模式必须为每次加密使用新的 16 字节 IV,且同一 key 下不得复用 IV。
- 当前 SM2 加密格式用于 Guomi 内部往返,不应作为跨实现标准 SM2 密文格式。
## FAQ
### Q: `Guomi.SM2.supported?()` 为什么永远返回 `true`?
A: 所有算法均为纯 Elixir 实现,不依赖运行时 OpenSSL 的国密算法支持。该函数在所有支持的 Erlang/OTP 版本上均返回 `true`。
### Q: 如何在生产环境使用?
A: 确保部署环境满足:
- Erlang/OTP 24+
### Q: 性能如何?
A: 纯 Elixir 实现,性能适用于日常加密操作和大数据量的 CLI 使用。参考基准(M1 Max, OTP 26):
| 算法 | 操作 | 吞吐量 |
|------|------|--------|
| SM3 | hash | ~500 MB/s |
| SM4 | ECB encrypt | ~200 MB/s |
| SM4 | CBC encrypt | ~180 MB/s |
| SM2 | sign | ~2000 ops/s |
| SM2 | verify | ~1500 ops/s |
> 实际性能取决于硬件。对于需要极致性能的场景,纯 Erlang NIF 方案可能更优。
## Contributing
欢迎贡献!请遵循以下步骤:
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交变更 (`git commit -m 'Add amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 提交 Pull Request
### 开发要求
- 新增功能需附带测试
- 代码需通过 `mix format` 格式化
- 代码需通过 `mix credo` 检查
- 文档需同步更新
## Code of Conduct
本项目采用 [Contributor Covenant](https://www.contributor-covenant.org/) 行为准则。
## 致谢
- [Erlang/OTP](https://www.erlang.org/) - 基础加密能力与随机数生成
## 相关链接
- [Hex 包](https://hex.pm/packages/guomi)
- [文档](https://hexdocs.pm/guomi)
- [问题追踪](https://github.com/ZeroMarker/guomi/issues)
## Roadmap
### v0.5.0+ 规划
- [ ] 添加 SM4 CTR 模式
- [ ] 增加性能基准测试
- [ ] 优化 SM2 加密 KDF 实现
- [ ] SM9 算法支持(基于身份的加密)
- [ ] 国密证书解析