fiber不内置sm2/sm3/sm4算法,无encrypt/decrypt方法;国密需显式引入合规库(如gmsm),且必须在业务层按字段手动加密,禁用ecb,cbc需动态iv并base64编码,签名与加密须分离使用。

直接用 Fiber 默认的中间件或内置工具做国密加密不可行——Fiber 本身不内置 SM2/SM3/SM4 算法,所有国密操作必须显式引入合规密码库并手动集成。
为什么不能直接调用 ctx.Encrypt() 或类似方法
Fiber 没有 Encrypt、Decrypt 这类加密方法;它的 ctx.SendString()、ctx.JSON() 等只负责响应输出,不处理加解密逻辑。试图在中间件里“自动加密响应体”会破坏 JSON 结构、导致前端解析失败,且无法区分哪些字段需加密(如仅加密 idCard 而非整个 user 对象)。
- 国密算法(SM2/SM3/SM4)不在 Go 标准库中,必须依赖第三方实现,如
github.com/tjfoc/gmsm或github.com/liyue201/gm - SM2 是非对称算法,适合密钥交换或签名,不适合直接加密敏感字段;SM4 才是国密标准的对称分组加密算法,对应 AES 的使用场景
- SM3 是哈希算法,用于摘要或 HMAC,不能逆向还原,不适用于“加密后传输再解密”的流程
如何在 Handler 中安全嵌入 SM4 加密逻辑
推荐在业务逻辑层(而非中间件)对明确标记为敏感的字段做按需加密,避免全局污染和误加密。例如用户注册返回中仅对 idCard 和 phone 字段加密:
- 使用
gmsm/sm4时,密钥必须为 16 字节(SM4-ECB)或 16/24/32 字节(SM4-CBC),且需自行管理 IV(CBC 模式下不可复用) - 不要硬编码密钥,从环境变量或 KMS 获取,例如
os.Getenv("SM4_KEY") - ECB 模式不安全,禁用;务必用 CBC 或 CFB,并确保每次加密生成新 IV,将 IV 与密文拼接(如
base64(IV + ciphertext)) - Go 中
gmsm/sm4的Encrypt方法返回的是原始字节,需转base64后再塞入 JSON,否则会破坏 UTF-8 编码
示例片段:
key := []byte(os.Getenv("SM4_KEY"))
iv := make([]byte, sm4.BlockSize)
rand.Read(iv)
block, _ := sm4.NewCipher(key)
mode := cipher.NewCBCEncrypter(block, iv)
plaintext := pad([]byte(phone), sm4.BlockSize)
ciphertext := make([]byte, len(plaintext))
mode.Crypt(ciphertext, plaintext)
result := base64.StdEncoding.EncodeToString(append(iv, ciphertext...))
SM2 签名与验签应绑定业务动作,而非响应加密
SM2 不该用来加密 HTTP 响应体,而应在关键操作(如支付确认、电子合同签署)中对请求参数做签名,由服务端验签保障来源可信。Fiber 中可封装为独立校验函数:
- 客户端用 SM2 私钥对
timestamp+nonce+bodyHash签名,传入X-SM2-Signature请求头 - 服务端用预置公钥调用
sm2.Verify()验证,失败则ctx.Status(401).SendString("invalid signature") - 注意:SM2 签名结果是 ASN.1 编码的 R+S 拼接,Go 库默认输出 DER 格式,需统一约定 Base64 编码传输
- 不要在签名中包含明文敏感数据,签名只保证完整性与身份,敏感数据仍走 SM4 加密通道
国密合规落地中最容易被忽略的三个点
很多团队卡在“能跑通”但不合规,问题常出在细节:
- 未使用国家密码管理局认证的算法实现——
gmsm是社区版,虽功能完整,但金融/政务项目需采购通过 GM/T 0002-2012 认证的商用 SDK(如江南天安、三未信安的 Go 封装) - SM4 密钥未定期轮换,且未与 HSM 或国密 KMS 对接,密钥以明文形式存在于内存或配置文件中
- 前端解密时未校验 SM4 解密后的 PKCS#7 填充有效性,导致错误解密不报错,掩盖密钥错配或篡改问题











