Skip to main content

熵密杯2024

·1934 words·10 mins
Table of Contents

为什么我证书patch不上 哭了

sm3长度扩展 #

我在此处囤个脚本,省得以后找了

my_sm3

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
"""
@Time:2019/10/13
@Author: hhzjj
@Description:SM3实现 将IV换成第一步得到第一步hash时各寄存器的值
"""
import binascii
from math import ceil
from myfunc import rotl, bytes_to_list

IV = [
    1937774191, 1226093241, 388252375, 3666478592,
    2842636476, 372324522, 3817729613, 2969243214,
]

T_j = [
    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
    2043430169, 2043430169, 2043430169, 2043430169, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042
]


def sm3_ff_j(x, y, z, j):
    if 0 <= j and j < 16:
        ret = x ^ y ^ z
    elif 16 <= j and j < 64:
        ret = (x & y) | (x & z) | (y & z)
    return ret

def sm3_gg_j(x, y, z, j):
    if 0 <= j and j < 16:
        ret = x ^ y ^ z
    elif 16 <= j and j < 64:
        #ret = (X | Y) & ((2 ** 32 - 1 - X) | Z)
        ret = (x & y) | ((~ x) & z)
    return ret

def sm3_p_0(x):
    return x ^ (rotl(x, 9 % 32)) ^ (rotl(x, 17 % 32))

def sm3_p_1(x):
    return x ^ (rotl(x, 15 % 32)) ^ (rotl(x, 23 % 32))

def sm3_cf(v_i, b_i):
    w = []
    for i in range(16):
        weight = 0x1000000
        data = 0
        for k in range(i*4,(i+1)*4):
            data = data + b_i[k]*weight
            weight = int(weight/0x100)
        w.append(data)

    for j in range(16, 68):
        w.append(0)
        w[j] = sm3_p_1(w[j-16] ^ w[j-9] ^ (rotl(w[j-3], 15 % 32))) ^ (rotl(w[j-13], 7 % 32)) ^ w[j-6]
        str1 = "%08x" % w[j]
    w_1 = []
    for j in range(0, 64):
        w_1.append(0)
        w_1[j] = w[j] ^ w[j+4]
        str1 = "%08x" % w_1[j]

    a, b, c, d, e, f, g, h = v_i

    for j in range(0, 64):
        ss_1 = rotl(
            ((rotl(a, 12 % 32)) +
            e +
            (rotl(T_j[j], j % 32))) & 0xffffffff, 7 % 32
        )
        ss_2 = ss_1 ^ (rotl(a, 12 % 32))
        tt_1 = (sm3_ff_j(a, b, c, j) + d + ss_2 + w_1[j]) & 0xffffffff
        tt_2 = (sm3_gg_j(e, f, g, j) + h + ss_1 + w[j]) & 0xffffffff
        d = c
        c = rotl(b, 9 % 32)
        b = a
        a = tt_1
        h = g
        g = rotl(f, 19 % 32)
        f = e
        e = sm3_p_0(tt_2)

        a, b, c, d, e, f, g, h = map(
            lambda x:x & 0xFFFFFFFF ,[a, b, c, d, e, f, g, h])

    v_j = [a, b, c, d, e, f, g, h]
    return [v_j[i] ^ v_i[i] for i in range(8)]

def sm3_hash(msg, new_v):
    # print(msg)
    len1 = len(msg)
    reserve1 = len1 % 64
    msg.append(0x80)
    reserve1 = reserve1 + 1
    # 56-64, add 64 byte
    range_end = 56
    if reserve1 > range_end:
        range_end = range_end + 64

    for i in range(reserve1, range_end):
        msg.append(0x00)

    bit_length = (len1) * 8
    bit_length_str = [bit_length % 0x100]
    for i in range(7):
        bit_length = int(bit_length / 0x100)
        bit_length_str.append(bit_length % 0x100)
    for i in range(8):
        msg.append(bit_length_str[7-i])

    group_count = round(len(msg) / 64) - 1

    B = []
    for i in range(0, group_count):
        B.append(msg[(i + 1)*64:(i+2)*64])

    V = []
    V.append(new_v)
    for i in range(0, group_count):
        V.append(sm3_cf(V[i], B[i]))

    y = V[i+1]
    result = ""
    for i in y:
        result = '%s%08x' % (result, i)
    return result


def sm3_kdf(z, klen): # z为16进制表示的比特串(str),klen为密钥长度(单位byte)
    klen = int(klen)
    ct = 0x00000001
    rcnt = ceil(klen/32)
    zin = [i for i in bytes.fromhex(z.decode('utf8'))]
    ha = ""
    for i in range(rcnt):
        msg = zin  + [i for i in binascii.a2b_hex(('%08x' % ct).encode('utf8'))]
        ha = ha + sm3_hash(msg)
        ct += 1
    return ha[0: klen * 2]

myfunc

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
from random import choice


xor = lambda a, b:list(map(lambda x, y: x ^ y, a, b))

rotl = lambda x, n:((x << n) & 0xffffffff) | ((x >> (32 - n)) & 0xffffffff)

get_uint32_be = lambda key_data:((key_data[0] << 24) | (key_data[1] << 16) | (key_data[2] << 8) | (key_data[3]))

put_uint32_be = lambda n:[((n>>24)&0xff), ((n>>16)&0xff), ((n>>8)&0xff), ((n)&0xff)]

padding = lambda data, block=16: data + [(16 - len(data) % block)for _ in range(16 - len(data) % block)]

unpadding = lambda data: data[:-data[-1]]

list_to_bytes = lambda data: b''.join([bytes((i,)) for i in data])

bytes_to_list = lambda data: [i for i in data]

random_hex = lambda x: ''.join([choice('0123456789abcdef') for _ in range(x)])

exp

from gmssl import sm3, func
import random
import my_sm3
import struct

# secret = str(random.random())
# secret_hash = sm3.sm3_hash(func.bytes_to_list(bytes(secret, encoding='utf-8')))
# secret_len = len(secret)


append_m = ""   # 附加消息
pad_str = ""
pad = []


def generate_guess_hash(old_hash, secret_len, append_m):
    """
    SM3长度扩展攻击
    :param old_hash: secret的hash值
    :param secret_len: secret的长度
    :param append_m: 附加的消息
    :return: hash(secret + padding + append_m)
    """
    vectors = []
    message = ""
    # 将old_hash分组,每组8个字节, 并转换为整数
    for r in range(0, len(old_hash), 8):
        vectors.append(int(old_hash[r:r + 8], 16))

    # 伪造消息
    if secret_len > 64:
        for i in range(0, int(secret_len / 64) * 64):
            message += 'a'
    for i in range(0, secret_len % 64):
        message += 'a'
    message = func.bytes_to_list(bytes(message, encoding='utf-8'))
    message = padding(message)
    message.extend(func.bytes_to_list(append_m))
    return my_sm3.sm3_hash(message, vectors)


def padding(msg):
    mlen = len(msg)
    msg.append(0x80)
    mlen += 1
    tail = mlen % 64
    range_end = 56
    if tail > range_end:
        range_end = range_end + 64
    for i in range(tail, range_end):
        msg.append(0x00)
    bit_len = (mlen - 1) * 8
    msg.extend([int(x) for x in struct.pack('>q', bit_len)])
    for j in range(int((mlen - 1) / 64) * 64 + (mlen - 1) % 64, len(msg)):
        global pad
        pad.append(msg[j])
        global pad_str
        pad_str += str(hex(msg[j]))
    return msg

secret_hash = "890778c09f1f203f6728c573ca4a030e5cd0488d8c396f752acb6861fccb13ac"


append_m = b'\xff\xff\xff\xff'
secret_len = 36
guess_hash = generate_guess_hash(secret_hash, secret_len, append_m)

append_m = b'\xff\xff\xff\xff'

conter = "6c09794a"+"80000000000000000000000000000000000000000000000000000120ffffffff"
print(conter)

print("guess_hash " , guess_hash)

一个简陋lwe #

task

import sympy as sp
import random

# 设置参数
n = 16  # 向量长度
q = 251  # 模数

# 生成随机噪声向量e
e = sp.Matrix(sp.randMatrix(n, 1, min=0, max=1))  # 噪声向量

# 生成随机n维私钥向量s和n*n矩阵A
s = sp.Matrix(sp.randMatrix(n, 1, min=0, max=q - 1))  # 私钥向量
Temp = sp.Matrix(sp.randMatrix(n, n, min=0, max=q - 1))  # 中间变量矩阵Temp
A = Temp.inv_mod(q)  # 计算矩阵Temp在模 q 下的逆矩阵作为A

# 计算n维公钥向量b
b = (A * s + e) % q  # 公钥向量b = A * s + e


# 加密函数
def encrypt(message, A, b):
    m_bin = bin(message)[2:].zfill(n)  # 将消息转换为16比特的二进制字符串
    m = sp.Matrix([int(bit) for bit in m_bin])  # 转换为SymPy矩阵
    x = sp.Matrix(sp.randMatrix(n, n, min=0, max=q // (n * 4)))  # 随机产生一个n*n的矩阵x
    e1 = sp.Matrix(sp.randMatrix(n, 1, min=0, max=1))  # 随机产生一个n维噪声向量e
    c1 = (x * A) % q  # 密文部分c1 =   x * A
    c2 = (x * b + e1 + m * (q // 2)) % q  # 密文部分c2 = x * b + e1 + m * q/2
    return c1, c2


# 解密函数
def decrypt(c1, c2, s):
    m_dec = (c2 - c1 * s) % q
    m_rec = m_dec.applyfunc(lambda x: round(2 * x / q) % 2)  # 还原消息
    m_bin = ''.join([str(bit) for bit in m_rec])  # 将SymPy矩阵转换为二进制字符串
    m_rec_int = int(m_bin, 2)  # 将二进制字符串转换为整数
    return m_rec_int


# 测试加解密
message = random.randint(0, 2 ** n - 1)  # 要加密的消息,随机生成一个16比特整数
c1, c2 = encrypt(message, A, b)  # 加密

print("原始消息: ", message)
print("公钥A=sp.", A)
print("公钥b=sp.", b)
print("密文c1=sp.", c1)
print("密文c2=sp.", c2)

decrypted_message = decrypt(c1, c2, s)
print("解密后的消息: ", decrypted_message)  # 输出解密后的消息

在解密时将e置为全0,可以成功解密massage

import sympy as sp
import random

# 设置参数
n = 16  # 向量长度
q = 251  # 模数

# 生成随机噪声向量e e


# 加密函数
def encrypt(message, A, b):
    m_bin = bin(message)[2:].zfill(n)  # 将消息转换为16比特的二进制字符串
    m = sp.Matrix([int(bit) for bit in m_bin])  # 转换为SymPy矩阵
    
    x = sp.Matrix(sp.randMatrix(n, n, min=0, max=q // (n * 4)))  # 随机产生一个n*n的矩阵x
    e1 = sp.Matrix(sp.randMatrix(n, 1, min=0, max=1))  # 随机产生一个n维噪声向量e
    
    c1 = (x * A) % q  # 密文部分c1 =   x * A
    c2 = (x * b + e1 + m * (q // 2)) % q  # 密文部分c2 = x * b + e1 + m * q/2
    return c1, c2


# 解密函数
def decrypt(c1, c2, s):
    m_dec = (c2 - c1 * s) % q
    m_rec = m_dec.applyfunc(lambda x: round(2 * x / q) % 2)  # 还原消息
    m_bin = ''.join([str(bit) for bit in m_rec])  # 将SymPy矩阵转换为二进制字符串
    m_rec_int = int(m_bin, 2)  # 将二进制字符串转换为整数
    return m_rec_int


# 测试加解密
# message = random.randint(0, 2 ** n - 1)  # 要加密的消息,随机生成一个16比特整数
# c1, c2 = encrypt(message, A, b)  # 加密

# print("原始消息: ", message)·


A=sp.Matrix([[243, 235, 167, 9, 150, 190, 119, 61, 46, 112, 27, 83, 249, 142, 102, 79], [236, 155, 70, 72, 247, 167, 129, 104, 129, 171, 249, 171, 143, 115, 244, 132], [60, 237, 108, 54, 38, 83, 162, 175, 209, 193, 3, 159, 88, 158, 213, 85], [128, 86, 66, 95, 201, 87, 205, 56, 53, 75, 166, 65, 243, 228, 144, 35], [45, 53, 59, 61, 13, 29, 78, 161, 232, 15, 83, 35, 192, 114, 185, 45], [188, 39, 139, 44, 208, 47, 78, 154, 223, 137, 56, 30, 141, 64, 130, 199], [75, 117, 156, 103, 176, 1, 226, 8, 53, 167, 15, 91, 42, 122, 139, 228], [243, 39, 59, 230, 250, 134, 70, 125, 57, 154, 244, 32, 118, 202, 223, 184], [38, 99, 163, 180, 184, 60, 52, 42, 7, 207, 87, 95, 188, 177, 244, 7], [67, 208, 131, 95, 67, 147, 188, 199, 115, 220, 221, 109, 37, 159, 212, 180], [112, 233, 124, 110, 57, 2, 186, 250, 186, 148, 245, 37, 204, 32, 31, 60], [170, 114, 211, 54, 133, 75, 60, 62, 75, 218, 79, 116, 63, 155, 123, 5], [186, 119, 87, 227, 73, 164, 59, 13, 142, 129, 44, 19, 4, 164, 12, 103], [40, 232, 237, 135, 42, 210, 99, 131, 217, 225, 42, 220, 148, 116, 69, 236], [153, 93, 138, 181, 191, 94, 157, 89, 218, 20, 136, 112, 180, 144, 214, 181], [17, 99, 91, 122, 169, 97, 74, 216, 82, 168, 166, 224, 23, 226, 202, 247]])

b=sp.Matrix([[134], [126], [157], [9], [166], [151], [149], [126], [95], [24], [62], [55], [7], [220], [239], [241]])

c1=sp.Matrix([[69, 232, 230, 63, 147, 120, 141, 146, 94, 101, 144, 212, 34, 79, 14, 158], [37, 194, 146, 82, 234, 99, 83, 10, 116, 153, 135, 202, 107, 106, 4, 139], [122, 216, 74, 193, 204, 187, 117, 120, 57, 182, 193, 226, 112, 225, 244, 111], [242, 199, 3, 106, 68, 102, 150, 75, 66, 186, 73, 76, 49, 112, 57, 233], [197, 139, 66, 9, 218, 134, 95, 242, 217, 4, 95, 200, 163, 234, 143, 27], [172, 130, 38, 76, 83, 71, 107, 69, 176, 68, 234, 162, 140, 131, 156, 68], [3, 157, 106, 106, 18, 67, 70, 186, 149, 222, 233, 83, 125, 172, 193, 16], [47, 200, 2, 133, 135, 191, 83, 78, 208, 225, 41, 226, 130, 38, 102, 31], [153, 92, 195, 56, 137, 161, 136, 91, 187, 198, 191, 6, 43, 141, 249, 8], [87, 232, 69, 230, 106, 119, 30, 201, 228, 60, 76, 230, 233, 57, 161, 48], [33, 220, 188, 140, 61, 174, 41, 23, 226, 61, 197, 159, 39, 62, 31, 232], [178, 194, 149, 161, 67, 19, 160, 89, 58, 37, 237, 82, 159, 11, 214, 155], [161, 6, 105, 144, 4, 215, 213, 86, 42, 144, 192, 107, 123, 198, 14, 100], [57, 129, 174, 207, 21, 122, 174, 225, 32, 19, 37, 230, 55, 105, 106, 28], [231, 246, 162, 210, 116, 100, 205, 241, 153, 126, 148, 155, 0, 25, 185, 134], [201, 120, 97, 103, 184, 164, 205, 155, 42, 189, 106, 218, 129, 198, 35, 248]])

c2=sp.Matrix([[233], [178], [154], [72], [224], [107], [97], [49], [179], [151], [245], [179], [242], [171], [199], [220]])


# 2699
Temp =  A.inv_mod(q)

s1 = Temp*(b)
decrypted_message = decrypt(c1, c2, s1)
print("解密后的消息: ", decrypted_message)  # 输出解密后的消息