欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python计算文件或字符串的MD5/SHA

程序员文章站 2022-05-12 22:16:01
...

本文章讲如何通过Python实现计算文件或字符串的MD5, SHA1, SHA224, SHA256, SHA384, SHA512值。
原文:https://blog.zeruns.tech/archives/582.html
Python计算文件或字符串的MD5/SHA

MD5算法

MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位的散列值(hash value),用于确保信息传输完整一致。MD5的前身有MD2、MD3和MD4。

MD5功能

输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);

不同的输入得到的不同的结果(唯一性);

MD5算法的特点

  1. 压缩性:任意长度的数据,算出的MD5值的长度都是固定的
  2. 容易计算:从原数据计算出MD5值很容易
  3. 抗修改性:对原数据进行任何改动,修改一个字节生成的MD5值区别也会很大
  4. 强抗碰撞:已知原数据和MD5,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

MD5算法是否可逆?

MD5不可逆的原因是其是一种散列函数,使用的是hash算法,在计算过程中原文的部分信息是丢失了的。

MD5用途

  1. 防止被篡改:
  • 比如发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。如果a与b一样就代表中途未被篡改。
  • 比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。
  • SVN在检测文件是否在CheckOut后被修改过,也是用到了MD5.
  1. 防止直接看到明文:
  • 现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码。(比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被**的难度。)
  1. 防止抵赖(数字签名):
  • 这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”。

SHA-1

安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。

SHA是美国国家安全局设计的,由美国国家标准和技术研究院发布的一系列密码散列函数。

由于MD5和SHA-1于2005年被山东大学的教授王小云**了,科学家们又推出了SHA224, SHA256, SHA384, SHA512,当然位数越长,**难度越大,但同时生成加密的消息摘要所耗时间也更长。目前最流行的是加密算法是SHA-256 .

程序源码

摘要算法模块使用教程:https://blog.zeruns.tech/archives/581.html#摘要算法模块%20hashlib

源码下载:https://gist.github.com/zeruns/015317b1ddac1957b8d5ee3afad4ba90

# Python计算字符串或文件的MD5/SHA值
import time
import os
import hashlib


# 计算文件的MD5/SHA值
def file(path, algorithm):
    global start, end  # 声明全局变量
    start = time.time()  # 获取当前时间,用于记录计算过程的耗时
    size = os.path.getsize(path)  # 获取文件大小,单位是字节(byte)
    with open(path, 'rb') as f:  # 以二进制模式读取文件
        while size >= 1024 * 1024:  # 当文件大于1MB时将文件分块读取
            algorithm.update(f.read(1024 * 1024))
            size -= 1024 * 1024
        algorithm.update(f.read())
    end = time.time()  # 获取计算结束后的时间
    print()
    print(algorithm.hexdigest())  # 输出计算结果


# 计算字符串的MD5/SHA值
def str(text, algorithm):
    global start, end
    start = time.time()
    algorithm.update(text.encode(encoding='UTF-8'))
    end = time.time()
    print()
    print(algorithm.hexdigest())

print('https://blog.zeruns.tech')
print('1.MD5  2.SHA1 3.SHA224 4.SHA256 5.SHA384 6.SHA512')
flag1 = int(input('请选择算法:'))
print('\n1.文件 2.字符串')
flag2 = int(input('请选择要计算的是文件还是字符串:'))
if flag2 == 1:
    path = input('\n请输入要计算的文件的目录(若跟脚本同目录直接输入文件名即可):')
    if flag1 == 1:
        file(path, hashlib.md5())
    elif flag1 == 2:
        file(path, hashlib.sha1())
    elif flag1 == 3:
        file(path, hashlib.sha224())
    elif flag1 == 4:
        file(path, hashlib.sha256())
    elif flag1 == 5:
        file(path, hashlib.sha384())
    elif flag1 == 6:
        file(path, hashlib.sha512())
elif flag2 == 2:
    text = input('\n请输入要加密的字符串:')
    if flag1 == 1:
        str(text, hashlib.md5())
    elif flag1 == 2:
        str(text, hashlib.sha1())
    elif flag1 == 3:
        str(text, hashlib.sha224())
    elif flag1 == 4:
        str(text, hashlib.sha256())
    elif flag1 == 5:
        str(text, hashlib.sha384())
    elif flag1 == 6:
        str(text, hashlib.sha512())

print("\n计算耗时: %s seconds" % (end - start))

推荐阅读