hashlib — 加密哈希算法
hashlib — 加密哈希算法
1.概述
加密可以保护消息的安全,以便验证它们的准确性并且使它们受保护不被拦截。 Python 的加密方式支持包括利用像 MD5 和 SHA 这样的标准算法对消息内容产生签名的 hashlib 和验证消息没有在传输过程中被改变的 hmac
hashlib 哈希库模块提供了许多哈希算法的 API 支持。哈希算法在中文又被称为散列函数 / 算法,此译文中将统称哈希。想使用具体某一个哈希算法,只需要使用对应的构造函数 new() 来创建对应的哈希对象。不论想使用哪一种具体的哈希算法,在创建哈希对象后的操作均为一致。
2.哈希算法
hashlib 使用开源软件库 OpenSSL 作为底层驱动,因此, hashlib 支持所有 OpenSSL 提供的算法,比如
- md5
- sha1
- sha224
- sha256
- sha384
- sha512
2.1.查看系统支持的算法
具体某一种哈希算法的支持与否取决于操作系统,因为有些哈希算法依赖特定的底层驱动库。查看全平台支持的哈希算法可以使用 algorithms_guaranteed ;查看当前使用平台所支持的哈希算法可使用 algorithms_available
import hashlibprint('Guaranteed:\n{}\n'.format(', '.join(sorted(hashlib.algorithms_guaranteed))))
print('Available:\n{}'.format(', '.join(sorted(hashlib.algorithms_available))))
运行结果
Guaranteed:
blake2b, blake2s, md5, sha1, sha224, sha256, sha384, sha3_224,
sha3_256, sha3_384, sha3_512, sha512, shake_128, shake_256Available:
DSA, DSA-SHA, MD4, MD5, RIPEMD160, SHA, SHA1, SHA224, SHA256,
SHA384, SHA512, blake2b, blake2s, dsaEncryption, dsaWithSHA,
ecdsa-with-SHA1, md4, md5, ripemd160, sha, sha1, sha224, sha256,
sha384, sha3_224, sha3_256, sha3_384, sha3_512, sha512,
shake_128, shake_256, whirlpool
3.MD5算法
3.1.简单的MD5加密
要为一个数据块(这里是一个 unicode 字符串转化成对应的字节串)计算 MD5 哈希值或者 摘要, 首先要创建哈希对象, 然后为这个对象添加数据并且进行 digest() 或者 hexdigest() 调用。
import hashliblorem = '''Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.'''h = hashlib.md5()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())
这个例子使用 hexdigest() 方法而不是使用 digest()。 是因为它的输出是格式化的,可以被清晰的打印出来。如果二进制的摘要值可以接受的话,可以使用 digest()。
3f2fd2c9e25d60fb0fa5d593b802b7a8
4.SHA1 算法
4.1.简单的例子
一个 SHA1 摘要是以相似的方式计算出来的
import hashliblorem = '''Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.'''h = hashlib.sha1()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())
在这个例子中,摘要值与上面的例子不一样,因为算法从 MD5 换成了 SHA1
ea360b288b3dd178fe2625f55b2959bf1dba6eef
5.使用名字创建哈希
有时通过字符串对算法进行引用比直接使用构造函数更加方便。例如,这样可以将哈希类型直接写入配置文件中,这是很方便的。在这种情况下,使用 new() 去创建一个哈希计算器。
import argparse
import hashlib
import syslorem = '''Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.'''parser = argparse.ArgumentParser('hashlib demo')
parser.add_argument('hash_name',choices=hashlib.algorithms_available,help='the name of the hash algorithm to use',
)
parser.add_argument('data',nargs='?',default=lorem,help='the input data to hash, defaults to lorem ipsum',
)
args = parser.parse_args()h = hashlib.new(args.hash_name)
h.update(args.data.encode('utf-8'))
print(h.hexdigest())
6.增量更新
哈希计算器中的 update() 方法可以被重复调用。 每一次调用摘要都会根据额外的文字进行更新。增量更新比起读取整个文件进入内存中更加有效率,并且参数的结果是相同的
import hashlibfrom hashlib_data import loremh = hashlib.md5()
h.update(lorem.encode('utf-8'))
all_at_once = h.hexdigest()def chunkize(size, text):"Return parts of the text in size-based increments."start = 0while start < len(text):chunk = text[start:start + size]yield chunkstart += sizereturnh = hashlib.md5()
for chunk in chunkize(64, lorem.encode('utf-8')):h.update(chunk)
line_by_line = h.hexdigest()print('All at once :', all_at_once)
print('Line by line:', line_by_line)
print('Same :', (all_at_once == line_by_line))
这个例子演示了如何在读取或以其他方式生成数据时增量更新摘要
All at once : 3f2fd2c9e25d60fb0fa5d593b802b7a8
Line by line: 3f2fd2c9e25d60fb0fa5d593b802b7a8
Same : True