乐趣区

关于python:爬虫逆向基础认识-SM1SM9ZUC-国密算法

关注微信公众号:K 哥爬虫,QQ 交换群:808574309,继续分享爬虫进阶、JS/ 安卓逆向等技术干货!

【01×00】简介

国密即国家明码局认定的国产加密算法,爬虫工程师在做 JS 逆向的时候,会遇到各种各样的加密算法,其中 RSA、AES、SHA 等算法是最常见的,这些算法都是国外的,在 K 哥以前的文章里也有介绍:《【爬虫常识】爬虫常见加密解密算法》

事实上从 2010 年开始,我国国家明码管理局就曾经开始陆续公布了一系列国产加密算法,这其中就包含 SM1、SM2、SM3、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业明码,是指用于商业的、不波及国家机密的明码技术。SM1 和 SM7 的算法不公开 ,其余算法都已成为 ISO/IEC 国际标准。

在这些国产加密算法中,SM2、SM3、SM4 三种加密算法是比拟常见的 ,在爬取局部 gov 网站时,也可能会遇到这些算法,所以作为爬虫工程师是有必要理解一下这些算法的,如下图所示某 gov 网站就应用了 SM2 和 SM4 加密算法:

【02×00】算法概述

算法名称 算法类别 应用领域 特点
SM1 对称(分组)加密算法 芯片 分组长度、密钥长度均为 128 比特
SM2 非对称(基于椭圆曲线 ECC)加密算法 数据加密 ECC 椭圆曲线明码机制 256 位,相比 RSA 处理速度快,耗费更少
SM3 散列(hash)函数算法 完整性校验 安全性及效率与 SHA-256 相当,压缩函数更简单
SM4 对称(分组)加密算法 数据加密和局域网产品 分组长度、密钥长度均为 128 比特,计算轮数多
SM7 对称(分组)加密算法 非接触式 IC 卡 分组长度、密钥长度均为 128 比特
SM9 标识加密算法(IBE) 端对端离线平安通信 加密强度等同于 3072 位密钥的 RSA 加密算法
ZUC 对称(序列)加密算法 挪动通信 4G 网络 流明码

【03×00】算法详解

【03×01】SM1 分组加密算法

SM1 为分组加密算法,对称加密,分组长度和密钥长度都为 128 位,故对音讯进行加解密时,若音讯长度过长,须要进行分组,要音讯长度有余,则要进行填充。算法平安窃密强度及相干软硬件实现性能与 AES 相当,该算法不公开,仅以 IP 核的模式存在于芯片中,调用该算法时,须要通过加密芯片的接口进行调用,采纳该算法曾经研制了系列芯片、智能 IC 卡、智能明码钥匙、加密卡、加密机等平安产品,广泛应用于电子政务、电子商务及国民经济的各个应用领域(包含国家政务通、警务通等重要畛域),个别理解的人比拟少,爬虫工程师也不会遇到这种加密算法。

【03×02】SM2 椭圆曲线公钥加密算法

SM2 为椭圆曲线(ECC)公钥加密算法,非对称加密,SM2 算法和 RSA 算法都是公钥加密算法,SM2 算法是一种更先进平安的算法,在咱们国家商用明码体系中被用来替换 RSA 算法,在不少 gov 网站会见到此类加密算法。我国学者对椭圆曲线明码的钻研从 20 世纪 80 年代开始,目前已获得不少成绩,SM2 椭圆曲线公钥明码算法比 RSA 算法有以下劣势:

SM2 RSA
安全性 256 位 SM2 强度已超过 RSA-2048 个别
算法构造 根本椭圆曲线(ECC) 基于非凡的可逆模幂运算
计算复杂度 齐全指数级 亚指数级
存储空间(密钥长度) 192-256 bit 2048-4096 bit
秘钥生成速度 较 RSA 算法快百倍以上
解密加密速度 较快 个别

【03×03】SM3 杂凑算法

SM3 为明码杂凑算法,采纳明码散列(hash)函数规范,用于代替 MD5/SHA-1/SHA-2 等国内算法,是在 SHA-256 根底上改良实现的一种算法,音讯分组长度为 512 位,摘要值长度为 256 位,其中应用了异或、模、模加、移位、与、或、非运算,由填充、迭代过程、音讯扩大和压缩函数所形成。在商用明码体系中,SM3 次要用于数字签名及验证、音讯认证码生成及验证、随机数生成等。据国家明码管理局示意,其安全性及效率要高于 MD5 算法和 SHA-1 算法,与 SHA-256 相当。

【03×04】SM4 分组加密算法

SM4 为无线局域网规范的分组加密算法,对称加密,用于代替 DES/AES 等国内算法,SM4 算法与 AES 算法具备雷同的密钥长度和分组长度,均为 128 位,故对音讯进行加解密时,若音讯长度过长,须要进行分组,要音讯长度有余,则要进行填充。加密算法与密钥扩大算法都采纳 32 轮非线性迭代构造,解密算法与加密算法的构造雷同,只是轮密钥的应用程序相同,解密轮密钥是加密轮密钥的逆序。

SM4 DES AES
计算轮数 32 16(3DES 为 16*3) 10/12/14
明码部件 S 盒、非线性变换、线性变换、合成变换 规范算术和逻辑运算、先替换后置换,不含线性变换 S 盒、行移位变换、列混合变换、圈密钥加变换(AddRoundKey)

【03×05】SM7 分组加密算法

SM7 为分组加密算法,对称加密,该算法不公开,利用包含身份辨认类利用(非接触式 IC 卡、门禁卡、工作证、参赛证等),票务类利用(大型赛事门票、展会门票等),领取与通卡类利用(积分生产卡、校园一卡通、企业一卡通等)。爬虫工程师基本上不会遇到此类算法。

【03×06】SM9 标识加密算法

SM9 为标识加密算法(Identity-Based Cryptography),非对称加密,标识加密将用户的标识(如微信号、邮件地址、手机号码、QQ 号等)作为公钥,省略了替换数字证书和公钥过程,使得平安零碎变得易于部署和治理,实用于互联网利用的各种新兴利用的平安保障,如基于云技术的明码服务、电子邮件平安、智能终端爱护、物联网平安、云存储平安等等。这些平安利用可采纳手机号码或邮件地址作为公钥,实现数据加密、身份认证、通话加密、通道加密等。在商用明码体系中,SM9 次要用于用户的身份认证,据新华网公开报道,SM9 的加密强度等同于 3072 位密钥的 RSA 加密算法。

【03×07】ZUC 祖冲之算法

ZUC 为流明码算法,对称加密,该机密性算法可实用于 3GPP LTE 通信中的加密和解密,该算法包含祖冲之算法(ZUC)、机密性算法(128-EEA3)和完整性算法(128-EIA3)三个局部。曾经被国内组织 3GPP 举荐为 4G 无线通信的第三套国内加密和完整性规范的候选算法。

【04×00】编程语言实现

【04×01】Python 语言实现

在 Python 外面并没有比拟官网的库来实现国密算法,这里仅列出了其中两个较为欠缺的第三方库,须要留神的是,SM1 和 SM7 算法不公开,目前大多库仅实现了 SM2、SM3、SM4 三种密算法。

  • snowland-smx-python:https://gitee.com/snowlandltd…
  • gmssl:https://github.com/duanhongyi…
  • gmssl-python:https://github.com/gongxian-d…

其中 gmssl-python 是 gmssl 的改进版,gmssl-python 新增反对了 SM9 算法,不过截止本文编写时,gmssl-python 并未公布 pypi,也未 PR 到 gmssl,应用 pip install gmssl 装置的 gmssl 不反对 SM9 算法。若要应用 SM9 算法,可下载 gmssl-python 源码手动装置。

以 gmssl 的 SM2 算法为例,实现如下(其余算法和具体用法可参考其官网文档):

SM2 加密(encrypt)和解密(decrypt):

from gmssl import sm2


# 16 进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)

# 待加密数据和加密后数据为 bytes 类型
data = b"this is the data to be encrypted"
enc_data = sm2_crypt.encrypt(data)
dec_data = sm2_crypt.decrypt(enc_data)

print('enc_data:', enc_data.hex())
print('dec_data:', dec_data)

# enc_data:  3cb96dd2e0b6c24df8e22a5da3951d061a6ee6ce99f46a446426feca83e501073288b1553ca8d91fad79054e26696a27c982492466dafb5ed06a573fb09947f2aed8dfae243b095ab88115c584bb6f0814efe2f338a00de42b244c99698e81c7913c1d82b7609557677a36681dd10b646229350ad0261b51ca5ed6030d660947

# dec_data:  b'this is the data to be encrypted'

SM2 签名(sign)和校验(verify):

from gmssl import sm2, func


# 16 进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)

# 待签名数据为 bytes 类型
data = b"this is the data to be signed"
random_hex_str = func.random_hex(sm2_crypt.para_len)

#  16 进制
sign = sm2_crypt.sign(data, random_hex_str)
verify = sm2_crypt.verify(sign, data)

print('sign:', sign)
print('verify:', verify)

# sign:  45cfe5306b1a87cf5d0034ef6712babdd1d98547e75bcf89a17f3bcb617150a3f111ab05597601bab8c41e2b980754b74ebe9a169a59db37d549569910ae273a

# verify:  True

【04×02】JavaScript 语言实现

在 JavaScript 中已有比拟成熟的实现库,这里举荐 sm-crypto,目前反对 SM2、SM3 和 SM4,须要留神的是,SM2 非对称加密的后果由 C1、C2、C3 三局部组成,其中 C1 是生成随机数的计算出的椭圆曲线点,C2 是密文数据,C3 是 SM3 的摘要值,最开始的国密规范的后果是按 C1C2C3 程序的,新规范的是按 C1C3C2 程序寄存的,sm-crypto 反对设置 cipherMode,也就是 C1C2C3 的排列程序。

sm-crypto:https://www.npmjs.com/package…

以 SM2 算法为例,实现如下(其余算法和具体用法可参考其官网文档):

SM2 加密(encrypt)和解密(decrypt):

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 = "this is the data to be encrypted"
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode)    // 加密后果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密后果

console.log("encryptData:", encryptData)
console.log("decryptData:", decryptData)

// encryptData:  ddf261103fae06d0efe20ea0fe0d82bcc170e8efd8eeae24e9559b3835993f0ed2acb8ba6782fc21941ee74ca453d77664a5cb7dbb91517e6a3b0c27db7ce587ae7af54f8df48d7fa822b7062e2af66c112aa57de94d12ba28e5ba96bf4439d299b41da4a5282d054696adc64156d248049d1eb1d0af28d76b542fe8a95d427e

// decryptData:  this is the data to be encrypted

SM2 签名(sign)和校验(verify):

const sm2 = require('sm-crypto').sm2

// 获取密钥对
let keypair = sm2.generateKeyPairHex()
let publicKey = keypair.publicKey   // 公钥
let privateKey = keypair.privateKey // 私钥

// 纯签名 + 生成椭圆曲线点
let msgString = "this is the data to be signed"
let sigValueHex = sm2.doSignature(msgString, privateKey)                    // 签名
let verifyResult = sm2.doVerifySignature(msgString, sigValueHex, publicKey) // 验签后果

console.log("sigValueHex:", sigValueHex)
console.log("verifyResult:", verifyResult)

// sigValueHex:  924cbb9f2b5adb554ef77129ff1e3a00b2da42017ad3ec2f806d824a77646987ba8c8c4fb94576c38bc11ae69cc98ebbb40b5d47715171ec7dcea913dfc6ccc1

// verifyResult:  true

【04×03】其余语言实现以及参考资料

  • Java 语言实现:

    • https://github.com/bcgit/bc-c…
    • https://github.com/xjfuuu/SM2…
  • Go 语言实现:https://github.com/tjfoc/gmsm
  • 开源国密算法工具箱:http://gmssl.org/
  • 国密算法源代码下载:http://www.scctc.org.cn/templ…
  • 国家明码管理局:https://www.sca.gov.cn/
  • 明码规范委员会:http://www.gmbz.org.cn/

【05×00】附:GM/T 明码行业标准

  • GM/T 0001.1-2012:祖冲之序列密码算法:第 1 局部:算法形容
  • GM/T 0001.2-2012:祖冲之序列密码算法:第 2 局部:基于祖冲之算法的机密性算法
  • GM/T 0001.3-2012:祖冲之序列密码算法:第 3 局部:基于祖冲之算法的完整性算法
  • GM/T 0003.1-2012:SM2 椭圆曲线公钥明码算法第 1 局部:总则
  • GM/T 0003.2-2012:SM2 椭圆曲线公钥明码算法第 2 局部:数字签名算法
  • GM/T 0003.3-2012:SM2 椭圆曲线公钥明码算法第 3 局部:密钥替换协定
  • GM/T 0003.4-2012:SM2 椭圆曲线公钥明码算法第 4 局部:公钥加密算法
  • GM/T 0003.5-2012:SM2 椭圆曲线公钥明码算法第 5 局部:参数定义
  • GM/T 0004-2012:SM3 明码杂凑算法
  • GM/T 0002-2012:SM4 分组明码算法
  • GM/T 0044.1-2016:SM9 标识明码算法 第 1 局部:总则
  • GM/T 0044.2-2016:SM9 标识明码算法 第 2 局部:数字签名算法
  • GM/T 0044.3-2016:SM9 标识明码算法 第 3 局部:密钥替换协定
  • GM/T 0044.4-2016:SM9 标识明码算法 第 4 局部:密钥封装机制和公钥加密算法
  • GM/T 0044.5-2016:SM9 标识明码算法 第 5 局部:参数定义

退出移动版