系列索引:【图解安全加密算法】加密算法系列索引 Python保姆级实现教程 | 物联网安全 | 信息安全

起初写实验时找到的代码大多基于c/c++,python可参考的资料很少,所以借着这次实验的机会把自己走过坑分享一下,希望对大家有所帮助!

文章目录

  • 一、什么是SHA1
  • 二、SHA1哈希算法流程
  • 三、具体实现过程(附代码)
    • (1)消息填充
    • (2)分割已填充消息
    • (3)设置初始散列值
    • (4)16份子明文分组扩展为80份
    • (5)SHA1的4轮运算
  • 四、跟着demo去debug
  • 五、完整代码

一、什么是SHA1

SHA-1是一种数据加密算法,该算法的思维是接纳一段明文,然后以一种不可逆的方式将它转换成一段(一般更小)密文,也能够简略的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为摘要信息或信息认证代码)的过程

二、SHA1哈希算法流程

对于任意长度的明文,SHA1首先对其进行分组,使得每一组的长度为512位,然后对这些明文分组反复重复处理。
每个明文分组的摘要生成过程如下:

(1) 将512位的明文分组划分为16个子明文分组,每个子明文分组为32位。
(2) 申请5个32位的链接变量,记为A、B、C、D、E。
(3) 16份子明文分组扩展为80份。
(4) 80份子明文分组进行4轮运算
(5) 链接变量与初始链接变量进行求和运算
(6) 链接变量作为下一个明文分组的输入重复进行以上操作。
(7) 最后,5个链接变量里面的数据就是SHA1摘要。

三、具体实现过程(附代码)

在进行散列值计算之前,先要对需要加密的数据进行预处理。这一预处理由三部分组成:消息填充、分割已填充消息(将填充后的消息等分成m位处理块)、为散列值计算设置初始化值。

(1)消息填充

假设原始消息(M)的长度是L位。首先,在消息最后加一位“1”,接着在这位“1”后面补k个“0”,使得L+1+k(即补位后的消息长度)满足对512取模后余数是448。然后,添加最后的64位二进制数据,这64位二进制数据就是原始L位消息(M)长度的二进制表示。

flag = 1  # 补1标志位,补一次1后置0
while len(M) % 512 != 448: #M是未补位的二进制串(字符串类型)if flag:M += '1'flag = 0else:M += '0'
M += "{:064b}".format(l)  # 末尾64位写入长度,空余补位补0
M = hex(int(M, 2))[2:]  # 这种转换会用到很多次,2进制转16进制,M现在是一个16进制字符串,如'1342a2c12...'

补位后如下:

(2)分割已填充消息

经过消息填充后,还必须将数据划分成m位一组的N块的数据块来提供给下面的散列值计算过程。对于SHA-1加密算法,填充过的消息被分割成N(M(1),M(2),…,M(N))块,每块512位。(其长度正好为512位的整数倍,然后按512位的长度进行分组(block))然后每组512位的输入块可以表示成16个32位的字,分别记为:M0(i),M1(i),…,M15(i)。

Mn = []  # 存储每个32位的字,因为M中一个字符4位(16进制),
#所以取M中的8个为一组,按要求将M分割成16个32位的字,故这里8*4=32,32*16=512
for i in range(16):Mn.append(M[8*i: 8*i+8])

(3)设置初始散列值

初始散列值由下面5个32位的字组成,其16进制表示如下:
A=0x67452301,B=0xEFCDAB89,C=0x98BADCFE,D=0x10325476,E=0xC3D2E1F0。

(4)16份子明文分组扩展为80份

将这16份子明文分组扩充到80份子明文分组,我们记为W[k](k= 0, 1,……79),扩充的方法如下。
Wt = Mt , 当0≤t≤15
Wt = (Wt-3⊕Wt-8⊕ Wt-14⊕Wt-16) <<< 1, 当16≤t≤79

W = ['' for _ in range(80)]  # 存储80份扩展子明文
for i in range(80):if 16 <= i <= 79:# 16-79要进行异或运算,这里先转换成十进制(W中存的是16进制字符串,str无法运算)temp = int(W[i-3], 16) ^ int(W[i-8],16) ^ int(W[i-14], 16) ^ int(W[i-16], 16)W[i] = hex(roll_left(temp, 1))[2:].zfill(8)  # 循环左移1位else:W[i] = Mn[i]

(5)SHA1的4轮运算

SHA1有4轮运算,每一轮包括20个步骤,一共80步(对应扩展后的80个W[t]),当第1轮运算中的第1步骤开始处理时,A、B、C、D、E五个链接变量中的值先赋值到另外5个记录单元A′,B′,C′,D′,E′中。这5个值将保留,用于在第4轮的最后一个步骤完成之后与链接变量A,B,C,D,E进行求和操作。

SHA1的4轮运算,共80个步骤使用同一个操作程序,如下:

A,B,C,D,E←[(A<<<5)+ ft(B,C,D)+E+Wt+Kt],A,(B<<<30),C,D

其中 ft(B,C,D)为逻辑函数,Wt为子明文分组W[t],Kt为固定常数。
这个操作程序的意义为:
● 将[(A<<<5)+ ft(B,C,D)+E+Wt+Kt]的结果赋值给链接变量A;
● 将链接变量A初始值赋值给链接变量B;
● 将链接变量B初始值循环左移30位赋值给链接变量C;
● 将链接变量C初始值赋值给链接变量D;
● 将链接变量D初始值赋值给链接变量E。

Ap, Bp, Cp, Dp, Ep = A, B, C, D, E  # 暂存初始值
for t in range(80):tmp = BB = AA = ((((E + ft(tmp, C, D, t)) % (2**32)+roll_left(A, 5)) %(2**32)+int(W[t], 16)) % (2**32)+K[t//20]) % (2**32)  # 预防溢出进行取模运算E = DD = CC = roll_left(tmp, 30)

SHA1规定4轮运算的逻辑函数如表

def ft(b, c, d, t):"""ft为逻辑函数Parameters----------b : intB值c : intC值d : intD值t : int轮次Returns-------int运算结果"""if t >= 0 and t <= 19:return ((b & c) | (~b & d))elif t >= 20 and t <= 39:return (b ^ c ^ d)elif t >= 40 and t <= 59:return ((b & c) | (b & d) | (d & c))elif t >= 60 and t <= 79:return (b ^ c ^ d)


SHA1的常数K取值表

四、跟着demo去debug

这里使用’abc’进行测试,包括各个步骤的结果,供大家debug使用








这里将最后一轮(79轮)的结果与初始值相加。

五、完整代码

代码已补充,不足之处大佬见谅,还有很对待完善之处,欢迎大家批评指正!

import randomA, B, C, D, E = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0  # 常量
K = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]  # 常量str = input("输入明文:\n").encode('utf-8')  # 这里对输入明文进行编码,str为bytes型
l = len(str)*8  # 每个字符8位
# python中二进制是字符串,不保留高位的0,这里使用zfill补高位0,如十进制6->110->0110,M这里是用了一个很长的字符串如:'11001010100011...'来表示原始数据
M = bin(int(str.hex(), 16))[2:].zfill(l)# [可选项] 下面的函数仅仅显示输入明文的ascii,末尾为长度,该段显示的是补位后的
for i in range(64):if i < len(str):print(str[i], end=' ')elif i < len(str)+1:print('128', end=' ')elif i < 63:print('0', end=' ')else:print(l)flag = 1  # 补1标志位,补一次1后置0
while len(M) % 512 != 448:if flag:M += '1'flag = 0else:M += '0'
M += "{:064b}".format(l)  # 末尾64位写入长度,空余补位补0
M = hex(int(M, 2))[2:]  # 这种转换会用到很多次,2进制转16进制,M现在是一个16进制字符串,如'1342a2c12...'
Mn = []  # 存储每个32位的字,因为M中一个字符4位(16进制),所以取M中的8个为一组,按要求将M分割成16个32位的字,故这里8*4=32,32*16=512
for i in range(16):Mn.append(M[8*i: 8*i+8])def roll_left(num, k):"""循环左移函数Parameters----------num : int输入一个数字,2进制、10进制等均可k : int左移位数Returns-------int返回一个int结果"""num_bin = bin(num)[2:].zfill(32)  # 因为python高位不会自动补0,导致要手动调整(也可能是我学艺不精),不然会忽略高位的0循环左移out = num_bin[k % len(num_bin):]+num_bin[:k % len(num_bin)]  # 注意预防溢出return int(out, 2)  # 二进制左移完成后转化成10进制输出W = ['' for _ in range(80)]  # 存储80份扩展子明文
for i in range(80):if 16 <= i <= 79:# 16-79要进行异或运算,这里先转换成十进制(W中存的是16进制字符串,str无法运算)temp = int(W[i-3], 16) ^ int(W[i-8],16) ^ int(W[i-14], 16) ^ int(W[i-16], 16)W[i] = hex(roll_left(temp, 1))[2:].zfill(8)  # 循环左移1位else:W[i] = Mn[i]def ft(b, c, d, t):"""ft为逻辑函数Parameters----------b : intB值c : intC值d : intD值t : int轮次Returns-------int运算结果"""if t >= 0 and t <= 19:return ((b & c) | (~b & d))elif t >= 20 and t <= 39:return (b ^ c ^ d)elif t >= 40 and t <= 59:return ((b & c) | (b & d) | (d & c))elif t >= 60 and t <= 79:return (b ^ c ^ d)Ap, Bp, Cp, Dp, Ep = A, B, C, D, E  # 暂存初始值
for t in range(80):tmp = BB = AA = ((((E + ft(tmp, C, D, t)) % (2**32)+roll_left(A, 5)) %(2**32)+int(W[t], 16)) % (2**32)+K[t//20]) % (2**32)  # 预防溢出进行取模运算E = DD = CC = roll_left(tmp, 30)#print(f" round{t+1} : {hex(A)} {hex(B)} {hex(C)} {hex(D)} {hex(E)}\n")
A, B, C, D, E = (Ap+A) % (2**32), (Bp+B) % (2**32), (Cp +C) % (2**32), (Dp+D) % (2**32), (Ep+E) % (2**32)
# 相加运算,因为python不像c/c++可以使用unsigned char_32直接限制位数,因此要对位数进行限制
print("明文对应的杂凑码:\n", hex(A), hex(B), hex(C), hex(D), hex(E))

图解安全加密算法系列持续更新,欢迎点赞收藏关注

上一篇:【图解DSA数字签名算法】DSA签名算法的Python实现 | 物联网安全 | 信息安全
下一篇:【图解RSA加密算法】RSA非对称密码算法的Python实现保姆级教程 | 物联网安全 | 信息安全

本人水平有限,文章中不足之处欢迎下方

【图解SHA1杂凑算法】SHA1杂凑算法的Python实现保姆级教程 | 物联网安全 | 信息安全相关推荐

  1. 目标检测算法——YOLOv7训练自己的数据集(保姆级教程)

    >>>深度学习Tricks,第一时间送达<<< 目录 YOLOv7训练自己的数据集(保姆级教程): 一.YOLOv7源代码下载 二.安装深度学习环境 三.准备自己的 ...

  2. centos的官网下载和vm16虚拟机安装centos8【保姆级教程图解】

    centos8的官网下载和vm16虚拟机安装centos8[保姆级图解] centos下载 vm虚拟机安装centos 可能出现的问题vcpu-0 centos下载 centos官网:https:// ...

  3. (二)深入浅出图解Git,入门到精通(保姆级教程)

    上一篇原创写了图解Git的第一篇,个人感觉还是可以,比较基础的那种,有兴趣的可以看一看[],这一篇我们继续图解Git,上一篇基本就是基础,这一篇算是进阶. 分支管理 Git中比较最重要的一点就是分支的 ...

  4. (一)深入浅出图解Git,入门到精通(保姆级教程)

    Git简介 在我们的认知范围Git和SVN都是对于代码托管的工具,那么这两者又有什么不同呢? Git是世界上先进的「分布式的版本控制系统」,而SVN是「集中式的版本控制系统」,SVN对于版本的管理集中 ...

  5. 保姆级教程:图解Transformer

    本文 GitHub https://github.com/Jack-Cherish/PythonPark 已收录,有技术干货文章,整理的学习资料,一线大厂面试经验分享等,欢迎 Star 和 完善. 一 ...

  6. git merge 冲突_更新了!深入浅出图解Git,入门到精通(保姆级教程)第三篇

    原文链接:https://mp.weixin.qq.com/s/d7YwRi1mEkxUSUqxWD_B1Q 这一篇写完基本Git的操作就图解完了,如果想深入了解Git,这里可以推荐一些Git的硬核书 ...

  7. Ubuntu-KCF/DSST算法无人机跟踪仿真/实物保姆级教程

    KCF算法无人机跟踪 介绍 自己搭建的无人机跟踪实验,主要讲软件,硬件的需要等等 基础知识准备 整个系统需要两部分,识别程序和控制无人机运动的程序,都是Python脚本,但运行需要在Ubuntu下用R ...

  8. 保姆级教程:硬核图解Transformer

    一.前言 今天的主角是 Transformer. Transformer 可以做很多有趣而又有意义的事情. 比如 OpenAI 的 DALL·E,可以魔法一般地按照自然语言文字描述直接生成对应图片! ...

  9. 树种优化算法(Tree seed algorithm(TSA)) 原理+代码(逐字逐句)+思考 保姆级教程

    一,介绍: TSA树种优化算法(TSA),是一种新型的演化算法,该算法是模拟大树通过种子进行繁衍的过程.Kiran在2015年提出了TSA算法.以下就是套话,该算法的收敛速度快,收敛精度高,等等... ...

最新文章

  1. 自动化运维工具Ansible
  2. 还有:用VB创建Excel报表
  3. ubuntu apt-mirror 同步源到本地
  4. 把 LiveData 用于事件传递那些坑
  5. Day 06 元组,字典,集合
  6. 第二阶段站立会议08
  7. axios的数据请求方式及跨域
  8. tos重装mysql_云服务器(腾讯云)从零开始部署记录(3)之mysql5.7安装
  9. 使用Nodejs搭建server
  10. Android的MediaPlayer架构介绍
  11. 深度学习2.0-31.CIFAR100与VGG13实战
  12. response.sendRedirect 报 java.lang.IllegalStateException 异常的解决思路
  13. 卸载oracle 10g
  14. 【零基础一起学习FPS游戏Unity3D手机游戏开发】第1章 准备工作
  15. 工业互联网的内涵及其应用
  16. 微软2016校园招聘4月在线笔试 总结
  17. qq2007服务器中断,自动重启pubwin2007服务器脚本
  18. 用来判断当前python语句在分支结构中是_【单选题】哪个选项是用来判断当前 Python 语句在分支结构中?...
  19. 用vue简单写一个音乐播放器
  20. 主机电源全是黑线怎么短接_电脑电源故障 绿线和黑线短接后风扇转一下就停了。...

热门文章

  1. 新浪分享 Insufficient app permissions!
  2. 世界名画陈列馆问题(不重复监视)
  3. 朴素贝叶斯分类的原理与流程——转张洋
  4. 扇贝编程python学习笔记-基础篇10
  5. Android窗口机制:六、一定要在主线程才可以更新UI吗?为什么?(源码版本SDK31)
  6. 奶爸日记14 - 记性
  7. python autosub_基于Python3(Autosub)以及Ffmpeg配合GoogleTranslation(谷歌翻译)为你的影片实现双语版字幕(逐字稿)...
  8. vue实现购物车(简单)
  9. window.scrollTo滚动条滚动速度 滚动到指定距离
  10. Python中的魔幻语法记录