【hash算法设计】信息摘要函数(hash)的设计与验证

信息摘要函数的设计与验证

设计一个类似MD5、RSA的hash函数,构造出一个自己的信息摘要函数

信息摘要函数具有以下的特性:

  • 信息摘要函数具有固定的输出数位
  • 信息摘要函数满足不可求逆,不可伪造和在可行时间之内找不到碰撞等特性
  • 对信息摘要函数进行设计与Hash值的性质验证

比如对于下面的明文信息设计合理的信息摘要函数进行Hash值产生:

Once upon a time, there lived a monkey in the woods. The monkey climbed up the tree and looked down at the river everyday. One day, the monkey saw fishermen throw a net over the river. He watched how the fishermen caught fish. Sometime after, the fishermen left the net and went to have lunch. Then, the monkey climbed down from the tree and went to the riverside. The monkey was planning to throw the net like the fishermen did. The monkey was confident since he was good at imitating. Yet, the net wound around the monkey when he touched it. Tied up in the net, the monkey fell into the water.The monkey regretted his behavior, but it was too late. “I should have learned how to use the net before touching it. After believing my prowess and showing off, I am in a bad fix.” The monkey who did not behave carefully drowned in the water.

要求是:

  1. 随机改变m的任意一位字符,产生新的Hash值,
  2. 如此实验10次,记新的Hash值为 H1,H2,…H10
  3. 设计函数计算H0和Hi 的相似度 i=1,2,…10

我的主要思路:

    我们都知道在底层计算机之中,任何数据都是作为二进制流来存在的,我对于明文进行加密,从某一个角度上来看,就是对二进制流进行规定的操作,不同的文件或者明文的二进制流可能存在相似,因此,单纯的使用二进制流来进行信息摘要认证也不行,因为之前接触过python之中的random.seed函数,使用random函数来生成随机数的时候,每一次生成的数都是随机的,但是如果我们通过使用random.seed来设定好种子之后,那么它得到的随机数确实固定的,根据这一个思路,我们可以利用random来对得到的二进制流进行操作,这样得到的信息认证码在不同明文下有很高的概率保证是不同的,随意改变其中一个会使他的异很大。

    因此重点就是就将明文转为二进制流,再将二进制流打乱,在打乱的过程之中,通过random.seed来给每一次打乱设置定值,这样最后只要明文不变,最后得到的结果就是固定的结果。在这个过程之中我们选取明文的特定字符位置以及其两边的ascii码之和来作为随机种子打乱字符的排序。

    由md5的算法得到启发,在我自己设计的信息摘要函数之中,我将明文选择512来作为二进制明文的公约数,保证二进制长度为512的倍数,然后再打乱多次,其中,每组设定为16个字符,即是四个四位二进制数,然后求出每组四个二进制数的和来作为输出字符的ascii码,其他字符则对ascii码来进行相应的加减,使其符合大小写的字母或者数字。

python程序设计思路:

在这里插入图片描述

python代码:

# encode ano
import math
import random

# change to bin
import string

def encode(s):
    return ''.join([bin(ord(c)).replace('0b', '') for c in s])


def random_int_list(start, stop, length):
    start, stop = (int(start), int(stop)) if start <= stop else (int(stop), int(start))
    length = int(abs(length)) if length else 0
    random_list = []
    for i in range(length):
        random_list.append(random.randint(start, stop))
    return random_list


def read_str(msg):
    '''
        首先计算输入明文信息的ascii码之和,然后根据这个进行
        随机种子设置,在这之中我们将明文转换为二进制,同时传
        为比特串,通过选取首个字符作为ab
    '''
    ascii_sum = 0
    # 计算 ascii 之和
    for char in msg:
        ascii_sum += ord(char)
    # ascii和 * 随机数
    random.seed(msg[0])
    value_1 = ascii_sum * random.random()
    random.seed(value_1)
    msg_list = list(msg)
    random.shuffle(msg_list)
    msg = "".join(msg_list)
    # 明文转为二进制
    b_msg = encode(msg)

    # 明文转为比特串
    by_msg = bytes(msg, encoding='utf-8')

    # 选明文首位字符作为ab

    a = ord(msg[0])
    b = ord(msg[-1])

    return a, b, value_1, msg


def random_all(a, b, y, msg):
    # 椭圆方程
    x = int(math.sqrt(abs((1 - (math.pow(y, 2) / pow(b, 2))) * pow(a, 2))) * 12)
    random.seed(x)

    msg_list = list(msg)
    random.shuffle(msg_list)
    ascii_sum = 0
    for i in range(0, int(len(msg_list) / 2)):
        ascii_sum += ord(msg_list[i])

    random.seed(ascii_sum)
    random.shuffle(msg_list)
    msg = "".join(msg_list)

    return msg


def operate(msg):
    # 将其补全位128位的
    b_msg = encode(msg)
    rst_mod = len(b_msg) % 512
    value = 512 - rst_mod
    random.seed(ord(msg[0]))

    if value != 0:
        r_l = random_int_list(0, 1, value)
        for i in range(0, len(r_l)):
            b_msg += str(r_l[i])

    b_msg = str(b_msg)
    b_msg_l = list(b_msg)
    random.shuffle(b_msg_l)
    b_msg = "".join(b_msg_l)

    times = int(len(b_msg) / 512)

    step = 16 * times
    b_32 = [b_msg[i:i + step] for i in range(0, len(b_msg), step)]

    rst_list = []
    # 将16位数转换得到为4个二进制位的
    for j in range(0, 32):
        for k in range(0, 16, 16):
            rst_1 = int(b_32[j][k]) * pow(2, 3) + int(b_32[j][k + 1]) * pow(2, 2) + int(b_32[j][k + 2]) * pow(2, 1) + \
                    int(b_32[j][k + 3]) * pow(2, 0)
            rst_2 = int(b_32[j][k + 4]) * pow(2, 3) + int(b_32[j][k + 5]) * pow(2, 2) + int(b_32[j][k + 6]) * pow(2, 1) + \
                    int(b_32[j][k + 7]) * pow(2, 0)
            rst_3 = int(b_32[j][k + 8]) * pow(2, 3) + int(b_32[j][k + 9]) * pow(2, 2) + int(b_32[j][k + 10]) * pow(2,1) + \
                    int(b_32[j][k + 11]) * pow(2, 0)
            rst_4 = int(b_32[j][k + 12]) * pow(2, 3) + int(b_32[j][k + 13]) * pow(2, 2) + int(b_32[j][k + 14]) * pow(2,1) + \
                    int(b_32[j][k + 15]) * pow(2, 0)
            rst = rst_1 + rst_2 + rst_3 + rst_4
            rst_list.append(rst)
    return rst_list


def case_case(int_):
    str_ = ""
    if 0 <= int_ <= 9 or 17 <= int_ <= 40:
        str_ = chr(int_ + 48)
    elif 10 <= int_ <= 16:
        str_ = chr(int_ + 100)
    elif 41 <= int_ <= 47:
        str_ = chr(int_ + 56)
    elif 48 <= int_ <= 57 or 65 <= int_ <= 90 or 97 <= int_ <= 122:
        str_ = chr(int_)
    elif 123 <= int_ <= 181:
        str_ = chr(int_ - 58)
    elif 58 <= int_ <= 64:
        str_ = chr(int_ - 10)

    return str_


def judge(rst):
    final_list = []
    for i in range(0, 32):
        fin_str = case_case(rst[i])
        final_list.append(fin_str)

    return final_list


def hash_0_10(msg, i):
    random.seed(i)
    a = random.sample(string.ascii_letters + string.digits, 1)
    b = random.randint(0, len(msg))
    msg_l = list(msg)
    msg_l[b] = a
    msg = "".join(str(msg_l))
    return msg


def Get(msg):
    text_rst = read_str(msg)
    msg_0 = random_all(text_rst[0], text_rst[1], text_rst[2], text_rst[3])
    rst = operate(msg_0)
    m = "".join(judge(rst))
    return m


if __name__ == '__main__':
    msg = input("Input the information : \n")
    m1 = Get(msg)
    print("\n H1: ", m1)


    for i in range(2, 11):
        msg_0 = hash_0_10(msg, i)
        m1 = Get(msg_0)
        print(" H{}: ".format(i), m1) 

加密得到结果:

在这里插入图片描述

与MD5信息摘要算法进行比较相似度:

首先第一张为使用我设计的hash函数进行信息摘要得到结果进行对比的相似度:
在这里插入图片描述
下面这个为使用md5进行信息摘要得到的相似度:
在这里插入图片描述
    从结果上来看,我设计的hash函数进行信息摘要得到的哈希值相似度还是比较低的,从修改明文中不同的一个字符得到10个不同的消息认证码来看,这10个消息认证码相似的程度是非常低的,因此,个人所设计的消息认证摘要算法算是比较成功了。
    经过比较,我可以发现我所设计的消息认证加密函数在该密文且10个不同的消息认证码的情况下比md5的算法要优越,这只是做一个小小的对比,具体算法的比较还需要在生成大量的消息认证码的情况下进行比较。

进行碰撞实验:

在这里插入图片描述
    使用我个人设计信息认证摘要函数进行碰撞计算,发现经过58万多次的计算暂时还未发现有重复的认证码产生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章