区块链挖矿实验

自己新建一个文件M,将文件中的汉字和标点符号用区位码代替生成一个数字字符串,如果是英文的文件,将英文、标点符号和空格都用阿斯克码代替,转换的程序可以自己编写程序,也可以调用别人的程序。转换之后计算该文件的单向散列函数值H(M),然后通过在该散列函数值后面添加随机数的方法,即进一步计算H(H(M)||R)的方法进行挖矿。

设置单向散列函数值为256比特,假设要求H(H(M)||R)<2250,首先设置R=0,计算H(H(M)||R),首先将R值设置为0,然后每次将R值增加1计算对应的单向散列函数值,直到找到满足要求的单向散列函数值。记下对应的随机数、单向散列函数值和找到满足要求的函数值的时间。

完整代码

import re
import time

# 初始值
iv = 0x7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e
MAX = 2 ** 32


# 算法常量 随j的变化取不同的值
def Tj(j):
    if j <= 15:
        return 0x79cc4519
    else:
        return 0x7a879d8a


# 布尔函数FF 随j的变化取不同的表达式
def FF(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | (x & z) | (y & z)


# 布尔函数GG 随j的变化取不同的表达式
def GG(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | ((x ^ 0xFFFFFFFF) & z)


# 置换函数p0 压缩函数中的置换函数
def p0(x):
    return x ^ rotate_left(x, 9) ^ rotate_left(x, 17)


# 置换函数P1 消息扩展中的置换函数
def p1(x):
    return x ^ rotate_left(x, 15) ^ rotate_left(x, 23)


# 对消息进行填充,“1”+k个“0” 填充后的消息满足:(l+1+k) mod 512 = 448 k取最小非负整数
# 添加1、0后再添加一个64位比特串,该比特串是长度的二进制表示。填充后消息的比特长度为512的倍数
def filling(msg_bin):
    l = len(msg_bin)
    k = 448 - (l + 1) % 512
    if k < 0:
        k += 512
    l_bin = int2bin(l, 64)
    msg_filled = msg_bin + '1' + '0' * k + l_bin
    return msg_filled


# 迭代过程 迭代压缩后的消息,长度为64的字符串
def iteration(msg):
    # 将填充后的消息按512比特进行分组
    n = len(msg) // 512
    b = []
    for i in range(n):
        b.append(msg[512 * i:512 * (i + 1)])
    # 对消息进行迭代
    v = [int2bin(iv, 256)]
    for i in range(n):
        v.append(cf(v[i], b[i]))

    return bin2hex(v[n], 64)


# 对消息进行扩展 将消息分组bi扩展生成132个字W0, W1, · · · , W67, W0', W1', · · · , W63',用于压缩函数CF
# w为68字的list, w1为64字的list
def expand(bi):
    # 将消息分组Bi划分为16个字W0, W1, · · · , W15
    w = []
    for j in range(16):
        w.append(int(bi[j * 32:(j + 1) * 32], 2))

    for j in range(16, 68):
        w_j = p1(w[j - 16] ^ w[j - 9] ^ rotate_left(w[j - 3], 15)) ^ rotate_left(w[j - 13], 7) ^ w[j - 6]
        w.append(w_j)

    w1 = []
    for j in range(64):
        w1.append(w[j] ^ w[j + 4])
    return w, w1


# 压缩函数,压缩后的比特串为256位
def cf(vi, bi):
    # 对bi进行消息扩展
    w, w1 = expand(bi)
    # 将vi拆分为 a~h 8个字 a~h为字寄存器
    t = []
    for i in range(8):
        t.append(int(vi[i * 32:(i + 1) * 32], 2))
    a, b, c, d, e, f, g, h = t
    # ss1,ss2,tt1,tt2为中间变量
    for j in range(64):
        ss1 = rotate_left((rotate_left(a, 12) + e + rotate_left(Tj(j), j)) % MAX, 7)
        ss2 = ss1 ^ rotate_left(a, 12)
        tt1 = (FF(a, b, c, j) + d + ss2 + w1[j]) % MAX
        tt2 = (GG(e, f, g, j) + h + ss1 + w[j]) % MAX
        d = c
        c = rotate_left(b, 9)
        b = a
        a = tt1
        h = g
        g = rotate_left(f, 19)
        f = e
        e = p0(tt2)

    vi_1 = int2bin(a, 32) + int2bin(b, 32) + int2bin(c, 32) + int2bin(d, 32) \
           + int2bin(e, 32) + int2bin(f, 32) + int2bin(g, 32) + int2bin(h, 32)
    vi_1 = int(vi_1, 2) ^ int(vi, 2)

    return int2bin(vi_1, 256)


# 将字符串转化为比特串
def str2bin(msg):
    l = len(msg)
    s_dec = 0
    for m in msg:
        s_dec = s_dec << 8
        s_dec += ord(m)

    msg_bin = bin(s_dec)[2:].zfill(l * 8)
    return msg_bin


# 将整数转化为比特串
def int2bin(a, k):
    return bin(a)[2:].zfill(k)


# 将整数转化为16进制的字符串
def int2hex(a, k):
    return hex(a)[2:].zfill(k)


# 将比特串转化为16进制的字符串
def bin2hex(a, k):
    return hex(int(a, 2))[2:].zfill(k)


# (字)循环左移k比特
def rotate_left(a, k):
    k = k % 32
    return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (32 - k))


# sm3加密
def sm3(msg):
    # 字符串转化为比特串
    s_bin = str2bin(msg)
    # 消息填充
    s_fill = filling(s_bin)
    # 迭代压缩
    s_sm3 = iteration(s_fill)
    return s_sm3


def gb2312_to_quwei(gb2312_str):
    if len(gb2312_str) == 2:
        area_code = gb2312_str[0] - 0xA0
        pos_code = gb2312_str[1] - 0xA0
        quwei_code = area_code * 100 + pos_code
        return f"{quwei_code:04d}"
    else:
        raise ValueError('Input must be a two-byte GB2312 character')


# 将文件中的汉字字符转换为区位码
def process_gb2312_file(file_path):
    quwei_code = ''
    with open(file_path, 'r', encoding='utf-8') as file:
        for line in file:
            line = line.strip()  # 去除行首行尾的空白字符
            for char in line:
                quwei_code += str(unicode_to_quwei(char))
    # print(quwei_code)
    return quwei_code


def unicode_to_gb2312(unicode_str):
    return unicode_str.encode('gb2312')


def unicode_to_quwei(unicode_str):
    gb2312_str = unicode_to_gb2312(unicode_str)
    quwei_code = gb2312_to_quwei(gb2312_str)
    return quwei_code


# 转换文件
def replace_characters(input_string):
    output_string = ""
    for char in input_string:
        if '\u4e00' <= char <= '\u9fff':  # 汉字
            # process_gb2312_file(file_path)
            output_string += str(process_gb2312_file(file_path))
        elif re.match(r'[\w\s]', char):  # 英文字母、数字或空格
            output_string += str(ord(char))
        elif u'\u3000' <= char <= u'\u303F':  # 中文标点
            process_gb2312_file(file_path)
            # output_string += str(process_gb2312_file(file_path))
        else:  # 标点符号
            output_string += str(ord(char))

    return output_string


def process_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        content = file.read()
    return replace_characters(content)


def find_hash():
    R = 0
    found = False
    start_time = time.time()

    while not found:
        hash_input = sm3(sm3(message) + str(R))
        hash_value = int(hash_input, 16)
        print(f"当前的随机数为{R}")
        if hash_value < 2 ** 250:
            end_time = time.time()
            elapsed_time = end_time - start_time

            return R, hash_input, elapsed_time
        R += 1


if __name__ == "__main__":
    file_path = input("请输入文件(路径):")
    file_type = input("请输入文件的类型(1-中文文件;2-英文文件):")
    if file_type == "1":
        result_Chinese = process_gb2312_file(file_path)
        print(f"输入文件为中文文件,转换后的数字字符串为:{result_Chinese}")
        message = result_Chinese
        message_sm3 = sm3(message)
        print(f"该文件的单向散列函数值:{message_sm3}")
    elif file_type == "2":
        result_English = process_file(file_path)
        print(f"输入文件为英文文件,转换后的数字字符串为:{result_English}")
        message = result_English
        message_sm3 = sm3(message)
        print(f"该文件的单向散列函数值:{message_sm3}")
    else:
        print("请重新选择。")
    # 调用函数寻找满足条件的单向散列函数值
    R, hash_output, time_taken = find_hash()

    # 打印结果
    print("对应的随机数:", R)
    print("单向散列函数值:", hash_output)
    print("找到满足要求的函数值的时间:", time_taken, "秒")

此时的输出结果

H(H(M)||R)<2^{256-x}作图展示挖矿成功的时间与x的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Issme

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

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

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

打赏作者

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

抵扣说明:

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

余额充值