SM4-CBC反转字节攻击(附代码)

CBC模式:Cipher Block Chaining mode,密文分组链接模式

CBC模式是先将明文分成若干个组块,然后每个明文分组与前一密文分组进行异或 XORXOR 运算,然后再进行加密。因此,每个密文分组都依赖于它前面的所有明文分组

由于密文分组像链条一样相互连接在一起,因此称为密文分组链接模式。

由于CBC模式分组块与块之间有相互连接关系,解密时前一块的密文会参与后一块密文的解密,所以我们更改前一块密文的值时,也会对后一块解密后的明文造成影响,而当我们知晓完整的密文和后一块密文对应的明文时,后一块密文解密出的明文就是可控制的,即我们可以通过控制A的值,进而控制C的值。这个攻击方式就是“CBC模式的反转字节攻击”,下面详细介绍原理。(至于为什么这么叫,我猜测是因为原理依赖异或运算吧)

在上图中,密文分组1为A,密文分组2进行解密运算后为B。明文分组2为C。

由CBC解密原理或图片信息可得:C=A^B。

由于异或两次同一个数等于啥也没干可由上式推出:B=A^C。

现在开始操作密文的值,使A'=A^C,用A'替换原来A的位置。

这个时候C=A'^B=(A^C)^(A^C)=0   C就被操作成了全0的值。

聪明的你肯定想到了,x^0=x。

所以我们再操作一次密文,A''=A^C^x,用A''替代上图中A的位置。

这个时候C=(A^C^x)^(A^C)=x

通过以上方法,我们就做到了在仅已知一对明文密文的情况下,通过修改密文得到一组成立的明密文对,且可以根据我们的喜好自定义明文的一部分。

博主博主,这种方式看起来很巧妙,但感觉没什么用呀,有什么具体的使用示例吗?

下面展示一个具体示例,假设我们通过抓包、监听等方式得到了一组明密文:

待加密内容: abcdefghijklm123456789111-staff
sm4_cbc加密后的结果: a44668576540e3bbf1b95115481e373c5af8c5fdaf5f775b65da549c7ecb8483 

你可以观察到这里明文结尾为用户名,所以我们可以通过刚刚学到的字节反转攻击方式构造一段明密文,修改最后的用户名,达到伪装为任何用户的目的。

Talk is cheap,上代码,这里通过修改密文,我们伪装了用户名为draina的一段明密文:

# -*-coding: utf-8-*-

from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT

import binascii
import base64

class SM4_cbc:

    def __init__(self):
        self.crypt_sm4 = CryptSM4()

    def str_to_strBin(self, hex_str):
        hex_data = hex_str.encode('utf-8')
        str_bin = binascii.unhexlify(hex_data)
        return str_bin.decode('utf-8')

    def encrypt_cbc(self, cbc_key, iv, value):
        crypt_cbc = self.crypt_sm4
        crypt_cbc.set_key(binascii.a2b_hex(cbc_key), SM4_ENCRYPT)
        Enc_value = crypt_cbc.crypt_cbc(binascii.a2b_hex(iv), value.encode())
        return binascii.b2a_hex(Enc_value)

    def decrypt_cbc(self, cbc_key, iv, value):
        crypt_cbc = self.crypt_sm4
        crypt_cbc.set_key(binascii.a2b_hex(cbc_key), SM4_DECRYPT)
        Dec_value = crypt_cbc.crypt_cbc(binascii.a2b_hex(iv), value)
        return Dec_value


def hex_to_base64(payload_hex2):
    bytes_out = bytes.fromhex(payload_hex2)
    str_out = base64.b64encode(bytes_out)
    # print("hex_to_base64:", str_out)
    return str_out


def pkcs7_pad(data: bytes, block_size: int = 16) -> bytes:
    """对数据进行 PKCS7 填充"""
    padding_length = block_size - (len(data) % block_size)
    padding = bytes([padding_length] * padding_length)
    return data + padding


def utf8_to_hex_with_padding(plain_text: str) -> str:
    """将 UTF-8 明文转换为十六进制字符串,并进行 PKCS7 填充"""
    utf8_bytes = plain_text.encode('utf-8')
    padded_bytes = pkcs7_pad(utf8_bytes)
    hex_string = padded_bytes.hex()

    return hex_string


def xor_hex_strings(hex1, hex2):
    # 将16进制字符串转换为整数
    int1 = int(hex1, 16)
    int2 = int(hex2, 16)
    # 进行按位异或操作
    xor_result = int1 ^ int2
    # 将结果转换回16进制字符串,并去掉前缀 '0x'
    return hex(xor_result)[2:]

if __name__ == '__main__':
    key = "b01b1e51ba8b9bfcd584ab5b73ab7670"
    str_data = "abcdefghijklm123456789111-staff"
    iv_str = "e5709dcac5e3016de93aaf7b364693c3"
    SM4 = SM4_cbc()
    print("待加密内容:", str_data)
    print("p=",utf8_to_hex_with_padding(str_data))
    cipher = SM4.encrypt_cbc(key, iv_str, str_data)
    cipher_hex = cipher.decode()
    print("sm4_cbc加密后的结果:", cipher_hex, type(cipher_hex))

    val = hex_to_base64(cipher_hex)
    decode_cbc = SM4.decrypt_cbc(key, iv_str, base64.b64decode(val))
    print("sm4_cbc解密结果是:", decode_cbc.decode(), "\n")

    print("下面是字节反转攻击,将staff改为draina")
    p22=utf8_to_hex_with_padding('abcdefghijklm12888888888-draina')[-32:]
    #新明文第二分组,将p2的尾部改为draina后转为HEX并填充

    temp=xor_hex_strings(cipher_hex[:32],utf8_to_hex_with_padding(str_data)[-32:])
    cipherx1= xor_hex_strings(p22,temp)
    #计算新密文的第一个分组,即原明文的第二个分组异或原密文的第一个分组 再异或需要得到的新明文的第二个分组

    cipherx12=cipherx1+cipher_hex[-32:]
    print('新的密文为',cipherx12)
    val2 = hex_to_base64(cipherx12)
    decode_cbc2 = SM4.decrypt_cbc(key, iv_str, base64.b64decode(val2))
    print("sm4_cbc解密结果是:",decode_cbc2, "\n")

-END-

参考链接:
python GMSSL包实现SM4算法ECB, CBC【含OFB、CFB、CTR资源!见页首】_python sm4 cbc 加解密-CSDN博客文章浏览阅读1.8k次,点赞2次,收藏5次。python GMSSL包实现SM4算法ECB, CBC。​key和iv数据输入均为32个16进制数,以上。代码里可能使用的一些方法。_python sm4 cbc 加解密 https://blog.csdn.net/weixin_42437696/article/details/133786366AES CBC 翻转字节攻击 - F0und一个新的 Puti 站点。http://f0und.icu/article/28.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Draina

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

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

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

打赏作者

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

抵扣说明:

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

余额充值