一 数据加密概述
1.数据加密传输过程中遇到的威胁
- 数据窃听与机密性 如何保证数据在传输过程中不被拦截
- 数据篡改以及完整性 如何保证在传输过程中被篡改而返回假数据
- 身份冒充和身份验证 如何保证传输对方身份无误
2.解决方案
加密方式 | 描述信息 | 解决的主要问题 | 常用算法 |
---|---|---|---|
对称加密 | 指数据加密和解密使用相同的密钥 | 数据的机密性 | DES, AES |
非对称加密 | 也叫公钥加密,指数据加密和解密使用不同的密钥--密钥对儿 | 身份验证 | DSA,RSA |
单向加密 | 指只能加密数据,而不能解密数据 | 数据的完整性 | MD5,SHA系列算法 |
ps:上面SHA系列算法是根据生成的密文的长度而命名的各种算法名称,如SHA1(160bits)、SHA224、SHA256、SHA384等。我们常听说的MD5算法生成的密文长度为128bits
二 python中实现数据加密模块的介绍
python作为"胶水语言",大部分功能都是通过模块来实现的.
通过Python中提供的一些内置的模块或外部模块来实现上面提到的各种加密算法。使用过程也很简单,只需要调用这些模块提供的相应的函数接口即可
1.python内置的数据加密模块的演变过程
单向的数据加密算法有:MD5 SHA系列算法和HMAC,对于python内置的数据加密算法主要功能是提供单向加密功能,并且这些模块随着Python版本的迭代也经历了一些调整和整合
- Python2.5之前的版本所提供的加密模块有:MD5、SHA和HMAC
- Python2.5开始把对md5和sha算法的实现整合到一个新的模块:hashlib;
- Python3.x开始去掉了md5和sha模块,仅剩下hashlib和hmac模块;
- Python3.6增加了一个新的可以产生用于密钥管理的安全随机数的模块:secrets。
md5模块和sha模块为什么会被整合到一个hashlib模块中呢? 因为md5模块提供的是MD5算法的实现,sha模块提供的是SHA1算法的实现,而MD5和SHA1都是hash算法
2. 相关名词解释
- HASH: 一般翻译为“散列”(也有直接音译为“哈希”),就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变成固定长度的输出,该输出值就是散列值。这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一确认输入值。简单来说,hash算法就是一种将任意长度的消息压缩为某一固定长度的消息摘要的函数。
- MD5: 全称为 Message Digest algorithm 5,即信息摘要算法。该算法可以生成定长的数据指纹,被广泛应用于加密和解密技术,常用于文件和数据的完整性校验。
- SHA: 全称为 Secure Hash Algorithm,即安全散列算法/安全哈希算法。该算法是数字签名等密码学应用中的重要工具,被广泛应用于电子商务等信息安全领域。根据生成的密文的长度而命名的各种具体的算法有:SHA1(160bits)、SHA224(224bits)、SHA256(256bits)、SHA384(384bits)等。
- HMAC: 全称为 Hash Message Authentication Code,即散列消息鉴别码。HMAC是基于密钥的哈希算法认证协议,主要是利用哈希算法(如MD5, SHA1),以一个密钥和一个消息作为输入,生成一个消息摘要作为输出,因此其具体的算法名称为HMAC-MD5、HMAC-SHA1等。可见HMAC算法是基于各种哈希算法的,只是它在运算过程中还可以使用一个密钥来增强安全性。
3. 本文要讲解的Python内置模块简介
Python早期的相关模块这里不再介绍了,我们今天主要说明的是以下几个模块:
模块名 | 内置模块 | 描述 |
---|---|---|
hashlib | Y | 主要提供了一些常见的单向加密算法(如MD5,SHA等),每种算法都提供了与其同名的函数实现。 |
hmac | Y | 提供了hmac算法的实现,hamc也是单向加密算法,但是它支持设置一个额外的密钥(通常被称为'salt')来提高安全性 |
random | Y | 该模块主要用于一些随机操作,如获取一个随机数,从一个可迭代对象中随机获取指定个数的元素。 |
secrets | Y | 这是Python 3.6中新增的模块,用于获取安全随机数。 |
base64 | Y | 该模块主要用于二进制数据与可打印ASCII字符之间的转换操作,它提供了基于Base16, Base32, 和Base64算法以及实际标准Ascii85和Base85的编码和解码函数。 |
pycrypto | N | 支持单向加密、对称加密和公钥加密以及随机数操作,这是个第三方模块,需要额外安装。 |
三 hashlib和hmac模块介绍
hashlib模块简介 hashlib文档
hashlib模块为不同的安全哈希/安全散列(Secure Hash Algorithm)和 信息摘要算法(Message Digest Algorithm)实现了一个公共的、通用的接口,也可以说是一个统一的入口。因为hashlib模块不仅仅是整合了md5和sha模块的功能,还提供了对更多中算法的函数实现,如:MD5,SHA1,SHA224,SHA256,SHA384和SHA512。
hashlib模块的函数与属性
函数名/属性名 | 描述 |
---|---|
hashlib.new(name[, data]) | 这是一个通用的哈希对象构造函数,用于构造指定的哈希算法所对应的哈希对象。其中name参数用于指定哈希算法名称,如'md5', 'sha1',不区分大小写;data是一个可选参数,表示初始数据。 |
hashlib.哈希算法名称() | 这是一个hashlib.new()的替换方式,可以直接通过具体的哈希算法名称对应的函数来获取哈希对象,如 hashlib.md5(),hashlib.sha1()等。 |
hashlib.algorithms_guaranteed | Python 3.2新增的属性,它的值是一个该模块在所有平台都会支持的哈希算法的名称集合:set(['sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5']) |
hashlib.algorithms_available | Python 3.2新增的属性,它的值是是一个当前运行的Python解释器中可用的哈希算法的名称集合,algorithms_guaranteed将永远是它的子集。 |
1.hash对象包含的方法与属性:
函数名/属性名 | 描述 |
---|---|
hash.update(data) | 更新哈希对象所要计算的数据,多次调用为累加效果,如m.update(a); m.update(b)等价于m.update(a b) |
hash.digest() | 返回传递给update()函数的所有数据的摘要信息--二进制格式的字符串 |
hash.hexdigest() | 返回传递给update()函数的所有数据的摘要信息--十六进制格式的字符串 |
hash.copy() | 返回该哈希对象的一个copy("clone"),这个函数可以用来有效的计算共享一个公共初始子串的数据的摘要信息。 |
hash.digest_size | hash结果的字节大小,即hash.digest()方法返回结果的字符串长度。这个属性的值对于一个哈希对象来说是固定的,md5:16,sha1(20), sha224(28) |
hash.block_size | hash算法内部块的字节大小 |
hash.name | 当前hash对象对应的哈希算法的标准名称--小写形式,可以直接传递给hashlib.new()函数来创建另外一个同类型的哈希对象。 |
hashlib模块使用步骤:
- 1)获取一个哈希算法对应的哈希对象(比如名称为hash): 可以通过
hashlib.new(哈希算法名称, 初始出入信息)
函数,来获取这个哈希对象,如hashlib.new('MD5', 'Hello'),hashlib.new('SHA1', 'Hello')等;也可以通过hashlib.哈希算法名称()
来获取这个哈希对象,如hashlib.md5(), hashlib.sha1()等。 - 2)设置/追加输入信息: 调用已得到哈希对象的
update(输入信息)
方法可以设置或追加输入信息,多次调用该方法,等价于把每次传递的参数凭借后进行作为一个参数垫底给update()方法。也就是说,多次调用是累加,而不是覆盖。 - 3)获取输入信息对应的摘要: 调用已得到的哈希对象的
digest()
方法或hexdigest()
方法即可得到传递给update()方法的字符串参数的摘要信息。digest()方法返回的摘要信息是一个二进制格式的字符串,其中可能包含非ASCII字符,包括NUL字节,该字符串长度可以通过哈希对象的digest_size
属性获取;而hexdigest()方法返回的摘要信息是一个16进制格式的字符串,该字符串中只包含16进制的数字,且长度是digest()返回结果长度的2倍,这可用邮件的安全交互或其它非二进制的环境中
hashlib模块使用实例:
我们以MD5算法为例获取字符串"Hello, World"的摘要信息(也叫数据指纹)
代码语言:javascript复制# -*- encoding=utf-8 -*-
# Author: Kevin
# @Time: 2019/09/01 16:14
import hashlib
# md5
# 创建hash对象
md5Hash = hashlib.md5()
# 输入需要加密的文本信息
md5Hash.update('Hello'.encode())
# 调用digest方法返回二进制格式的字符串
res1 = md5Hash.digest()
# 通过digest_size属性返回字符串长度
size1 = md5Hash.digest_size
print("通过digest 方法返回的类型:[{}],长度:[{}],结果:[{}]".format(type(res1), size1, res1))
# 调用hexdigest方法返回16进制的字符串,长度是digest方法两倍
ret2 = md5Hash.hexdigest()
print("通过hexdigest 方法返回的类型:[{}],长度:[{}],结果:[{}]".format(type(ret2), len(ret2), ret2))
输出结果
代码语言:javascript复制通过digest 方法返回的类型:[<class 'bytes'>],长度:[16],结果:[b"x8bx1ax99Sxc4ax12x96xa8'xabxf8xc4xx04xd7"]
通过hexdigest 方法返回的类型:[<class 'str'>],长度:[32],结果:[8b1a9953c4611296a827abf8c47804d7]
分析:
- digest()方法返回的结果是一个二进制格式的字符串,字符串中的每个元素是一个字节,我们知道1个字节是8bits,MD5算法获取的数据摘要长度是128bits,因此最后得到的字符串长度是128/8=16;
- hexdigest()方法返回的结果是一个16进制格式的字符串,字符串中每个元素是一个16进制数字,我们知道每个16进制数字占4bits,MD5算法获取的数据摘要长度是128bits,因此最后得到的字符串长度是128/4=32。
在实际工作中,我们通常都是获取数据指纹的16进制格式,比如我们在数据库中存放用户密码时,不是明文存放的,而是存放密码的16进制格式的摘要信息。当用户发起登录请求时,我们按照相同的哈希算法获取用户发送的密码的摘要信息,与数据中存放的与该账号对应的密码摘要信息做比对,两者一致则验证成功。
2. hmac模块
hashmac模块简介:
前面说过,HMAC算法也是一种一种单项加密算法,并且它是基于上面各种哈希算法/散列算法的,只是它可以在运算过程中使用一个密钥来增增强安全性。hmac模块实现了HAMC算法,提供了相应的函数和方法,且与hashlib提供的api基本一致。
hmac模块提供的函数:
函数名 | 描述 |
---|---|
hmac.new(key, msg=None, digestmod=None) | 用于创建一个hmac对象,key为密钥,msg为初始数据,digestmod为所使用的哈希算法,默认为hashlib.md5 |
hmac.compare_digest(a, b) | 比较两个hmac对象,返回的是a==b的值 |
hmac对象中的方法和属性:
方法名/属性名 | 描述 |
---|---|
HMAC.update(msg) | 同hashlib.update(msg) |
HMAC.digest() | 同hashlib.digest() |
HMAC.hexdigest() | 同hashlib.hexdigest() |
HMAC.copy() | 同hashlib.copy() |
HMAC.digest_size | 同hashlib.digest_size |
HMAC.block_size | 同hashlib.block_size |
HMAC.name | 同hashlib.name |
hmac模块使用步骤:
hmac模块模块的使用步骤与hashlib模块的使用步骤基本一致,只是在第1步获取hmac对象时,只能使用hmac.new()函数,因为hmac模块没有提供与具体哈希算法对应的函数来获取hmac对象。