Python 哈希函数与消息认证实验
目录前言一、计算哈希值和消息认证1.引入库2.实现二、哈希函数的雪崩效应实现三、暴力破解MD51.引入库2.实现总结前言提示:测试运行环境为 python3.7.5,IDE为Pycharm2020.1,文章包含三道题,分别是:1.计算哈希值和消息认证;2.哈希函数的雪崩效应;3.暴力破解MD5。复制过去的源码可能要改一下输出格式嗷。一、计算哈希值和消息认证题目描述:编写一个能计算文本MD5、SHA
前言
提示:测试运行环境为 python3.7.5,IDE为Pycharm2020.1,文章包含三道题,分别是:1.计算哈希值和消息认证;2.哈希函数的雪崩效应;3.暴力破解MD5。复制过去的源码可能要改一下输出格式嗷。
一、计算哈希值和消息认证
题目描述:编写一个能计算文本MD5、SHA512和hmac的程序。
1.引入库
代码如下:
import hashlib
import hmac
from hashlib import md5, sha256, sha512
关于库的使用可见官方文档:
hmac — 基于密钥的消息验证
hashlib — 安全哈希与消息摘要
2.实现
实现–版本一:
# 一开始写的,为了过实验的版本
import hashlib
import hmac
from hashlib import md5, sha256, sha512
def myhash(str):
res = hashlib.md5(str.encode(encoding="utf-8"))
print(res.hexdigest())
def myhmac(key, str, mode):
# param key:计算消息验证码的用到的密钥
# param str:计算消息验证码的字符串
# param mode: 使用的哈希函数
key = key.encode(encoding="utf-8")
str = str.encode(encoding="utf-8")
if mode == 'md5':
my_hmac = hmac.new(key, str, digestmod=md5)
res1 = sha512(str)
print(res1.hexdigest())
print(my_hmac.hexdigest())
elif mode == 'sha256':
res1 = sha512(str)
print(res1.hexdigest())
my_hmac = hmac.new(key, str, digestmod=sha256)
print(my_hmac.hexdigest())
elif mode == 'sha512':
res1 = sha512(str)
print(res1.hexdigest())
my_hmac = hmac.new(key, str, digestmod=sha512)
print(my_hmac.hexdigest())
if __name__ == "__main__":
str = input()
key = input()
mode = input()
myhash(str)
myhmac(key, str, mode)
那会为了过实验,写的又臭又长,不美观也不好读,也就是实现个功能罢了,于是又跑去参考了BossXie同学的代码,看完之后直呼666,简洁得不像话,于是我也大致照着思路又写了一个改良版:
# 改良版
import hashlib
import hmac
from hashlib import md5, sha256, sha512
def myhash(str):
res = hashlib.md5(str.encode(encoding="utf-8"))
print("md5: " + res.hexdigest())
def myhmac(key, str, mode):
# param key:计算消息验证码的用到的密钥
# param str:计算消息验证码的字符串
# param mode: 使用的哈希函数
key = key.encode(encoding="utf-8")
str = str.encode(encoding="utf-8")
my_hmac = hmac.new(key, str, mode)
res1 = sha512(str)
print("sha512 " + res1.hexdigest())
print("hmac: " + my_hmac.hexdigest())
if __name__ == "__main__":
str = input()
key = input()
mode = input()
myhash(str)
myhmac(key, str, mode)
测试一下结果:
看着确实是要舒服很多呀~
二、哈希函数的雪崩效应
题目描述:编写一个能验证哈希函数MD5雪崩效应的程序。
(偷偷吐槽:这道题应该是本次实验最烦人的了,虽然说写完之后确实感觉不难,但是题目的提示真的太少了!可以查的资料也不多,是比较难写的,当然也可能是我太菜了)
实现
代码如下:
import hashlib
def encode(s):
return ' '.join([bin(ord(c)).replace('0b', '') for c in s])
def decode(s):
return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]])
# 该函数用于计算两个字符串不同的位数
def cmpcount(str1, str2):
count = 0
for i in range(0, len(str1)):
times += 1
if str1[i] != str2[i]:
count += 1
return count
def avalanche(str, nbyte, mbit):
# param str:计算哈希值的字符串
# param nbyte:str的第几个字节(从低位到高位数)
# parem mbit: nbyte的第几个bit位(从低位到高位数)
h1 = hashlib.md5(str.encode(encoding="utf-8")) # 获取原字符串的MD5
h1 = h1.hexdigest()
nbyte_place = len(str) - nbyte # 获取目标字节所在位置
nbytes = str[nbyte_place] # 获取目标字节
nbyte_str = encode(nbytes) # 目标字节转换为二进制
mbit_place = len(nbyte_str) - mbit # 获取目标bit位置,第一次调试出错点
mbits = nbyte_str[mbit_place] # 获取目标bit
# bit位翻转+字节二进制还原
if mbits == '0':
nbyte_str = nbyte_str[:mbit_place] + '1' + nbyte_str[mbit_place+1:]
elif mbits == '1':
nbyte_str = nbyte_str[:mbit_place] + '0' + nbyte_str[mbit_place+1:]
nbyte_str = decode(nbyte_str) # 获取修改后的字节
str1 = str[:nbyte_place] + nbyte_str + str[nbyte_place+1:] # 获取修改后的字符串
print("str1: " + str1)
h2 = hashlib.md5(str1.encode(encoding="utf-8"))
h2 = h2.hexdigest()
h1 = bin(int(h1, 16))[2:]
h2 = bin(int(h2, 16))[2:]
if len(h1) != 128:
h1 = h1.zfill(128)
else:
pass
if len(h2) != 128:
h2 = h2.zfill(128)
else:
pass
print("h1: " + h1)
print("h2: " + h2)
cout_different = cmpcount(h1, h2)
print(cout_different)
# 测试:python 2 1
if __name__ == "__main__":
str, nbyte, mbit = input().split()
nbyte = int(nbyte)
mbit = int(mbit)
avalanche(str, nbyte, mbit)
本题用到的库比第一题少一些,所以就省略了引用库环节,说一下本题的注意事项:
1.字节是按照从低位数排列的,比如 ‘python’ 中的的第一个字节为 ‘n’,第二个字节为 ‘o’,bit位也是按照这样的方式排列的。
2.若是md5加密后的二进制字符串长度不足128位,则需要使用 zfill 函数函数进行补齐,使用方法为str.zfill(lenth),lenth 为需要填充到的位数,本题需要128位,也就是 str.zfill(128)。
3.二进制和字符串之间的相互转换是参照了一位博主的代码,写的很非常nice!看着很简洁就搬到了本程序中。
其他的基本都写在注释里啦,不懂的话欢迎评论区讨论喔~
三、暴力破解MD5
题目描述:编写一个能破解md5的程序
感觉描述的很简洁,我来补充一点点,输入一个字符串,对该字符串进行md5加密,再通过字母、数字、字符的全排列来对照密文,最终得到加密之前的字符串,差不多就是这个意思啦。
1.引入库
代码如下:
from hashlib import md5
from string import ascii_letters, digits, punctuation # 用string模块获得字母、数字和字符
from itertools import permutations # 用于全排列
用法其实很简单的,待会看代码就知道了,注释也有写的,所以就不多赘述啦
2.实现
代码如下:
# 哈希函数的雪崩效应
# author:marxycj
# date:2021-10-29
from hashlib import md5
from string import ascii_letters, digits, punctuation # 用string模块获得字母、数字和字符
from itertools import permutations # 用于全排列
def brute_md5(md5_value):
if len(md5_value) != 32:
print("不是有效的md5值")
return
else:
allkind = ascii_letters + digits + punctuation
for i in range(5, 10):
for j in permutations(allkind, i):
md5_test = ''.join(j)
md5_testmd5 = md5(md5_test.encode(encoding="utf-8"))
md5_testhex = md5_testmd5.hexdigest()
if md5_testhex == md5_value:
print(md5_test)
return
if __name__ == '__main__':
md5_value = input()
brute_md5(md5_value)
解释一下,allkind就是 字母、数字、字符的组合啦,把三种类型加起来, md5_test用来接收全排列字符串然后进行md5暴力破解测试的,或许叫md5_try合适些,别的也没有啥要注意的啦~
总结
总结:
可能写代码的时候自己写的不快,也不如别人写的好,写的整洁,但是最好还是自己写一遍,毕竟是自己的思路,写完之后再去对照大佬的进行修改,这样或许可以更好地提升自己的代码能力,没有经过思考就照搬代码,能学的东西就比较有限,愿脚踏实地,不骄不躁。
更多推荐
所有评论(0)