密碼學之一(Hash函數)

定義

Hash函數H將可變長度的數據M作爲輸入,產生固定長度的Hash值h。
Hash函數,哈希函數,散列函數,雜湊函數它們說的都是同一個含義,後續我們都稱之爲Hash函數。

h=H(M)

單向性

給定輸入M,通過函數H可以很容易計算出輸出h;但如果給定h,則找到M在計算上不可行。

數據完整性

輸入數據M中任何1個bit發生變化,都將導致輸出M發生很大的變化。

Hash衝突

在Hash函數中,M稱之爲h原像,,因爲H函數是一個多對一的映射,,對於任意給定的Hash數值h,,可能會有多個原像,,如果滿足如下條件, 則稱之爲發生了哈希碰撞,也就是哈希衝突。

x!=yandH(x)==H(y)

一個優良的Hash函數必須滿足如下幾個性質:

  • 任意y,找x,使得H(x) = y,非常困難
  • 給定x1, 找x2, 使得H(x1) == H(x2), 非常困難
  • 找任意的x1, x2, 使得H(x1) == H(x2), 非常困難 生日定理

常用的Hash算法

  • MD5
  • SHA1
  • SHA224
  • SHA256
  • SHA384
  • SHA512
  • SM3

程序

這裏僅做原理性質的描述,因此直接調用庫API。

#!/usr/bin/python
#coding:utf8

import hashlib

def b2s(bytes):
    rets = []
    for c in bytes:
        rets.append("%02X" % (ord(c)))
    r = ' '.join(rets)
    return r

def md5(data):
    hashobj = hashlib.md5()
    hashobj.update(data)
    return hashobj.digest()

def sha1(data):
    hashobj = hashlib.sha1()
    hashobj.update(data)
    return hashobj.digest()

def sha224(data):
    hashobj = hashlib.sha224()
    hashobj.update(data)
    return hashobj.digest()

def sha256(data):
    hashobj = hashlib.sha256()
    hashobj.update(data)
    return hashobj.digest()

def sha384(data):
    hashobj = hashlib.sha384()
    hashobj.update(data)
    return hashobj.digest()

def sha512(data):
    hashobj = hashlib.sha512()
    hashobj.update(data)
    return hashobj.digest()

def main():
    hash_fun_list = (md5, sha1, sha224, sha256, sha384, sha512)
    data = '\x12\x34'

    for fun in hash_fun_list:
        print fun
        r = fun(data)
        print b2s(r)

if __name__ == '__main__':
    main()

輸出如下:

33563489094A0506C237A4965395D61B
FFA76D854A2969E7B9D83868D455512FCE0FD74D
C555719D8ABD5ECB99FB1D0B545448BE34F783632C09E314CA10AFF7
3A103A4E5729AD68C02A678AE39ACCFBC0AE208096437401B7CEAB63CCA0622F
9D27A0B45F3329EBEDDFAA3E99EC9F4C0FF164B86D816F051C2117C6B96F8432BD6B7CBECD13C796AE65FC9E445824F5
4C54886C9821195522D88FF4705C3E0C686B921054421E6EA598739C29C26E1EE75419AACEEC94DD2E3C0DBB82ECF895C9F61215F375DE6D800D9B99D3D4B816

Hash環問題

從一個給定的輸入x0開始,依次計算找到一個環滿足如下條件:

x1=H(x0)

x2=H(x1)

x3=H(x2)

x4=H(x3)

...

x0=H(xn)

以SHA256爲例子, 限定輸入也爲32字節,那麼輸入的集合包含2^32個元素,輸出的集合包含2^32個元素,可以證明這樣的Hash環存在。兩種極端的情況分別是:

  • 2^32個元素構成一個環
  • 一個元素構成一個環,也就是 x0=H(x0)

尋找Hash環的程序,如此大的數學計算面前,計算機何時才能找到呢?

x0 = '\xAB' * 32
x = x0
num = 0
while True:
    x = sha256(x)
    num += 1
    if x == x0:
        print b2s(x)
        break

Hash應用場景

  • 校驗數據的完整性
  • 和簽名函數聯合使用,用於計算輸入數據的簽名
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章