Compare commits
3 Commits
46f9b1f6d9
...
dc155a9245
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc155a9245 | ||
|
|
60c6c4c3e3 | ||
|
|
358d9876e0 |
@ -1,5 +1,12 @@
|
|||||||
# Changelog: @go/crypto-sm
|
# Changelog: @go/crypto-sm
|
||||||
|
|
||||||
|
## v1.5.4 (2026-06-21)
|
||||||
|
- **JS 对齐**: 重构 JS 导出为具名函数,并引入 `jsmod.MakeError` 动态包装错误以获取调用栈。
|
||||||
|
- **依赖更新**: 升级依赖 `jsmod` 至 `v1.5.3`,`cast` 至 `v1.5.3`,`rand` 至 `v1.5.3`,`encoding` 至 `v1.5.4`,`safe` 至 `v1.5.2`,`crypto` 至 `v1.5.3`。
|
||||||
|
|
||||||
|
## v1.5.3 (2026-06-11)
|
||||||
|
- **版本对齐**: 基础设施全局对齐 v1.5.3。
|
||||||
|
|
||||||
## v1.5.2 (2026-06-08)
|
## v1.5.2 (2026-06-08)
|
||||||
- **JS 对齐 & 重命名**:
|
- **JS 对齐 & 重命名**:
|
||||||
- 注册模块名更正为极简的 `"sm"`。
|
- 注册模块名更正为极简的 `"sm"`。
|
||||||
|
|||||||
5
TEST.md
5
TEST.md
@ -1,14 +1,14 @@
|
|||||||
# Test Report: @go/crypto-sm
|
# Test Report: @go/crypto-sm
|
||||||
|
|
||||||
## 📋 测试概览
|
## 📋 测试概览
|
||||||
- **测试时间**: 2026-05-07
|
- **测试时间**: 2026-06-21
|
||||||
- **测试环境**: darwin/amd64
|
- **测试环境**: darwin/amd64
|
||||||
- **Go 版本**: 1.25.0
|
- **Go 版本**: 1.25.0
|
||||||
|
|
||||||
## ✅ 功能测试 (Functional Tests)
|
## ✅ 功能测试 (Functional Tests)
|
||||||
| 场景 | 状态 | 描述 |
|
| 场景 | 状态 | 描述 |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `TestSM2` | PASS | SM2 签名、验签与加解密测试。 |
|
| `TestSM2` | PASS | SM2 签名、验签 with SM3 与加解密测试。 |
|
||||||
| `TestSM3` | PASS | SM3 哈希确定性验证。 |
|
| `TestSM3` | PASS | SM3 哈希确定性验证。 |
|
||||||
| `TestSM4` | PASS | SM4 CBC/GCM 模式加解密测试。 |
|
| `TestSM4` | PASS | SM4 CBC/GCM 模式加解密测试。 |
|
||||||
| `TestSMPassword` | PASS | 基于密码的 SM4 与 SM2 构造器测试。 |
|
| `TestSMPassword` | PASS | 基于密码的 SM4 与 SM2 构造器测试。 |
|
||||||
@ -17,6 +17,7 @@
|
|||||||
## 🛡️ 鲁棒性防御 (Robustness)
|
## 🛡️ 鲁棒性防御 (Robustness)
|
||||||
- **摩擦消除**:移除 `Must` 冗余 API,完全对齐 `go/crypto` 规范。
|
- **摩擦消除**:移除 `Must` 冗余 API,完全对齐 `go/crypto` 规范。
|
||||||
- **内存安全**:继承 `go/crypto` 的安全缓冲区机制。
|
- **内存安全**:继承 `go/crypto` 的安全缓冲区机制。
|
||||||
|
- **JS 错误调用栈**:JS 桥接层改用具名导出并使用 `jsmod.MakeError` 包裹错误,确保 JS 抛出异常时携带准确的 Go 运行时堆栈。
|
||||||
|
|
||||||
## ⚡ 性能基准 (Benchmarks)
|
## ⚡ 性能基准 (Benchmarks)
|
||||||
*SM 系列算法性能已在常规测试中验证,符合业务预期。*
|
*SM 系列算法性能已在常规测试中验证,符合业务预期。*
|
||||||
|
|||||||
12
go.mod
12
go.mod
@ -3,16 +3,16 @@ module apigo.cc/go/crypto-sm
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/go/cast v1.5.0
|
apigo.cc/go/cast v1.5.3
|
||||||
apigo.cc/go/crypto v1.5.0
|
apigo.cc/go/crypto v1.5.3
|
||||||
apigo.cc/go/encoding v1.5.0
|
apigo.cc/go/encoding v1.5.4
|
||||||
apigo.cc/go/jsmod v1.5.0
|
apigo.cc/go/jsmod v1.5.3
|
||||||
apigo.cc/go/safe v1.5.0
|
apigo.cc/go/safe v1.5.2
|
||||||
github.com/emmansun/gmsm v0.28.0
|
github.com/emmansun/gmsm v0.28.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/go/rand v1.5.0 // indirect
|
apigo.cc/go/rand v1.5.3
|
||||||
golang.org/x/crypto v0.52.0 // indirect
|
golang.org/x/crypto v0.52.0 // indirect
|
||||||
golang.org/x/sys v0.45.0 // indirect
|
golang.org/x/sys v0.45.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
194
js_export.go
194
js_export.go
@ -7,72 +7,144 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
jsmod.Register("sm", map[string]any{
|
jsmod.Register("sm", map[string]any{
|
||||||
// SM3 Hash
|
// SM3 Hash
|
||||||
"SM3": SM3,
|
"SM3": jsSM3,
|
||||||
"SM3ToHex": SM3ToHex,
|
"SM3ToHex": jsSM3ToHex,
|
||||||
"SM3ToBase64": SM3ToBase64,
|
"SM3ToBase64": jsSM3ToBase64,
|
||||||
"SM3ToURLBase64": SM3ToURLBase64,
|
"SM3ToURLBase64": jsSM3ToURLBase64,
|
||||||
|
|
||||||
// SM4 Symmetric (Stateless)
|
// SM4 Symmetric (Stateless)
|
||||||
"SM4EncryptCBC": func(data, key, iv []byte) ([]byte, error) {
|
"SM4EncryptCBC": jsSM4EncryptCBC,
|
||||||
s, err := NewSM4CBCAndEraseKey(key, iv)
|
"SM4DecryptCBC": jsSM4DecryptCBC,
|
||||||
if err != nil {
|
"SM4EncryptGCM": jsSM4EncryptGCM,
|
||||||
return nil, err
|
"SM4DecryptGCM": jsSM4DecryptGCM,
|
||||||
}
|
|
||||||
return s.EncryptBytes(data)
|
|
||||||
},
|
|
||||||
"SM4DecryptCBC": func(data, key, iv []byte) ([]byte, error) {
|
|
||||||
s, err := NewSM4CBCAndEraseKey(key, iv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.DecryptBytes(data)
|
|
||||||
},
|
|
||||||
"SM4EncryptGCM": func(data, key, iv []byte) ([]byte, error) {
|
|
||||||
s, err := NewSM4GCMAndEraseKey(key, iv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.EncryptBytes(data)
|
|
||||||
},
|
|
||||||
"SM4DecryptGCM": func(data, key, iv []byte) ([]byte, error) {
|
|
||||||
s, err := NewSM4GCMAndEraseKey(key, iv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.DecryptBytes(data)
|
|
||||||
},
|
|
||||||
|
|
||||||
// SM2 Asymmetric (Stateless)
|
// SM2 Asymmetric (Stateless)
|
||||||
"SM2Encrypt": func(data, pubKey []byte) ([]byte, error) {
|
"SM2Encrypt": jsSM2Encrypt,
|
||||||
a, err := NewSM2AndEraseKey(nil, pubKey)
|
"SM2Decrypt": jsSM2Decrypt,
|
||||||
if err != nil {
|
"SM2Sign": jsSM2Sign,
|
||||||
return nil, err
|
"SM2Verify": jsSM2Verify,
|
||||||
}
|
|
||||||
return a.EncryptBytes(data)
|
|
||||||
},
|
|
||||||
"SM2Decrypt": func(data, privKey []byte) ([]byte, error) {
|
|
||||||
a, err := NewSM2AndEraseKey(privKey, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return a.DecryptBytes(data)
|
|
||||||
},
|
|
||||||
"SM2Sign": func(data, privKey []byte) ([]byte, error) {
|
|
||||||
a, err := NewSM2AndEraseKey(privKey, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return a.Sign(data)
|
|
||||||
},
|
|
||||||
"SM2Verify": func(data, sig, pubKey []byte) (bool, error) {
|
|
||||||
a, err := NewSM2AndEraseKey(nil, pubKey)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return a.Verify(data, sig)
|
|
||||||
},
|
|
||||||
|
|
||||||
// Key Generation
|
// Key Generation
|
||||||
"GenerateSM2KeyPair": GenerateSM2KeyPair,
|
"GenerateSM2KeyPair": jsGenerateSM2KeyPair,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func jsSM3(data ...[]byte) []byte {
|
||||||
|
return SM3(data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM3ToHex(data []byte) string {
|
||||||
|
return SM3ToHex(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM3ToBase64(data []byte) string {
|
||||||
|
return SM3ToBase64(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM3ToURLBase64(data []byte) string {
|
||||||
|
return SM3ToURLBase64(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM4EncryptCBC(data, key, iv []byte) ([]byte, error) {
|
||||||
|
s, err := NewSM4CBCAndEraseKey(key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := s.EncryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM4DecryptCBC(data, key, iv []byte) ([]byte, error) {
|
||||||
|
s, err := NewSM4CBCAndEraseKey(key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := s.DecryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM4EncryptGCM(data, key, iv []byte) ([]byte, error) {
|
||||||
|
s, err := NewSM4GCMAndEraseKey(key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := s.EncryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM4DecryptGCM(data, key, iv []byte) ([]byte, error) {
|
||||||
|
s, err := NewSM4GCMAndEraseKey(key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := s.DecryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM2Encrypt(data, pubKey []byte) ([]byte, error) {
|
||||||
|
a, err := NewSM2AndEraseKey(nil, pubKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := a.EncryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM2Decrypt(data, privKey []byte) ([]byte, error) {
|
||||||
|
a, err := NewSM2AndEraseKey(privKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := a.DecryptBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM2Sign(data, privKey []byte) ([]byte, error) {
|
||||||
|
a, err := NewSM2AndEraseKey(privKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := a.Sign(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsSM2Verify(data, sig, pubKey []byte) (bool, error) {
|
||||||
|
a, err := NewSM2AndEraseKey(nil, pubKey)
|
||||||
|
if err != nil {
|
||||||
|
return false, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
res, err := a.Verify(data, sig)
|
||||||
|
if err != nil {
|
||||||
|
return false, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsGenerateSM2KeyPair() ([]byte, []byte, error) {
|
||||||
|
priv, pub, err := GenerateSM2KeyPair()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, jsmod.MakeError(err)
|
||||||
|
}
|
||||||
|
return priv, pub, nil
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user