【JS逆向学习】国家加密系列-SM算法实例

博客介绍了我国国家密码管理局发布的国产加密算法,如 SM1、SM2 等,提及在 JavaScript 中有成熟实现库。还通过具体案例展示逆向分析过程,包括观察网络请求、搜索加密参数、打断点分析加密逻辑等,对请求头加密参数进行了详细分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SM系列

1、国家加密算法介绍

事实上从 2010 年开始,我国国家密码管理局就已经开始陆续发布了一系列国产加密算法,其中SM1、SM4、SM7、祖冲之密码(ZUC)是对称算法;SM2、SM9是非对称算法;SM3是哈希算法。目前,这些算法已广泛应用于各个领域中。其中SM2、SM3、SM4 三种加密算法是比较常见的

2、算法分类
算法名称 算法类别 应用领域 特点
SM1 对称(分组)加密算法 芯片 分组长度、密钥长度均为 128 比特,算法安全保密强度及相关软硬件实现性能与AES相当
SM2 非对称(基于椭圆曲线 ECC)加密算法 数据加密 ECC 椭圆曲线密码机制 256 位,相比 RSA 处理速度快,消耗更少,SM2算法在很多方面都优于RSA算法(RSA发展的早应用普遍,SM2领先也很正常)
SM3 散列(hash)函数算法 完整性校验 安全性及效率与 SHA-256 相当,压缩函数更复杂, 此算法适用于商用密码应用中的数字签名和验证,消息认证的生成与验证以及随机函数的生成,可满足多种密码应用的安全需求。
SM4 对称(分组)加密算法 数据加密和局域网产品 该算法的分组长度为128比特,密钥长度为128比特。加密算法与密钥扩展算法都采用32轮非线性迭代结构
SM7 对称(分组)加密算法 非接触式 IC 卡 分组长度为128比特,密钥长度为128比特
SM9 标识加密算法(IBE) 端对端离线安全通讯 SM9算法不需要申请数字证书,适用于互联网应用的各种新兴应用的安全保障
ZUC 对称(序列)加密算法 移动通信 4G 网络 祖冲之序列密码算法是中国自主研究的流密码算法,是运用于移动通信4G网络中的国际标准密码算法,该算法包括祖冲之算法(ZUC)、加密算法(128-EEA3)和完整性算法(128-EIA3)三个部分。目前已有对ZUC算法的优化实现,有专门针对128-EEA3和128-EIA3的硬件实现与优化
3、算法实现
JavaScript实现

在 JavaScript 中已有比较成熟的实现库,这里推荐 sm-crypto[4],目前支持 SM2、SM3 和 SM4,需要注意的是,SM2 非对称加密的结果由 C1、C2、C3 三部分组成,其中 C1 是生成随机数的计算出的椭圆曲线点,C2 是密文数据,C3 SM3 的摘要值,最开始的国密标准的结果是按 C1C2C3 顺序的,新标准的是按 C1C3C2 顺序存放的,sm-crypto 支持设置 cipherMode,也就是 C1C2C3 的排列顺序。

// cnpm install sm-crypto --save
const sm2 = require('sm-crypto').sm2
// 1: C1C3C2,0: C1C2C3,默认为1
const cipherMode = 1
 
// 生成密钥对
let keypair = sm2.generateKeyPairHex()
let publicKey = keypair.publicKey   // 公钥
let privateKey = keypair.privateKey // 私钥
 
let msgString = "待加密数据"
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode)    // 加密结果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
 
console.log("encryptData: ", encryptData)
console.log("decryptData: ", decryptData)
Python实现

使用之前先安装三方库:pip install gmssl

from gmssl import sm2
 
# 16 进制的公钥和私钥
private_key = '2423c43b9d3a5a8aa41c983ef30231986ea38398b8a36f082057478f0ef23a13'
public_key = '045cfaca8c4fc5af189bbe36f831017daa51dd5116c1118affda2185aaec53a8cbc80762f1b7df97c7ac004194f721cb2862e493945f9dc86a53c06fe00fbd6273'
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
 
# 待加密数据和加密后数据为 bytes 类型
data = b"I love Python"
enc_data = sm2_crypt.encrypt(data)
dec_data = sm2_crypt.decrypt(enc_data)
 
print('enc_data: ', enc_data.hex())
print('dec_data: ', dec_data)

关于算法还原,大家尽量能用javascript实现尽量用javascript,当然这只是个人建议,毕竟不同的程序猿对语言的偏好不同

具体案例

1、逆向目标
  • 目标:某某某
  • 主页:https://fuwu.nhsa.gov.cn/nationalHallSt/#/search/medical?code=90000&flag=false&gbFlag=true
  • 接口:
    https://fuwu.nhsa.gov.cn/ebus/fuwu/api/nthl/api/CommQuery/queryFixedHospital
  • 逆向参数:
    • 头部加密:X-Tif-Nonce、X-Tif-Paasid、X-Tif-Signature、X-Tif-Timestamp、X-Tingyun
    • pyaload:encData、signData
    • response: encData、signData
2、逆向过程

老规矩,直接翻页观察网络请求,然后比对两次的请求结果,哪些参数是加密的显而易见了
在这里插入图片描述

3、逆向分析
3.1 我们先来分析头部参数加密

对这种请求头加密,我们先挑一个比较有特点的加密参数搜索看下,这里我们选择 X-Tif-Signature 进行搜索尝试,发现只有两条结果
在这里插入图片描述
这就好办了,每个地方都打一个断点,然后翻页,发现断点断住了,如下
在这里插入图片描述

function f(t) {
   
   
  var r = n("6c27").sha256
    , s = Math.ceil((new Date).getTime() / 1e3)
    , h = Object(i.a)()
    , f = s + h + s;
  return t.headers["x-tif-paasid"] = l.paasId,
  t.headers["x-tif-signature"] = r(f),
  t.headers["x-tif-timestamp"] = s,
  t.headers["x-tif-nonce"] = h,
  t.headers.Accept = "application/json",
  t.headers.contentType = "application/x-www-form-urlencoded",
  t.data = {
   
   
      data: t.data || {
   
   }
  },
  t.data.appCode = l.appCode,
  t.data.version = l.version,
  t.data.encType = "SM4",
  t.data.signType = "SM2",
  t.data.timestamp = s,
  t.data.signData = function(t) {
   
   
      try {
   
   
          var n = m(t.data)
            , i = p(n);
          i.data = p(i.data);
          var r = v(i)
            , a = o.doSignature(r, d, {
   
   
              hash: !0
          });
          return e.from(a, "hex").toString("base64")
      } catch (e) {
   
   }
  }(t),
  t.data.data = {
   
   
      encData: function(e, t) {
   
   
          switch (e.toUpperCase()) {
   
   
          case "SM2":
              return function(e) {
   
   
                  try {
   
   
                      var t = o.generateKeyPairHex()
                        , n = t.publicKey
                        , i = e;
                      o.doEncrypt(i, n, 1)
                  } catch (e) {
   
   }
              }(t);
          
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗雅颂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值