文章目录
- 一、汇总
- 二、base64加密-(无密钥)
- 三、哈希Hash加密算法
- 1、简介
- 2、哈希碰撞
- 3、Hash算法的性质 :
- 4、Hash算法的用途:
- (1) 检验信息是否相同
- (2)密码加密
- 5、MD5加密算法
- 6、SHA256加密
- 四、对称加密算法-- AES
- 1、介绍
- 2、原理
- 3、python实现
- 五、非对称加密算法-- RSA
- 1、原理
- 2、Python实现
一、汇总
加密算法分类:
1-Base64编码
2-哈希算法
3-对称加密算法
4-非对称加密算法
python中常用的数据加密算法:
1-Base64编码
2-MD5加密算法(哈希)
3-SHA256加密算法(哈希)
4-RSA加密算法(非对称加密)
由于加密算法的特点不同,所以使用的场合也不同。
1-用户登录,一般采用MD5算法、RSA算法
2-数据完整性校验,一般采用MD5算法
3-Token,一般采用Base64编码
二、base64加密-(无密钥)
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
在网络应用领域,常有人将BASE64编码误称为加密。实际上,BASE64只是一种将二进制数据转换为可打印字符的编码方式,不具备加密特性。它的主要应用是实现不同设备和平台间的二进制数据传输及特定协议和规范中的处理。
import base64
#base64加密
def encode_base64(val):
ret = base64.b64encode(val)
return ret
#base64解密
def decode_base64(val):
ret = base64.b64decode(val)
return ret
假如通过邮件发送字符串“Hello, World!”,因邮件客户端不支持特殊符号,需先将文本进行BASE64编码。编码过程如下:
- 将字符串“Hello, World!”转换成二进制数据:
01001000 01100101 01101100 01101100 01101111 00101100 00100000 01010111 01101111 01110010 01101100 01100100 00100001 - 将二进制数据按6比特进行划分:
010010 000110 010101 101100 011011 001101 101111 001011 001000 001010 110111 011011 100010 110110 001100 010001 - 将得到的每个6比特组对应到BASE64字符表中:
SGVsbG8sIFdvcmxkIQ==
这样,收件人收到BASE64编码后的字符串SGVsbG8sIFdvcmxkIQ==
,
三、哈希Hash加密算法
1、简介
Hash加密算法是一种将任意长度的消息压缩成固定长度散列值的算法。
它的特点是快速、不可逆和安全。
Hash加密算法被广泛用于数字签名、数据完整性验证等信息安全领域。
Hash加密算法通过将任意长度的消息输入到算法中,经过一系列计算得到一个固定长度的Hash值。Hash值可以看作是消息的指纹,具有唯一性和不可逆性。
对于相同的消息,执行相同的Hash算法得到的Hash值是相同的,但即使是输入消息的微小变化也会导致Hash值的巨大变化。因此,Hash加密算法可以用于验证数据完整性和数字签名等场景。
哈希加密算法提供:MD5加密、SHA-1加密、SHA-2加密、SHA-256加密、SHA-512加密、SHA-3加密、RIPEMD-160加密等各种加密工具。
2、哈希碰撞
哈希碰撞是指:两个不同的输入得到了相同的输出。
"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0
"通话".hashCode(); // 0x11ff03
"重地".hashCode(); // 0x11ff03
碰撞能不能避免?答案是不能。碰撞是一定会出现的,因为输出的字节长度是固定的, String 的 hashCode() 输出是 4 字节整数,最多只有 4294967296 种输出, 但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入 集合映射到一个有限的输出集合,必然会产生碰撞。 碰撞不可怕,我们担心的不是碰撞,而是碰撞的概率,因为碰撞概率的高低关系 到哈希算法的安全性。一个安全的哈希算法必须满足: 碰撞概率低; 不能猜测输出。 不能猜测输出是指:输入的任意一个 bit 的变化会造成输出完全不同,这样就很难从输出反推输入(只能依靠暴力穷举)。
3、Hash算法的性质 :
- 单向性。即给定一个输入数,容易计算出它的哈希值,但是已知一个哈希值根据同样的算法不能得到原输入数。
- 弱抗碰撞性。即给定一个输入数,要找到另一个得到给定数的哈希值,在使用同一种方法时,在计算上不可行。
- 强抗碰撞性。即对于任意两个不同的输入数,根据同样的算法计算出相同的哈希值,在计算上不可行。
- 雪崩效应:当一个输入未发生变化时输出位将有一半发生变化。
4、Hash算法的用途:
(1) 检验信息是否相同
它可以检验信息是否是相同的,这样的优势是可以节省重复数据传送的时间。就像我们在一些网盘中上传的文件,如果文件内容相同的话,哪怕属于不同的用户,也可以通过对比哈希值避免向服务器重复上传相同的文件,可以很大程度上节约存储资源,提高存储效率。
我们在网上下载文件,在本地校验,以保证文件未被篡改:
import hashlib
with open("D:\python-3.11.1-amd64.exe", 'rb') as f:
m1 = hashlib.md5(f.read())
print('该文件校验值为:' + m1.hexdigest())
(2)密码加密
除此之外,哈希算法也可以对网站注册用户的密码进行加密保护。
哈希算法不可逆,用于密文保存密码的签名,网站后台只保存签名值。 这样即使网站保存的信息被盗取,也无法获取用户的密码,具有更高的安全性。
5、MD5加密算法
MD5即Message-Digest Algorithm 5(信息-摘要算法 5), 将数据(如汉字)运算为另一固定长度值,是散列算法的基础原理(密码散列函数),MD5的前身有MD2、MD3和MD4。
MD5一度被广泛应用于安全领域。但是由于MD5的弱点被不断发现以及计算机能力不断的提升,现在已经可以构造两个具有相同MD5的信息,使本算法不再适合当前的安全环境。
目前,MD5计算广泛应用于错误检查。例如在一些BitTorrent下载中,软件通过计算MD5和检验下载到的碎片的完整性。
MD5是输入不定长度信息,输出固定长度128-bits(16字节)的散列值(哈希值)的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
import hashlib
def Md5(val):
md5 = hashlib.md5()
md5.update(val.encode("UTF-8"))
ret = md5.hexdigest()
return ret
6、SHA256加密
SHA-1在许多安全协议中广为使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5的后继者。但SHA-1的安全性如今被密码学家严重质疑。
SHA-224、SHA-256、SHA-384,和SHA-512并称为SHA-2。
SHA-256信息摘要算法,也是一种密码散列函数对于任意长度的消息,SHA256都会产生一个256bit长的散列值(哈希值),用于确保信息传输完整一致,称作消息摘要。
新的散列函数并没有接受像SHA-1一样的公众密码社区做详细的检验,所以它们的密码安全性还不被大家广泛的信任。
虽然至今尚未出现对SHA-2有效的攻击,它的算法跟SHA-1基本上仍然相似;因此有些人开始发展其他替代的散列算法。
import hashlib
def Sha256(val):
sha256 = hashlib.sha256()
sha256.update(val.encode("UTF-8"))
ret = sha256.hexdigest()
return ret
四、对称加密算法-- AES
1、介绍
AES加密,全名“高级加密标准”,是一种非常强大的加密算法,它是由美国国家标准与技术研究所(NIST)在2001年发布的,它被认为是目前世界上最安全、最先进的加密算法之一。
AES加密有着很多用途,它可以用来加密数据,以防止未经授权的访问和更改;也可以用来加密电子邮件,保护个人隐私;它还可以用来加密网络传输,保护网络数据免受未经授权的访问;也可以用来保护Wi-Fi网络的安全性。
AES加密算法的安全性可以通过它的密钥长度来衡量,密钥越长,安全性就越高。128位的密钥可以抵抗大多数的攻击,而192位和256位的密钥可以抵抗所有的攻击。
它的安全性可以抵抗各种类型的攻击,包括密码穷举攻击、密码分析攻击和密码拓展攻击。
2、原理
将明文按照一定的规则进行分组,然后使用密钥(128位、192位或256位)对每组数据进行加密。
AES加密算法有三种模式:ECB(电子密码本)、CBC(密码块链)和CFB(密码反馈)。
- ECB模式。最常用的模式,它将明文分割成固定大小的块,然后使用密钥对每个块进行加密。但是,它存在一个问题:如果明文中有两个相同的块,那么它们也会被加密成相同的密文。
- CBC模式。为了解决ECB问题,它使用一个初始化向量(IV)来确保每个块都被加密为不同的密文。它的工作原理是:将明文分割成固定大小的块,然后使用IV和密钥对每个块进行加密。
- CFB模式。它使用一个初始化向量(IV)来确保每个明文字节都被加密为不同的密文字节。它的工作原理是:将明文分割成固定大小的块,然后使用IV和密钥对每个块进行加密,并将加密后的密文作为下一次加密的输入。
3、python实现
from Crypto.Cipher import AES
import base64
# 密钥(key), 密斯偏移量(iv) CBC模式加密
BLOCK_SIZE = 16 # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) # 如果text不足16位的倍数就用空格补足为16位
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
vi = '0102030405060708'
def AES_Encrypt(key, data):
data = pad(data) # 字符串补位
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
encryptedbytes = cipher.encrypt(data.encode('utf8'))
encodestrs = base64.b64encode(encryptedbytes) # 加密后得到的是bytes类型的数据,使用Base64进行编码,返回byte字符串
enctext = encodestrs.decode('utf8') # 对byte字符串按utf-8进行解码
return enctext
def AES_Decrypt(key, data):
data = data.encode('utf8')
encodebytes = base64.decodebytes(data) # 将加密数据转换位bytes类型数据
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
text_decrypted = cipher.decrypt(encodebytes) # 去补位
text_decrypted = unpad(text_decrypted)
text_decrypted = text_decrypted.decode('utf8')
return text_decrypted
if __name__ == '__main__':
key = 'ILoveyou_5201314'
data = 'I Love you'
enctext = AES_Encrypt(key, data)
print(enctext)
AES_Decrypt(key, enctext)
五、非对称加密算法-- RSA
1、原理
RSA是最常见的非对称加密,也就是用来加密的密钥和用来解密的密钥不是同一个。
RSA也是分组加密算法,不同的是分组大小可以根据密钥的大小而改变。如果加密的数据不是分组大小的整数倍,则会根据具体的应用方式增加额外的填充位。
首先生成两个密钥,一个公钥,一个私钥,前者加密,后者解密,客户端和服务器各执一份.一般为了安全,私钥是不会给前端暴露出来 的,只会通过私钥生成一个公开的公钥提供给外部对数据进行加密。
将加密后的数据传给后端,后端使用私钥解密.当客户端向服务器发送数据的时候,先用公钥加密,再有私钥加签,到了服务器一端,用公钥验签,用私钥解密,然后再往下走.加密是为了安全,加签是为了防止冒充APP 客户端进行请求,导致服务器的瘫痪。
RSA算法属于分组加密方案,也就是说明文以分组为单位加密,分组的大小取决于所选的模n的值,明文块每个分组的长度可以相同也可以不同,但是,各分组大小必须小于或等于log2(n)的值。已知明文的某块分组报文M,公钥(e,n),私钥(d,n),则加密过程如下:对M的e次方幂指数运算结果再做模n运算,所得结果即为密文C。
publicKey: 公钥,用于加密。
privateKey: 私钥,用于解密。
plaintext: 明文。
ciphertext: 密文。
2、Python实现
import base64
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
from Crypto.PublicKey import RSA
def create_rsa_pair(is_save=False): # 生成密钥对-----
'''
创建rsa公钥私钥对
:param is_save: default:False
:return: public_key, private_key
'''
f = RSA.generate(2048)
private_key = f.exportKey("PEM") # 生成私钥
public_key = f.publickey().exportKey() # 生成公钥
if is_save:
with open("crypto_private_key.pem", "wb") as f:
f.write(private_key)
with open("crypto_public_key.pem", "wb") as f:
f.write(public_key)
return public_key, private_key
def read_public_key(file_path="crypto_public_key.pem") -> bytes:
with open(file_path, "rb") as x:
b = x.read()
return b
def read_private_key(file_path="crypto_private_key.pem") -> bytes:
with open(file_path, "rb") as x:
b = x.read()
return b
# ------------------------加密------------------------
def encryption(text: str, public_key: bytes):
text = text.encode('utf-8') # 字符串指定编码(转为bytes)
cipher_public = PKCS1_v1_5.new(RSA.importKey(public_key)) # 构建公钥对象
text_encrypted = cipher_public.encrypt(text) # 加密(bytes)
text_encrypted_base64 = base64.b64encode(text_encrypted).decode() # base64编码,并转为字符串
return text_encrypted_base64
# ------------------------解密------------------------
def decryption(text_encrypted_base64: str, private_key: bytes):
text_encrypted_base64 = text_encrypted_base64.encode('utf-8') # 字符串指定编码(转为bytes)
text_encrypted = base64.b64decode(text_encrypted_base64) # base64解码
cipher_private = PKCS1_v1_5.new(RSA.importKey(private_key)) # 构建私钥对象
text_decrypted = cipher_private.decrypt(text_encrypted, Random.new().read) # 解密(bytes)
text_decrypted = text_decrypted.decode() # 解码为字符串
return text_decrypted
if __name__ == '__main__':
public_key, private_key = create_rsa_pair(is_save=False) # 生成密钥对
text = '123456'
text_encrypted_base64 = encryption(text, public_key) # 加密
print('密文:', text_encrypted_base64)
text_decrypted = decryption(text_encrypted_base64, private_key) # 解密
print('明文:', text_decrypted)