当前位置: 首页 > news >正文

HTTPS接口国密安全设计-示例

HTTPS接口国密安全设计

一、需求

1、总体安全需求

接口需要使用国密算法进行安全传输、防重放、防篡改和防伪造,敏感字段加密。
敏感字段是idCard和amount。

2、场景设定

客户端调用服务端接口

  • 客户端(App 或前端)向服务端(API 接口)发送请求。
  • 请求包含敏感参数(如用户身份证号、金额等),需加密。
  • 接口需防重放、防篡改、防伪造。

3、原始接口参数

{"userId": "1001","idCard": "110101199001011234","amount": "5000.00","timestamp": "1731123456789","nonce": "abc123xyz"
}

二、设计与实现步骤

简单来说客户端实现

  • 将需要加密的字段通过sm4加密,然后进行base64编码

  • 将报文通过sm3进行报文摘要计算

  • 将报文摘要进行签名,然后进行base64编码

  • 将base64编码后的字符串(可选的公钥)作为参数

  • 完成请求参数构造

实现简单代码示例如下。

// 原始报文
{"userId": "1001","idCard": "110101199001011234","amount": "5000.00","timestamp": "1731123456789","nonce": "abc123xyz"
}
// 需要加密的字段
"encryptedData": {"idCard": "110101199001011234","amount": "5000.00"
}// 1、将需要加密的字段通过sm4加密,然后进行base64编码
// cipherBytes 是二进制数据,不能直接放在 JSON 中传输
byte[] cipherBytes = SM4_CBC_Encrypt(encryptedData, key, iv);
// 经过Base64编码后的密文
String cipherText = Base64.encode(cipherBytes);// 2、将报文通过sm3进行报文摘要计算
// 待签名的字符串,一般需要按照需要设定
待签名字符串=“userId=1001&timestamp=1731123456789&nonce=abc123xyz&cipherText=Base64编码的SM4密文...”
digest = SM3(待签名字符串)// 3、将报文摘要进行签名,然后进行base64编码byte[] derSignature = SM2_Sign(client_private_key, digest); // 已经是 DER 编码String signature = Base64.encode(derSignature);        // 用于 JSON 传输// 4、最终构造的请求体{"userId": "1001","cipherText": "Base64编码的SM4密文",// 来自于第一步"timestamp": 1731123456789,"nonce": "abc123xyz","signature": "Base64编码的SM2签名", // 来自于第三步"publicKey": "客户端SM2公钥(首次调用时提供,可缓存)" // 一般是约定共享方式或作为参数传递
}

服务端实现

  • 将报文通过sm3进行摘要计算

  • 将公钥、报文摘要和客户端的签名进行sm2验证签名

  • 签名验证通过进行加密字段sm4解密

  • 正常业务处理

实现简单代码示例如下。

// 原始报文{"userId": "1001","cipherText": "Base64编码的SM4密文",// 来自于第一步"timestamp": 1731123456789,"nonce": "abc123xyz","signature": "Base64编码的SM2签名", // 来自于第三步"publicKey": "客户端SM2公钥(首次调用时提供,可缓存)" // 一般是约定共享方式或作为参数传递
}// 0、在进行报文sm3摘要计算之前可能会做些基础性的校验,比如防重放等// 1、将报文通过sm3进行摘要计算
待签名字符串=“userId=1001&timestamp=1731123456789&nonce=abc123xyz&cipherText=Base64编码的SM4密文...”
digest_server = SM3(待签名字符串) // 2、将公钥、报文摘要和客户端的签名进行sm2验证签名
isValid = SM2_Verify(publicKey, digest_server, signature)    // 3、验证通过则进行sm4解密
// 通过共享的sm4密钥进行解密并结构化得到    
"encryptedData": {"idCard": "110101199001011234","amount": "5000.00"
}// 4、正常的业务逻辑处理
...

1、总体目标

  • 传输安全:使用国密 HTTPS(即基于 SM2/SM3/SM4 的 TLS 协议)
  • 接口参数加密:在应用层对敏感参数进行国密加密(使用 SM4)
  • 身份认证与防篡改:使用 SM2 数字签名 + SM3 摘要验证请求合法性
  • 符合国家密码管理局要求:满足等保、密评等合规需求

2、实现步骤

1)、建立国密 HTTPS 通道(传输层安全)
  • 使用算法
    SM2:用于服务器证书和密钥交换
    SM3:用于消息摘要和证书指纹
    SM4:用于加密会话数据(替代 AES)

  • 实现方式
    服务端申请国密数字证书(含 SM2 公钥)
    客户端使用支持国密的浏览器或 SDK(如 CFCA 国密浏览器、GmSSL 库)

  • 握手过程
    服务器发送 SM2 证书
    双方通过 SM2 密钥协商(ECDH)生成会话密钥
    使用 SM4 加密后续通信数据
    使用 SM3 计算握手消息完整性

结果:传输通道已加密,防止中间人窃听。

2)、客户端准备请求(应用层加密与签名)

在 HTTPS 基础上,对接口参数进行额外加密和签名,增强安全性。

  • 请求参数(原始)
{"userId": "1001","idCard": "110101199001011234","amount": "5000.00","timestamp": "1731123456789","nonce": "abc123xyz"
}
  • 使用算法
    SM4:加密敏感字段(如 idCard、amount)
    SM3:计算待签名数据的摘要
    SM2:对摘要进行签名,生成数字签名
  • 实现步骤

(1)选择需加密的敏感字段

"encryptedData": {"idCard": "110101199001011234","amount": "5000.00"
}

(2)使用 SM4 加密敏感数据(CBC 模式 + 随机 IV)
客户端和服务端预先协商或通过安全通道分发一个 SM4 会话密钥(可用于一次请求或多请求),使用 SM4-CBC 加密 encryptedData,得到密文(Base64 编码)。

"cipherText": "Base64编码的SM4密文"

实现过程如下。

先通过SM4-CBC加密算法得到二进制密文,然后进行Base64编码得到经过Base64编码的密文。

原始数据(JSON对象) → 转为字节数组 → SM4-CBC加密 → 二进制密文(byte[]) → Base64编码 → Base64字符串(可传输)

java实现示例

// cipherBytes 是二进制数据,不能直接放在 JSON 中传输
byte[] cipherBytes = SM4_CBC_Encrypt(encryptedData, key, iv);
// 经过Base64编码后的密文
String cipherText = Base64.encode(cipherBytes);

(3)构造待签名字符串(拼接关键字段)

待签名字符串示例如下。

userId=1001&timestamp=1731123456789&nonce=abc123xyz&cipherText=Base64编码的SM4密文...

(4)使用 SM3 计算摘要

digest = SM3(待签名字符串)

(5)使用客户端 SM2 私钥签名

// 示例(伪代码)
byte[] derSignature = SM2_Sign(client_private_key, digest); // 已经是 DER 编码
String signature = Base64.encode(derSignature);        // 用于 JSON 传输

使用成熟的国密库(如 Bouncy Castle + 国密补丁、Hutool、GmSSL、SM-CRYPTO)时,签名方法通常会自动返回 DER 编码后的字节数组,只需再做一次 Base64 编码即可用于传输。

(6)构造最终请求体

{"userId": "1001","cipherText": "Base64编码的SM4密文","timestamp": 1731123456789,"nonce": "abc123xyz","signature": "Base64编码的SM2签名","publicKey": "客户端SM2公钥(首次调用时提供,可缓存)"
}
3)、服务端验证与解密

服务端收到请求后,执行以下验证流程:

(1)基础校验

  • 检查 timestamp 是否过期(防重放攻击,如超过5分钟拒绝)
  • 检查 nonce 是否已使用(防重放)
  • 校验 userId 合法性

(2)获取客户端公钥

  • 若是首次调用,保存 publicKey
  • 否则从数据库或缓存中取出该用户的 SM2 公钥
  • 或者另行约定的方式

(3)重构待签名字符串(同客户端规则)

根据约定的签名字段、算法等要素进行构建待签名的字符串。

userId=1001&timestamp=...&nonce=...&cipherText=...

(4)使用 SM3 计算摘要

digest_server = SM3(重构字符串)

(5)使用客户端公钥验证 SM2 签名

isValid = SM2_Verify(client_public_key, digest_server, signature)
  • 若验证失败 → 拒绝请求(可能被篡改或伪造)

(6)使用 SM4 解密数据

  • 使用预共享的 SM4 密钥解密 cipherText
  • 得到原始敏感数据(如 idCard, amount

(7)处理业务逻辑

  • 使用解密后的数据完成业务操作

(8)返回响应(可选加密)

  • 响应也可使用 SM4 加密,并附 SM2 签名,确保下行安全

三、SM2、SM3、SM4 使用环节总结

环节使用算法用途
1. 传输层安全SM2 + SM3 + SM4国密 HTTPS,保障通信通道安全
2. 敏感参数加密SM4对身份证、金额等字段加密
3. 数据完整性校验SM3计算请求参数摘要,防篡改
4. 身份认证与抗抵赖SM2客户端私钥签名,服务端公钥验签
5. 密钥协商SM2(ECDH)在 HTTPS 握手中协商会话密钥
6. 证书体系SM2 + SM3国密数字证书,SM3 用于证书指纹

四、关键技术点与建议

  1. SM4 密钥管理
    • 可通过国密 HSM(硬件安全模块)生成和存储
    • 支持定期轮换,提高安全性
  2. SM2 密钥对
    • 客户端需持有自己的 SM2 密钥对(可存储在 U盾、TEE 或安全容器中)
    • 服务端需维护客户端公钥白名单
  3. 时间戳与随机数(nonce)
    • 必须使用,防止重放攻击
  4. 开发库推荐
    • Java:Bouncy Castle + 国密补丁、Hutool、Lang-Crypto
    • 前端:sm-crypto(JavaScript 国密库)
  5. 合规要求
    • 通过国家密码管理局的商用密码应用安全性评估(密评)
    • 使用经认证的密码产品(如国密 U盾、HSM)

五、总结

要实现一个国密合规的 HTTPS 接口调用系统,应采用“双层防护”策略:

第一层:国密 HTTPS
使用 SM2/SM3/SM4 构建安全传输通道,防止窃听。

第二层:应用层加密 + 签名
使用 SM4 加密敏感参数,SM3 + SM2 实现防篡改和身份认证。

这样既能满足高安全性要求,又能通过国家合规审查,适用于金融、政务、医疗等高敏感场景。

不能直接对原始消息进行签名,而是先对消息计算 SM3 摘要,再对摘要值进行签名。

原因1:性能效率(Efficiency)

  • 问题:如果直接对一个大文件(比如几MB的网页内容)进行 SM2 签名,计算量极大,速度慢。
  • 解决:使用 SM3 将任意长度的数据压缩成 固定 256 位(32 字节) 的摘要,SM2 只需对这 32 字节签名,极大提升效率。

原因2:安全性(Security)

(1)防止“长度扩展攻击”等潜在风险

  • 直接对原始数据签名可能暴露结构信息,增加被攻击的风险。
  • 使用哈希函数(SM3)作为“中介”,可以隔离原始数据与签名过程,增强安全性。

(2)SM2 算法设计要求输入为固定长度

  • SM2 基于椭圆曲线数学运算,其签名算法要求输入是一个固定长度的整数(通常是哈希值)。
  • 如果直接输入可变长度的原始消息,会导致算法不稳定或不安全。

国密标准 GM/T 0009-2012《SM2密码算法使用规范》明确规定

“在使用 SM2 进行数字签名时,应先使用 SM3 杂凑算法对消息进行摘要处理,然后对摘要值进行签名。”

原因3:完整性验证的标准化流程

在 HTTPS 握手过程中,数字证书和握手消息的签名验证流程如下:

发送方(服务器):
1. 计算握手消息的摘要:digest = SM3(handshake_messages)
2. 使用私钥对摘要签名:signature = SM2_Sign(private_key, digest)
3. 发送签名值和原始消息接收方(浏览器):
1. 接收到消息后,重新计算摘要:digest' = SM3(received_messages)
2. 使用服务器公钥验证签名:SM2_Verify(public_key, digest', signature)
3. 如果验证通过 → 说明消息未被篡改,且来源可信

这个流程中,SM3 保证了数据完整性,SM2 保证了身份认证和不可否认性,二者缺一不可。

下一篇介绍如何简单实现防重放

http://www.dtcms.com/a/552919.html

相关文章:

  • 通过nginx+openssl自签名证书部署https应用并解决不安全问题
  • AI提示词:别再把提示词当 “聊天”—— 它是人机协作的 “接口定义”
  • Rust开发之使用panic!处理不可恢复错误
  • 买业务送网站浙江省住房和城乡建设厅网站查询
  • 网站托管服务 优帮云网站专题页面用什么做
  • Redisson 的分布式锁机制幽默笑话理解
  • Qt-HTTPWebSocket
  • MATLABcode|2个雷达二维目标跟踪滤波系统 - EKF实现,匀速运动模型,输入:雷达观测数据(距离、方位角),输出:目标状态估计(位置、速度)
  • TDengine 数据函数 CORR 用户手册
  • Java的驼峰转换实现方案
  • 从零开始的C++学习生活 19:C++复习课(5.4w字全解析)
  • 阿里云-云服务器的创建与使用
  • 安防监控系统:安防之眼,智守未来
  • 网站建设吸引人的话语广元北京网站建设
  • 网站上线前营销推广工作准备网站创建费用
  • Apache Tomcat RewriteValve目录遍历漏洞 | CVE-2025-55752 复现
  • k8s:service资源详解
  • 大型系统性能优化问题
  • 国际版多语言语聊语音厅交友源码开发:技术特性、中外差异与核心注意事项
  • 面对网络蠕虫的紧急处理方式和防护措施
  • 深入掌握 Maven Settings:从配置到实战
  • 厦门做网站seo的惠州哪家做网站比较好
  • 目标检测原理分享
  • AI驱动的VSCode插件开发:从模型研发到性能优化的全栈实践
  • 6 种无误的方法:如何备份和恢复华为手机
  • Spring Boot 整合 ShedLock 处理定时任务重复
  • 静态网站开发课程相关新闻做设计图的网站
  • MCU(微控制器单元)上的语音识别
  • 【普中Hi3861开发攻略--基于鸿蒙OS】-- 第 31 章 WIFI 实验-华为 IoTDA 设备接入
  • hive的全连接