Skip to content

加密有关模块

hashlib 模块

内置模块hashlib提供了常见的摘要算法,如 MD5,SHA1 等等。

什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用 16 进制的字符串表示)。 摘要算法就是通过摘要函数 f()对任意长度的数据 data 计算出固定长度的摘要 digest,目的是为了发现原始数据是否被人篡改过。 摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算 f(data)很容易,但通过 digest 反推 data 却非常困难。而且,对原始数据做一个 bit 的修改,都会导致计算出的摘要完全不同。

我们以常见的摘要算法 MD5 为例,计算出一个字符串的 MD5 值:

shell
import hashlib

md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?'.encode())

# 计算结果如下:
>>> md5.hexdigest()
'd26a53750bc40b38b65a520292f69306'

如果数据量很大,可以分块多次调用 update(),最后计算的结果是一样的

python
md5 = hashlib.md5()
md5.update("how to use md5 in ".encode())
md5.update("python hashlib?".encode())
print(md5.hexdigest())

MD5 是最常见的摘要算法,速度很快,生成结果是固定的 128 bit 字节,通常用一个 32 位的 16 进制字符串表示。另一种常见的摘要算法是 SHA1,调用 SHA1 和调用 MD5 完全类似

python
import hashlib

sha1 = hashlib.sha1()
sha1.update("how to use sha1 in ".encode())
sha1.update("python hashlib?".encode())
print(md5.hexdigest())

SHA1 的结果是 160 bit 字节,通常用一个 40 位的 16 进制字符串表示。比 SHA1 更安全的算法是 SHA256 和 SHA512,不过越安全的算法越慢,而且摘要长度更长。

hmac 模块

Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把 key 混入计算过程中。Hmac 算法针对所有哈希算法都通用,无论是 MD5 还是 SHA-1。采用 Hmac 替代我们自己的 salt 算法,可以使程序算法更标准化,也更安全。

shell
>>> import hmac
>>> message = b'Hello, world!'
>>> key = b'secret'
>>> h = hmac.new(key, message, digestmod='MD5')
>>> # 如果消息很长,可以多次调用h.update(msg)
>>> h.hexdigest()
'fa4ee7d173f2d97ee79022d1a7355bcf'

base64 模块

base64模块它也不算加密,只是二进制显示的区别。
解码需要注意的是,位数不够 等号来凑。
具体用法请参考文档。最常用的编码和解码的 API 为:

  • base64.b64encode(s, altchars=None)
  • base64.b64decode(s, altchars=None, validate=False)
shell
import base64
>>> base64.b64encode(b'nanarino', altchars=None)
b'bmFuYXJpbm8='
>>> base64.b64decode(b'bmFuYXJpbm8=',altchars=None, validate=False)
b'nanarino'

pycrypt 模块

加密不同于摘要,加密是一个可逆的过程。
Python 中常用的加密模块是第三方模块pycrypto
在 Windows 系统中可用的模块名字叫pycryptodomex

提供了常用的几种对称加密算法(RSA 等)
具体用法请参考文档。使用 ASE 加密和解密的例子:

python
import base64

# 导入时某些python版本下,包名crypto要小写
# 这里是Windows7 python3.7下使用pycryptodomex安装的
from Cryptodome.Cipher import AES

# 密钥长度必须为16、24或32位,分别对应AES-128、AES-192和AES-256,这里使用16位
aes = AES.new(str.encode("1234567890123456"), AES.MODE_ECB)

msg = "待加密文本"


# 待加密文本长度需要是为16的倍数 不够需要补'\0',反之 解密后也需要去除多余的'\0'
def add_to_16(s):
    while len(s) % 16 != 0:
        s += "\0"
    return str.encode(s)


encrypted_text = str(
    base64.encodebytes(aes.encrypt(add_to_16(msg))), encoding="utf8"
).replace("\n", "")  # 加密
decrypted_text = str(
    aes.decrypt(base64.decodebytes(bytes(encrypted_text, encoding="utf8")))
    .rstrip(b"\0")
    .decode("utf8")
)  # 解密

print("加密值:", encrypted_text)
print("解密值:", decrypted_text)

zlib 模块

zlib模块通过哈夫曼编码对二进制数据的压缩,具体用法请参考文档。常用 API:

python
# 压缩二进制字符串
msg = zlib.compress(msg)

# 解压二进制字符串
msg = zlib.decompress(msg)

uuid 模块

uuid模块是用来生成唯一标识的工具

  • uuid1,基于时间戳和 Mac 地址,有连续的特点:
shell
>>> import uuid
>>> str(uuid.uuid1())
'ab537191-a545-11ea-a77d-00e070a5016b'
>>> str(uuid.uuid1())
'abaf0e8a-a545-11ea-bb19-00e070a5016b'
>>> str(uuid.uuid1())
'ac2dfa83-a545-11ea-87e2-00e070a5016b'
  • uuid3,基于名字的 MD5 散列值:
python
import uuid

print(uuid.uuid3(uuid.NAMESPACE_DNS, "alice"))
  • uuid4,基于随机数。
  • uuid5,基于名字的 SHA-1 散列值。