爬虫逆向加密技术详解之对称加密算法:SM4加密解密

一、对称加密介绍


SM4属于对称加密算法,不知道什么是对称加密的小伙伴请看这篇文章:https://blog.youkuaiyun.com/thy525/article/details/147700959


二、SM4算法简介

SM4 是中国国家密码管理局发布的一种分组密码算法,也被称为国密 SM4 算法。它是一种对称加密算法,用于替代 DES 和 AES 等传统的对称加密算法。 其中“SM”代表“商密”,即用于商用的、不涉及国家秘密的密码技术。

核心参数定义 :

  1. 密钥与密钥位数

    • 密钥长度固定为128位(16字节),加密与解密使用同一密钥。
    • 密钥扩展:将初始密钥通过非线性变换生成32个32位轮密钥(RK₀至RK₃₁),用于32轮迭代加密。
  2. 初始向量(IV)

    • 在CBC、CFB等模式中需使用IV,长度为16字节,用于初始化加密状态,确保相同明文在不同加密操作中产生不同密文。
  3. 加密模式

    • ECB(电子密码本):明文分组独立加密,安全性低,不推荐用于敏感数据。
    • CBC(密码分组链接):前一块密文与当前明文异或后加密,适用于文件加密。
    • CTR(计数器模式):将块加密转为流密码,适合大数据量并行加密。
  4. 填充方式

    • 常用PKCS#5/PKCS#7填充,确保明文长度为分组长度(16字节)的整数倍。

三、SM4加密解密原理

  1. 加密流程

    • 密钥扩展:128位密钥生成32个轮密钥。
    • 分组处理:明文按128位分组,不足则填充。
    • 32轮迭代
      • 轮函数F:包含S盒替换(非线性变换)和线性变换(L函数),每轮使用一个轮密钥。
      • 反序变换:第32轮输出反序后得到密文。
  2. 解密流程

    • 与加密流程相同,但轮密钥按逆序(RK₃₁至RK₀)使用。

四、快速识别SM4加密的方法

4.1 密文长度判断

密文长度是 16 字节分组的整数倍转换为十六进制后的结果,通常是 16 或者32 的倍数。

4.2 验证密文字符集

密文是十六进制字符串,由字符 0 - 9a - f 组成。

4.3 代码特征识别

代码中可能包含SM4CryptSM4等算法标识。

总结:密文为十六进制字符串,这是与其他使用 Base64 编码的加密算法明显不同的特征。结合使用的 SM4 加密库和 16 字节分组的规律,可推测为 SM4 加密结果。

五、代码实现

5.1 JavaScript实现SM4加密解密

const sm4 = require('sm-crypto').sm4;

// SM4 加密函数,使用 CBC 模式和偏移量
function sm4Encrypt(plainText, key, iv) {
    return sm4.encrypt(plainText, key, {
        mode: 'cbc',
        iv: iv
    });
}

// SM4 解密函数,使用 CBC 模式和偏移量
function sm4Decrypt(cipherText, key, iv) {
    return sm4.decrypt(cipherText, key, {
        mode: 'cbc',
        iv: iv
    });
}

const plainText = '123456';
const key = '0123456789abcdeffedcba9876543210'; // 16字节密钥(Hex)
const iv = '00000000000000000000000000000000';  // 16字节IV(Hex)
const encrypted = sm4Encrypt(plainText, key, iv);
const decrypted = sm4Decrypt(encrypted, key, iv);

console.log('SM4 加密后密文: ', encrypted);
console.log('SM4 加密后密文长度: ', encrypted.length);
console.log('SM4 解密后: ', decrypted);

运行结果:

SM4 加密后密文:  13c71106a5aad6efddd2476f44565f37
SM4 加密后密文长度:  32
SM4 解密后:  123456

5.2 Python实现SM4加密解密

from gmssl import sm4


def sm4_encrypt(plain_text, key, iv):
    """
    SM4 加密函数,使用 CBC 模式和偏移量
    :param plain_text: 明文(字节串或字符串)
    :param key: 密钥(16字节或32字节的字节串)
    :param iv: 初始化向量(16字节的字节串)
    :return: 加密后的密文(字节串)
    """
    if isinstance(plain_text, str):
        plain_text = plain_text.encode('utf-8')
    if isinstance(key, str):
        key = bytes.fromhex(key)
    if isinstance(iv, str):
        iv = bytes.fromhex(iv)

    crypt_sm4 = sm4.CryptSM4()
    crypt_sm4.set_key(key, sm4.SM4_ENCRYPT)
    cipher_text = crypt_sm4.crypt_cbc(iv, plain_text)
    return cipher_text


def sm4_decrypt(cipher_text, key, iv):
    """
    SM4 解密函数,使用 CBC 模式和偏移量
    :param cipher_text: 密文(字节串)
    :param key: 密钥(16字节或32字节的字节串)
    :param iv: 初始化向量(16字节的字节串)
    :return: 解密后的明文(字节串)
    """
    if isinstance(key, str):
        key = bytes.fromhex(key)
    if isinstance(iv, str):
        iv = bytes.fromhex(iv)

    crypt_sm4 = sm4.CryptSM4()
    crypt_sm4.set_key(key, sm4.SM4_DECRYPT)
    plain_text = crypt_sm4.crypt_cbc(iv, cipher_text)
    return plain_text


# 示例使用
plain_text = '123456'
key = '0123456789abcdeffedcba9876543210'  # 16字节密钥(Hex)
iv = '00000000000000000000000000000000'  # 16字节IV(Hex)

# 加密
encrypted = sm4_encrypt(plain_text, key, iv)
print('SM4 加密后密文:', encrypted.hex())
print('SM4 加密后密文长度:', len(encrypted))

# 解密
decrypted = sm4_decrypt(encrypted, key, iv)
print('SM4 解密后:', decrypted.decode('utf-8'))

运行结果:

SM4 加密后密文:  13c71106a5aad6efddd2476f44565f37
SM4 加密后密文长度:  32
SM4 解密后:  123456
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值