【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萬多次的計算暫時還未發現有重複的認證碼產生。

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