【01x00】 簡介
國密即國家密碼局認定的國產(chǎn)加密算法揽惹,爬蟲工程師在做 JS 逆向的時候,會遇到各種各樣的加密算法四康,其中 RSA、AES狭握、SHA 等算法是最常見的闪金,這些算法都是國外的,在 K 哥以前的文章里也有介紹:《【爬蟲知識】爬蟲常見加密解密算法》
事實上從 2010 年開始论颅,我國國家密碼管理局就已經(jīng)開始陸續(xù)發(fā)布了一系列國產(chǎn)加密算法哎垦,這其中就包括 SM1、SM2恃疯、SM3 漏设、SM4、SM7今妄、SM9郑口、ZUC(祖沖之加密算法)等鸳碧,SM 代表商密,即商業(yè)密碼犬性,是指用于商業(yè)的瞻离、不涉及國家秘密的密碼技術(shù)。SM1 和 SM7 的算法不公開乒裆,其余算法都已成為 ISO/IEC 國際標準套利。
在這些國產(chǎn)加密算法中,SM2鹤耍、SM3肉迫、SM4 三種加密算法是比較常見的,在爬取部分 gov 網(wǎng)站時稿黄,也可能會遇到這些算法喊衫,所以作為爬蟲工程師是有必要了解一下這些算法的,如下圖所示某 gov 網(wǎng)站就使用了 SM2 和 SM4 加密算法:
【02x00】算法概述
算法名稱 | 算法類別 | 應(yīng)用領(lǐng)域 | 特點 |
---|---|---|---|
SM1 | 對稱(分組)加密算法 | 芯片 | 分組長度抛猖、密鑰長度均為 128 比特 |
SM2 | 非對稱(基于橢圓曲線 ECC)加密算法 | 數(shù)據(jù)加密 | ECC 橢圓曲線密碼機制 256 位格侯,相比 RSA 處理速度快,消耗更少 |
SM3 | 散列(hash)函數(shù)算法 | 完整性校驗 | 安全性及效率與 SHA-256 相當财著,壓縮函數(shù)更復雜 |
SM4 | 對稱(分組)加密算法 | 數(shù)據(jù)加密和局域網(wǎng)產(chǎn)品 | 分組長度联四、密鑰長度均為 128 比特,計算輪數(shù)多 |
SM7 | 對稱(分組)加密算法 | 非接觸式 IC 卡 | 分組長度撑教、密鑰長度均為 128 比特 |
SM9 | 標識加密算法(IBE) | 端對端離線安全通訊 | 加密強度等同于 3072 位密鑰的 RSA 加密算法 |
ZUC | 對稱(序列)加密算法 | 移動通信 4G 網(wǎng)絡(luò) | 流密碼 |
【03x00】算法詳解
【03x01】SM1 分組加密算法
SM1 為分組加密算法朝墩,對稱加密,分組長度和密鑰長度都為 128 位伟姐,故對消息進行加解密時收苏,若消息長度過長,需要進行分組愤兵,要消息長度不足鹿霸,則要進行填充。算法安全保密強度及相關(guān)軟硬件實現(xiàn)性能與 AES 相當秆乳,該算法不公開懦鼠,僅以 IP 核的形式存在于芯片中,調(diào)用該算法時屹堰,需要通過加密芯片的接口進行調(diào)用肛冶,采用該算法已經(jīng)研制了系列芯片、智能 IC 卡扯键、智能密碼鑰匙睦袖、加密卡、加密機等安全產(chǎn)品荣刑,廣泛應(yīng)用于電子政務(wù)馅笙、電子商務(wù)及國民經(jīng)濟的各個應(yīng)用領(lǐng)域(包括國家政務(wù)通伦乔、警務(wù)通等重要領(lǐng)域),一般了解的人比較少延蟹,爬蟲工程師也不會遇到這種加密算法评矩。
【03x02】SM2 橢圓曲線公鑰加密算法
SM2 為橢圓曲線(ECC)公鑰加密算法,非對稱加密阱飘,SM2 算法和 RSA 算法都是公鑰加密算法斥杜,SM2 算法是一種更先進安全的算法,在我們國家商用密碼體系中被用來替換 RSA 算法沥匈,在不少 gov 網(wǎng)站會見到此類加密算法蔗喂。我國學者對橢圓曲線密碼的研究從 20 世紀 80 年代開始,目前已取得不少成果高帖,SM2 橢圓曲線公鑰密碼算法比 RSA 算法有以下優(yōu)勢:
SM2 | RSA | |
---|---|---|
安全性 | 256 位 SM2 強度已超過 RSA-2048 | 一般 |
算法結(jié)構(gòu) | 基本橢圓曲線(ECC) | 基于特殊的可逆模冪運算 |
計算復雜度 | 完全指數(shù)級 | 亞指數(shù)級 |
存儲空間(密鑰長度) | 192-256 bit | 2048-4096 bit |
秘鑰生成速度 | 較 RSA 算法快百倍以上 | 慢 |
解密加密速度 | 較快 | 一般 |
【03x03】SM3 雜湊算法
SM3 為密碼雜湊算法缰儿,采用密碼散列(hash)函數(shù)標準,用于替代 MD5/SHA-1/SHA-2 等國際算法散址,是在 SHA-256 基礎(chǔ)上改進實現(xiàn)的一種算法乖阵,消息分組長度為 512 位,摘要值長度為 256 位预麸,其中使用了異或瞪浸、模、模加吏祸、移位对蒲、與、或贡翘、非運算蹈矮,由填充、迭代過程鸣驱、消息擴展和壓縮函數(shù)所構(gòu)成泛鸟。在商用密碼體系中,SM3 主要用于數(shù)字簽名及驗證踊东、消息認證碼生成及驗證谈况、隨機數(shù)生成等。據(jù)國家密碼管理局表示递胧,其安全性及效率要高于 MD5 算法和 SHA-1 算法,與 SHA-256 相當赡茸。
【03x04】SM4 分組加密算法
SM4 為無線局域網(wǎng)標準的分組加密算法缎脾,對稱加密,用于替代 DES/AES 等國際算法占卧,SM4 算法與 AES 算法具有相同的密鑰長度和分組長度遗菠,均為 128 位联喘,故對消息進行加解密時,若消息長度過長辙纬,需要進行分組豁遭,要消息長度不足,則要進行填充贺拣。加密算法與密鑰擴展算法都采用 32 輪非線性迭代結(jié)構(gòu)蓖谢,解密算法與加密算法的結(jié)構(gòu)相同,只是輪密鑰的使用順序相反譬涡,解密輪密鑰是加密輪密鑰的逆序闪幽。
SM4 | DES | AES | |
---|---|---|---|
計算輪數(shù) | 32 | 16(3DES 為 16*3) | 10/12/14 |
密碼部件 | S 盒、非線性變換涡匀、線性變換盯腌、合成變換 | 標準算術(shù)和邏輯運算、先替換后置換陨瘩,不含線性變換 | S 盒腕够、行移位變換、列混合變換舌劳、圈密鑰加變換(AddRoundKey) |
【03x05】SM7 分組加密算法
SM7 為分組加密算法帚湘,對稱加密,該算法不公開蒿囤,應(yīng)用包括身份識別類應(yīng)用(非接觸式 IC 卡客们、門禁卡、工作證材诽、參賽證等)底挫,票務(wù)類應(yīng)用(大型賽事門票、展會門票等)脸侥,支付與通卡類應(yīng)用(積分消費卡建邓、校園一卡通、企業(yè)一卡通等)睁枕。爬蟲工程師基本上不會遇到此類算法官边。
【03x06】SM9 標識加密算法
SM9 為標識加密算法(Identity-Based Cryptography),非對稱加密外遇,標識加密將用戶的標識(如微信號注簿、郵件地址、手機號碼跳仿、QQ 號等)作為公鑰诡渴,省略了交換數(shù)字證書和公鑰過程,使得安全系統(tǒng)變得易于部署和管理菲语,適用于互聯(lián)網(wǎng)應(yīng)用的各種新興應(yīng)用的安全保障妄辩,如基于云技術(shù)的密碼服務(wù)惑灵、電子郵件安全、智能終端保護眼耀、物聯(lián)網(wǎng)安全英支、云存儲安全等等。這些安全應(yīng)用可采用手機號碼或郵件地址作為公鑰哮伟,實現(xiàn)數(shù)據(jù)加密干花、身份認證、通話加密澈吨、通道加密等把敢。在商用密碼體系中,SM9 主要用于用戶的身份認證谅辣,據(jù)新華網(wǎng)公開報道修赞,SM9 的加密強度等同于 3072 位密鑰的 RSA 加密算法。
【03x07】ZUC 祖沖之算法
ZUC 為流密碼算法桑阶,對稱加密柏副,該機密性算法可適用于 3GPP LTE 通信中的加密和解密,該算法包括祖沖之算法(ZUC)蚣录、機密性算法(128-EEA3)和完整性算法(128-EIA3)三個部分割择。已經(jīng)被國際組織 3GPP 推薦為 4G 無線通信的第三套國際加密和完整性標準的候選算法。
【04x00】編程語言實現(xiàn)
【04x01】Python 語言實現(xiàn)
在 Python 里面并沒有比較官方的庫來實現(xiàn)國密算法萎河,這里僅列出了其中兩個較為完善的第三方庫荔泳,需要注意的是,SM1 和 SM7 算法不公開虐杯,目前大多庫僅實現(xiàn)了 SM2玛歌、SM3、SM4 三種密算法擎椰。
- snowland-smx-python:https://gitee.com/snowlandltd/snowland-smx-python
- gmssl:https://github.com/duanhongyi/gmssl
- gmssl-python:https://github.com/gongxian-ding/gmssl-python
其中 gmssl-python 是 gmssl 的改進版支子,gmssl-python 新增支持了 SM9 算法,不過截止本文編寫時达舒,gmssl-python 并未發(fā)布 pypi值朋,也未 PR 到 gmssl,使用 pip install gmssl
安裝的 gmssl 不支持 SM9 算法巩搏。若要使用 SM9 算法昨登,可下載 gmssl-python 源碼手動安裝。
以 gmssl 的 SM2 算法為例贯底,實現(xiàn)如下(其他算法和詳細用法可參考其官方文檔):
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)
# 待加密數(shù)據(jù)和加密后數(shù)據(jù)為 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)
# 待簽名數(shù)據(jù)為 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
【04x02】JavaScript 語言實現(xiàn)
在 JavaScript 中已有比較成熟的實現(xiàn)庫篙骡,這里推薦 sm-crypto,目前支持 SM2、SM3 和 SM4糯俗,需要注意的是,SM2 非對稱加密的結(jié)果由 C1睦擂、C2得湘、C3 三部分組成,其中 C1 是生成隨機數(shù)的計算出的橢圓曲線點顿仇,C2 是密文數(shù)據(jù)淘正,C3 是 SM3 的摘要值,最開始的國密標準的結(jié)果是按 C1C2C3 順序的臼闻,新標準的是按 C1C3C2 順序存放的鸿吆,sm-crypto 支持設(shè)置 cipherMode,也就是 C1C2C3 的排列順序述呐。
sm-crypto:https://www.npmjs.com/package/sm-crypto
以 SM2 算法為例惩淳,實現(xiàn)如下(其他算法和詳細用法可參考其官方文檔):
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) // 加密結(jié)果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密結(jié)果
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) // 驗簽結(jié)果
console.log("sigValueHex: ", sigValueHex)
console.log("verifyResult: ", verifyResult)
// sigValueHex: 924cbb9f2b5adb554ef77129ff1e3a00b2da42017ad3ec2f806d824a77646987ba8c8c4fb94576c38bc11ae69cc98ebbb40b5d47715171ec7dcea913dfc6ccc1
// verifyResult: true
【04x03】其他語言實現(xiàn)以及參考資料
- Java 語言實現(xiàn):
- Go 語言實現(xiàn):https://github.com/tjfoc/gmsm
- 開源國密算法工具箱:http://gmssl.org/
- 國密算法源代碼下載:http://www.scctc.org.cn/templates/Download/index.aspx?nodeid=71
- 國家密碼管理局:https://www.sca.gov.cn/
- 密碼標準委員會:http://www.gmbz.org.cn/
【05x00】附:GM/T 密碼行業(yè)標準
- 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部分:數(shù)字簽名算法
- GM/T 0003.3-2012:SM2 橢圓曲線公鑰密碼算法第3部分:密鑰交換協(xié)議
- GM/T 0003.4-2012:SM2 橢圓曲線公鑰密碼算法第4部分:公鑰加密算法
- GM/T 0003.5-2012:SM2 橢圓曲線公鑰密碼算法第5部分:參數(shù)定義
- GM/T 0004-2012:SM3 密碼雜湊算法
- GM/T 0002-2012:SM4 分組密碼算法
- GM/T 0044.1-2016:SM9 標識密碼算法 第1部分:總則
- GM/T 0044.2-2016:SM9 標識密碼算法 第2部分:數(shù)字簽名算法
- GM/T 0044.3-2016:SM9 標識密碼算法 第3部分:密鑰交換協(xié)議
- GM/T 0044.4-2016:SM9 標識密碼算法 第4部分:密鑰封裝機制和公鑰加密算法
- GM/T 0044.5-2016:SM9 標識密碼算法 第5部分:參數(shù)定義