前言:在测试过程中,我们经常会遇到加密或者解密的情况,我们需要针对项目中的加密方式进行相关操作,下面就一起来看看常见的加密方式有哪些吧
一、什么是加密/解密?
答:加密就是通过一定手段把需要传输的数据,进行复杂化的算法加密,而解密的过程中就是把加密算法计算后的数据,进行逆向解密(注:部分加密方式不可逆)
二、为什么要做加密?
答:因为要保护数据的安全性和防篡改
三、加密方式介绍
a)算法 1: base64
解析:严格老说这不是加密算法,它叫做编码算法。和我们把文字编码成计算机当中的二进制数据一样。就和我们把中文翻译成英文一样, base64 这样的编码算法只是把你看得懂的字翻译成肉眼看不懂的字,但是一旦你知道这些看不懂的符号是哪一门语言,你就可以直接翻译回去。
例子:
备注1:编码后的数据: b'SSBMaWtlIOWwj+mYv+WNtw==',这个b" "其实代表是字节的意思
备注2:手动解码base64网址:Base64 在线编码解码 | Base64 加密解密 - Base64.us
import base64
#——————————————————————————开发人员做的加密过程————————————————————————
str_1 = "I Like 小阿卷" #需要加密(编码)的数据
print("原数据:{}".format(str_1))#打印下原始的数据
byte_str = str_1.encode("utf-8") #encode() 方法以指定的编码格式编码字符串,默认编码为 ‘utf-8’。
encode_str = base64.b64encode(byte_str) #base64位进行加密
print("编码后的数据:",encode_str) #打印编码后的内容
#——————————————————————————测试人员去做的解密过程——————————————————————
encode_str_001 = "SSBMaWtlIOWwj+mYv+WNtw==" #被加密后的数据
decode_str = base64.b64decode(encode_str_001) #base64解密
decode_str = decode_str.decode("utf-8") #decode() 方法以指定的编码格式解码字符串
print("解码后的数据:",decode_str)
#响应:
原数据:I Like 小阿卷
编码后的数据: b'SSBMaWtlIOWwj+mYv+WNtw=='
解码后的数据: I Like 小阿卷
b)算法 2: urlencode
解析:URL 编码, 和 base64 一样,只是编码算法,不能称为加密。 记住,编码方式,只要你通过观察看到的字符串的特征,分析出编码方式,是可以很轻易的解码的。
备注1:比如:base64 的特征是尾部经常带有 =
号, url 编码的特征是 %
很多,比如:
http://example.com/?q=%E8%8F%9C%E9%B8%9F
http://example.com/?q=菜鸟
例子:
from urllib.parse import quote, unquote
#url 编码, 得到 http://example.com/?q=%E8%8F%9C%E9%B8%9F
url = "http://example.com/?q=%E8%8F%9C%E9%B8%9F" #已被编码的内容
#——————————————解码———————————————————————
q = "%E8%8F%9C%E9%B8%9F"
q = unquote(q) #解码
print(q)
响应:
菜鸟
c)算法 3: md5
md5 不是编码,也不是加密,它叫做摘要算法,又称哈希算法和散列算法。 他的主要作用是:防篡改、数据校验——MD5加密不可逆
比如你下载了一个软件,会担心这个软件被人修改,植入了病毒。软件开发者为了防止自己的软件被别人修改,会在官网附带一个摘要信息。比如 https://dl.snipaste.com/sha-1.txt 这个网址就是该软件每个版本的摘要信息。
当你下载好软件以后,利用摘要算法检测工具检测改软件,算出他的摘要信息,如果和官方提供的一致,说明软件没有被修改;如果不一致,就说明这个软件被篡改了。
摘要算法的另一个应用场景是用来保存密码。我们日常注册账号输入的密码通常不会直接保存在数据库,而是经过摘要(或者是加密)处理以后保存在数据库当中。你可以通过在线工具对任意数据进行 md5 “加密”,这里提供 python 版代码:
那为什么密码会被盗? 密码被盗通常是因为黑客利用了摘要算法的另一个特性攻击了数据库,这种方式叫撞库。 对于单一的摘要算法,有一个特征:只要你的原始数据是固定的,得到的 hash 值也会一样。比如 hello yuz 得到的就是 bfb3f4712d0b04e8348a3fb5fa0b9bc2 。黑客就是利用这种对应关系,将很多人常用的密码和对应的 hash 值做成一个关系表(彩虹表),然后一一去尝试。 比如很多人喜欢把密码生成 8888, abc123。 黑客只需要将这些密码提前算出对应的 hash 值保存起来,就可以尝试攻破你的账号
例子:
import hashlib
hash = hashlib.md5() #初始化md5库
hash.update(b"ajuan") ## 明文密码是ajuan
hash_str = hash.hexdigest()#返回摘要,作为十六进制数据字符串值
print(hash_str)
响应:
eabaa2703810a93be31dce8792276de7
c1.1)什么是加盐?
上面的例子提到,黑客可以利用彩虹表套取你的密码,所以纯粹的摘要算法不是一种特别安全的方式去存储密码。但是我们可以采取“加盐” 的方式提高安全性。 网站开发者会提供一个类似于秘钥的东西,我们称为 salt, 其实就是一个随便起的字符串。然后将原始密码 + salt 得到一个新字符串,再对他进行 hash。 只要 salt 不被黑客知道,就没有办法利用彩虹表来攻击数据库。以下是加盐版的 python 代码:
在测试过程中,如果公司的密码是通过摘要算法生成的,可以找开发小哥哥要盐, 然后通过对应的摘要算法验证数据库密码。
import hashlib
salt = "the salt" #类似于秘钥的东西
pwd = "8888" #你的密码
salt_pwd = pwd + salt #我们称为 salt, 其实就是一个随便起的字符串。然后将原始密码 + salt 得到一个新字符串,再对他进行 hash。
hash = hashlib.md5() #初始化md5
hash.update(salt_pwd.encode("utf-8")) #加密
hash_str = hash.hexdigest() #返回摘要,作为十六进制数据字符串值
print(hash_str)
响应:
4b366a299919d113185edc24127f2e56
d)SHA1算法
SHA1 和 md5 一样,也是摘要算法,还有 SHA256, SHA512。 我们看到的区别就是长度不一样。长度越长,理论上更加安全,同时也意味着速度更慢。
例子:
import hashlib
s = hashlib.sha1() #实例化sha1()
s.update(b"xiaoajuan") #需要加密的数据->b''代表字节
sha_str = s.hexdigest()#返回摘要,作为十六进制数据字符串值
print(sha_str)
响应:
d0a2d62cb490529fb14a8a41d350f2cd7a63d030
e)RSA 算法
RSA加密算法是一种非对称加密算法,加密的秘钥是由公钥和私钥两部分组成秘钥对,公钥用来加密消息,私钥用来对消息进行解密,公钥是公开的,私钥则是用户自己保留的,由于公钥是公开的,那么任何人只要获取到公钥,都可以使用公钥来加密发送伪造内容,出于安全性考虑,在发送消息之前我们可以使用RSA来签名,签名使用私钥来进行签名,使用公钥来进行验签,通过签名我们可以确保用户身份的唯一性,从而提高安全性。
————加密:
比方现在有两个人A和B,A要给B传递机密的信息,为了避免信息泄露,B事先通过RSA加密算法生成了一对秘钥,并且将公钥事先给到A,私钥则自己保留,A给B传递消息的时候,先使用B给的公钥对消息进行加密,然后再将消息传递给B,B拿到加密后的消息,可以通过私钥对消息进行解密,消息在传递过程中就算被他人获取了也没关系,没有私钥就没办法对消息进行解密。但是这个时候还有一个问题,公钥一般都是公开的,会同时给到多个人,那么如果这个时候还有一个人C,获取到了这个公钥,他通过公钥对消息进行加密,想冒充A来给B发信息,那么B接受到信息之后,能够通过私钥来对消息进行解密,但是无法确认这个信息到底是不是A发的(有可能是别拿的公钥加密发的),为了区分发送者的身份,那么这个时候我们就要用到签名。
————签名:
虽然我们通过加密能够确保发送的消息不被泄密,但是却无法区分发送者的身份,A用户为了区分自己的身份,同样也生成了一对秘钥,事先将公钥给到B,发送消息的时候,先用B给的公钥对消息进行加密,然后用A自己的私钥生成签名,最后将加密的消息和签名一起发过去给B,B接收到A发送的数据之后,首先使用A用户的公钥对签名信息进行验签,确认身份信息,如果确认是A用户,然后再使用自己的私钥对加密消息进行解密。 A的消息通过加密和签名处理之后,再发送出去给B,就算被人截获了,也没有关系,没有B的私钥无法对消息进行解密,就算获取A的公钥,想要发送伪造信息,没有A私钥也无法进行签名。同样B给A回复消息的时候,可以通过B的公钥进行加密,然后使用自己的私钥生成签名,A接收到数据化使用同样的方式进行解密验证身份。 这样一来就能够做到万无一失。
官方文档:https://stuvel.eu/python-rsa-doc/
RSA非对称加密
1、公钥进行加密(公开的)
2、私钥进行解密(保密)
例子:
import rsa
import base64
#简单封装RSA加解密方法:
class MyRsa:
def __init__(self):
self.pubkey,self.privkey = rsa.newkeys(512) #初始化生成公钥和私钥,512位
#————————————————————————————加密——————————————————————————————————————————————
def encode_string(self,string): #string需要加密的数据
string = string.encode("utf8")#指定utf-8的方式进行编码
encrypt_string = rsa.encrypt(message=string,pub_key = self.pubkey) #message:需要加密的信息 pub_key:使用公钥加密
encrypt_string = base64.b64encode(encrypt_string) #使用base64编码
encrypt_string = encrypt_string.decode() #decode() 方法以指定的编码格式编码字符串
print("加密后:",encrypt_string)
return encrypt_string
#————————————————————————————解密——————————————————————————————————————————————
def decode_string(self,encrypt_string): #encrypt_string:需要解密的数据
encrypt_string = encrypt_string.encode() #encode() 方法以指定的编码格式解码字符串
encrypt_string = base64.b64decode(encrypt_string) #使用base64解码
encrypt_string = rsa.decrypt(crypto=encrypt_string, priv_key=self.privkey) #crypto:需要解密的数据 #priv_key:使用私钥解密
encrypt_string = encrypt_string.decode(encoding="utf8") #指定utf-8的方式进行解码
print("解密后:",encrypt_string)
if __name__ == '__main__':
cl = MyRsa()
encrypt_string = cl.encode_string(string="123456")
cl.decode_string(encrypt_string)
响应:
加密后: Ayo3ns+BzxBiruI5rO26oR2ptHE03fs8e0hNPWR8t8MJPEpqRR+0LXnnf/8zgy2RqpEW5PJN37io5suGLNjGxw==
解密后: 123456