上机三:HASH函数编程
【上机目的】
熟悉HASH函数的基本原理和性质,通过编程/开源代码分析了解一种标准HASH算法的运行原理。
【上机环境】
1、硬件 PC机一台。
2、系统配置:操作系统windows XP以上。
3、编程语言:C/C++/C#/Java/Python
【上机内容及要求】
1、MD5算法分析和实现
2、使用实例分析
备注:可借鉴网上相关算法的开源代码进行编程实现,编程语言不限;除了MD5算法,也可以选取SHA系列HASH算法(或其它任一种标准的HASH算法)进行研究。
【上机报告】
实验过程:
Python遇到Hash,内置的函数库就可以解决,但要是想理解算法与原理。还是要走一边流程。
Python hash库的应用
import hashlib
psw="a"
md5 = hashlib.md5() #初始化摘要对象
md5.de('utf-8')) #使用md5算法计算print(md5.hexdigest())#输出16进制字符串
‘a’的Hash值对应‘0cc175b9c0f1b6a831c399e269772661’
让a=‘bujunjie’我的名字hash
看来老师让我们分析分析源码吗?
要分析源码首先搞一下。什么是HASH?
摘要算法是将信息压缩提取以作为数据指纹的算法,我们下载东西要确认下的东西有没有下错下漏常用这种算法来做验证,在密码学中这是很多算法的基础
具体摘要算法是怎么样的?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)
还有一种应用场景是用来存储用户的密码,大明文密码存储在数据库里很不安全,之前爆出很多知名网站将用户密码以明文存储,导致信息泄露.可以通过摘要算法给密码加个密存储进去.这样要破解密码除了要知道密码本身,还得知道生成最终摘要文本的算法才可以.也就相对安全多了。
MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
{\displaystyle \oplus ,\wedge ,\vee ,\neg } 
-----------------------------摘自wiki百科
//Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating
var int[64] r, k
//r specifies the per-round shift amounts
r[ 0..15]= {7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22}
r[16..31]= {5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20}
r[32..47]= {4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23}
r[48..63]= {6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21}
//Use binary integer part of the sines of integers as constants:
for i from 0 to 63
    k[i] := floor(abs(sin(i + 1)) × 2^32)
//Initialize variables:
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476
//Pre-processing:
append "1" bit to message
append "0" bits until message length in bits 448 (mod 512)
append bit length of message as 64-bit little-endian integer to message
//Process the message in successive 512-bit chunks:
for each 512-bit chunk of message
    break chunk into sixteen 32-bit little-endian words w[i], 0 i 15
    //Initialize hash value for this chunk:
    var int a := h0
    var int b := h1
    var int c := h2
    var int d := h3
    //Main loop:
    for i from 0 to 63
        if 0 i 15 then
            f := (b and c) or ((not b) and d)
            g := i
        else if 16 i 31
            f := (d and b) or ((not d) and c)
            g := (5×i + 1) mod 16
        else if 32 i 47
            f := b xor c xor d
            g := (3×i + 5) mod 16
        else if 48 i 63
            f := c xor (b or (not d))
            g := (7×i) mod 16
        temp := d
        d := c
        c := b
        b := leftrotate((a + f + k[i] + w[g]),r[i]) + b
        a := temp
    Next i
    //Add this chunk's hash to result so far:
    h0 := h0 + a
    h1 := h1 + b
    h2 := h2 + c
    h3 := h3 + d
End ForEach
var int digest := h0 append h1 append h2 append h3 //(expressed as little-endian)
wiki的伪代码。大概的意思就是经过64次运算,在经过4轮,然后将32位的加起来。
# codeing=utf-8
# 引入math模块,因为要用到sin函数
import math
# 定义常量,用于初始化128位变量,注意字节顺序,文中的A=0x01234567,这里低值存放低字节,即01 23 45 67,所以运算时A=0x67452301,其他类似。
# 这里用字符串的形势,是为了和hex函数的输出统一,hex(10)输出为'0xA',注意结果为字符串。
A = '0x67452301'
B = 字符串长度1是什么意思'0xefcdab89'
C = '0x98badcfe'
D = '0x10325476'
# 定义每轮中用到的函数。L为循环左移,注意左移之后可能会超过32位,所以要和0xffffffff做与运算,确保结果为32位。
F = lambda x, y, z: ((x & y) | ((~x) & z))
G = lambda x, y, z: ((x & z) | (y & (~z)))
H = lambda x, y, z: (x ^ y ^ z)
I = lambda x, y, z: (y ^ (x | (~z)))
L = lambda x, n: (((x << n) | (x >> (32 - n))) & (0xffffffff))
# 定义每轮中循环左移的位数,这里用4个元组表示,用元组是因为速度比列表快。
shi_1 = (7, 12, 17, 22) * 4
shi_2 = (5, 9, 14, 20) * 4
shi_3 = (4, 11, 16, 23) * 4
shi_4 = (6, 10, 15, 21) * 4
# 定义每轮中用到的M[i]次序。
m_1 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
m_2 = (1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12)
m_3 = (5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2)
m_4 = (0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9)
# 定义函数,用来产生常数T[i],常数有可能超过32位,同样需要&0xffffffff操作。注意返回的是十进制的数。
def T(i):
    result = (int(4294967296 * abs(math.sin(i)))) & 0xffffffff
    return result
# 定义函数,用来将列表中的元素循环右移。原因是在每轮操作中,先运算A的值,然后是D,C,B,16轮之后右恢复原来顺序,所以只要每次操作第一个元素即可。
def shift(shift_list):
    shift_list = [shift_list[3], shift_list[0], shift_list[1], shift_list[2]]

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。