HASH函数编程

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

上机三: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.update(psw.encode('utf-8')) #使用md5算法计算

print(md5.hexdigest())#输出16进制字符串

‘a’的Hash值对应‘0cc175b9c0f1b6a831c399e269772661’

让a=‘bujunjie’我的名字hash

看来老师让我们分析分析源码吗?

要分析源码首先搞一下。什么是HASH?

摘要算法是将信息压缩提取以作为数据指纹的算法,我们下载东西要确认下的

东西有没有下错下漏常用这种算法来做验证,在密码学中这是很多算法的基础

具体摘要算法是怎么样的?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符

串表示)

还有一种应用场景是用来存储用户的密码,大明文密码存储在数据库里很不安全,之前爆出很多知名网站将用户密码以明文存储,导致信息泄露.可以通过摘

要算法给密码加个密存储进去.这样要破解密码除了要知道密码本身,还得知道

生成最终摘要文本的算法才可以.也就相对安全多了。

MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、

调整长度、与链接变量进行循环运算。得出结果。

-----------------------------摘自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}

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 = '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]]

return shift_list

# 定义主要的函数,参数为当做种子的列表,每轮用到的F,G,H,I,生成的M[],以及循环左移的位数。该函数完成一轮运算。

def fun(fun_list, f, m, shi):

count = 0

global Ti_count

# 引入全局变量,T(i)是从1到64循环的。

while count < 16:

xx = int(fun_list[0], 16) + f(int(fun_list[1], 16), int(fun_list[2], 16), int(fun_list[3], 16)) + int(m[count],

16) + T(

Ti_count)

xx = xx & 0xffffffff

ll = L(xx, shi[count])

fun_list[0] = hex((int(fun_list[1], 16) + ll) & (0xffffffff))[:-1]

# 最后的[:-1]是为了去除类似'0x12345678L'最后的'L'

fun_list = shift(fun_list)

count += 1

Ti_count += 1

print fun_list

return fun_list

# 该函数生成每轮需要的M[],最后的参数是为了当有很多分组时,进行偏移。

def genM16(order, ascii_list, f_offset):

ii = 0

m16 = [0] * 16

相关文档
最新文档