前言:
因为主管数据,数据安全问题比较常见,最近遇到一个业务场景,较多数据加密的处理,结合最近优化数据安全流程的问题,重新梳理下数据加密的知识。
原则还是那句话:代码尽可能短,讲的尽可能通俗。
考虑到加密算法的进步,文末特地放了一些新的文章,供大家交流学习。
定义
数据加密:对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,只能在输入相应的密钥之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。
算法分类
目前主流的分法有2类,对称加密、非对称加密,当然也还有分3类的,新增单向加密(Hash算法),取决于每个人的理解。
算法 | 对称加密 | 非对称加密 | 单向加密 |
---|---|---|---|
类别 | AES / DES / 3DES | RSA / DSA | MD5,SHA系列 |
描述 | 数据加解密用相同密钥 | 公钥加密,加解密不同密钥 | 只可加密不可解密 |
解决问题 | 数据的机密性 | 身份验证 | 数据的完整性 |
优点 | 加密速度快 | 加解密密钥不一致,公钥公开,密钥安全 | |
缺点 | 密钥一致容易泄露 | 加密速度慢 | |
安全性 | AES高 > 3DES中 > DES低 | 均高 | SHA-1高>MD中 |
速度 | AES快 > DES中 > 3DES慢 | RSA中>ECC慢 | MD5快>SHA-1慢 |
资源消耗 | 3DES高 > DES中 > AES低 | ECC高>RSA中 | |
适用范围 | 内部系统,适合大数据量M比特级/秒 | 小数据量/数据签名 | 极少 |
其他 | 密钥:AES(128/192/256位)/3DES(112/168位)/DES(56位) | 成熟度:高 |
主要包介绍
因为平时主要用python处理,所以主要介绍下常用的包
模块名 | 描述 |
---|---|
base64 | 用于二进制数据与ASCII字符的转换操作,提供了基于Base16, Base32, 和Base64算法以及实际标准Ascii85和Base85的编码和解码函数 |
hashlib | 提供常见的单向加密算法(如MD5,SHA等),每种算法都提供了与其同名的函数实现 |
hmac | 实现hmac单向加密算法,支持设置一个额外的密钥(通常被称为’salt’)来提高安全性 |
secrets | Python3.6 新增的模块,用于获取安全随机数 |
pycrypto | 持单向加密、对称加密和公钥加密以及随机数操作,该包是Python中密码学最有名的,2012年已停止。幸运的是,该项目的分支PyCrytodome 取代了 PyCrypto。 |
算法详解
1. base64
- 网络上最常见的用于传输8Bit字节码的编码方式之一,是一种基于64个可打印字符来表示二进制数据的方法。
- 从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。
- 由于以上优点被广泛应用于计算机的各个领域,由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。
1.1 实现原理
- 先将字符转化为ASCII码
- ASCII码转化为8位二进制
- 将二进制3个字节归成一组,每3个字节在编码之后被转换为4个字节一组(如一个数据有6个字节,可编码后将包含6/3*4=8个字节,不足3个在后边补0或“=”)
- 统一在6位二进制前补两个0凑足8位。
- 将补0后的二进制转为十进制。
- 从Base64编码表获取十进制对应的Base64编码。
1.2 代码实现
import base64
# 编码 encode
# 想将字符串转编码成base64,要先将字符串转换成二进制数据
tmp = "this is a test message:四叔的旅途."
res = tmp.encode("utf-8") # 默认以 utf-8 编码
res_code = base64.b64encode(res) # 被编码的参数必须是二进制数据
print(res_code)
# 解码 decode
res_code = "b'dGhpcyBpcyBhIHRlc3QgbWVzc2FnZS4="
res = base64.b64decode(res_code).decode("utf-8")
print(res)
2.MD5 算法
2.1 原理
一种信息摘要算法,以512位分组来处理输入的信息,每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
简单来说,即把一段信息(明文),通过一种有损的方式压缩成定长的字符(32位密文)。因为这种压缩方式是会损失信息的,所以是无法还原出“明文”的,即不可逆。
虽然无法从数学上破解MD5算法,但由于现在计算机具备强大的计算能力,可以通过“穷举法”破解该算法。如果想用该算法加密,还可以通过**“加盐”**的方式提高解密难度。算法允许多传一个参数"salt",指定通过MD5加密的次数,这样是能够提高解密难度的。
2.2 应用场景
常用于不可还原的密码存储、信息完整性校验,如:
- 密码管理(加密注册用户的密码)、电子签名;
- 网站用户上传图片 / 文件后,将MD5值作为文件名。(MD5因不可逆,可保证唯一性)
- 比较两个文件是否被篡改。(在下载资源的时候,发现网站提供了MD5值,就是用来检测文件是否被篡改)
- key-value数据库中使用MD5值作为key。
2.3 代码实现
# 由于MD5模块在python3中被移除,在python3中使用hashlib模块进行md5操作。
# pip install md5/import md5 会报错
# ERROR: Could not find a version that satisfies the requirement md5
# ERROR: No matching distribution found for md5
# 写法1
import hashlib
tmp_text = 'test message:四叔的旅途'
md5 = hashlib.md5() # 生成MD5对象
md5.update(tmp_text.encode('utf-8')) # 对数据加密 该方法只接受byte类型,否则会报错,所以要在参数前添加b来转换类型的原因, 后面方法
tmp_text = md5.hexdigest() # 获取密文 hexdigest 十六进制的意思
print(tmp_text)
# or:
tmp_text = 'test message:四叔的旅途'
tmp_text = hashlib.md5(bytes(tmp_text,encoding = 'utf-8')).hexdigest()
# 不同写法
tmp_text = hashlib.md5(tmp.encode("utf-8")).hexdigest() # 最简单写法,推荐☆
tmp_pic = hashlib.md5(b'test message:四叔的旅途').hexdigest() # 最常见的写法,常用于图片的命名,因为该方法只接受byte类型,否则会报错,所以要在参数前添加b来转换类型的原因
tmp_text = hashlib.new('md5', b'test message:四叔的旅途').hexdigest() # hashlib.new(name[, data]),name传入的是哈希加密算法的名称,如md5
# MD5加盐值(SALT)
tmp_text = 'test message:四叔的旅途'
# 生成MD5对象
md5 = hashlib.md5(b'~!@@#!#$DFDT@#$@#')
# 以下两种方式与上面效果等同
# md5 = hashlib.md5('~!@@#!#$DFDT@#$@#'.encode('utf-8'))
# md5 = hashlib.md5(bytes('~!@@#!#$DFDT@#$@#',encoding='utf-8'))
3. SHA 算法
3.1 原理
安全哈希算法(英语:Secure Hash Algorithm,缩写为SHA)一个密码哈希函数家族,是FIPS所认证的安全哈希算法。
- SHA家族的五个算法:SHA-1、SHA-2(SHA-224、SHA-256、SHA-384和SHA-512),由美国国家安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布,是美国的政府标准。
- SHA-1在许多安全协定中广为使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5的后继者,基于MD5,加密后的数据长度更长,它对长度小于264的输入,产生长度为160bit的散列值。比MD5多32位,因此,比MD5更加安全,但SHA1的运算速度就比MD5要慢。
SHA与MD5的不同:
- 对强行攻击的安全性,SHA-1摘要比MD5摘长,对强行攻击有更大的强度。
- 对密码分析