我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes。所以当我们在Python中进行加密操作的时候,要确保我们操作的是Bytes,否则就会报错。
基本概念
- 明文:明文是指没有经过加密的数据。一般而言,明文都是等待传输的数据。由于没有经过加密,明文很容易被识别与破解,因此在传输明文之前必须进行加密处理。
- 密文:密文只是明文经过某种加密算法而得到的数据,通常密文的形式复杂难以识别及理解。
- 密钥:密钥是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的参数。
- 对称加密:通信双方同时掌握一个密钥,加密解密都是由一个密钥完成的(即加密密钥等于解密密钥,加解密密钥可以相互推倒出来)。双方通信前共同拟定一个密钥,不对第三方公开。
- 分组加密:分组密码是将明文分成固定长度的组,每一组都采用同一密钥和算法进行加密,输出也是固定长度的密文。
加密算法分类
对称加密算法:
对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥
发送方和接收方需要持有同一把密钥,发送消息和接收消息均使用该密钥。
相对于非对称加密,对称加密具有更高的加解密速度,但双方都需要事先知道密钥,密钥在传输过程中可能会被窃取,因此安全性没有非对称加密高。
常见的对称加密算法:DES,AES,3DES等等
非对称加密算法:
文件加密需要公开密钥(publickey)和私有密钥(privatekey)。
接收方在发送消息前需要事先生成公钥和私钥,然后将公钥发送给发送方。发送放收到公钥后,将待发送数据用公钥加密,发送给接收方。接收到收到数据后,用私钥解密。
在这个过程中,公钥负责加密,私钥负责解密,数据在传输过程中即使被截获,攻击者由于没有私钥,因此也无法破解。
非对称加密算法的加解密速度低于对称加密算法,但是安全性更高。
非对称加密算法:RSA、DSA、ECC等算法
消息摘要算法:
消息摘要算法可以验证信息是否被篡改。
在数据发送前,首先使用消息摘要算法生成该数据的签名,然后签名和数据一同发送给接收者。
接收者收到数据后,对收到的数据采用消息摘要算法获得签名,最后比较签名是否一致,以此来判断数据在传输过程中是否发生修改。
Python实现加密方法合集
# -*- coding:utf-8 -*-
import base64
import rsa
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from pyDes import des, CBC, PAD_PKCS5
from Crypto.Cipher import DES3
import hashlib
import hmac
class USE_AES:
"""
AES
除了MODE_SIV模式key长度为:32, 48, or 64,
其余key长度为16, 24 or 32
详细见AES内部文档
CBC模式传入iv参数
本例使用常用的ECB模式
"""
def __init__(self, key):
if len(key) > 32:
key = key[:32]
self.key = self.to_16(key)
def to_16(self, key):
"""
转为16倍数的bytes数据
:param key:
:return:
"""
key = bytes(key, encoding="utf8")
while len(key) % 16 != 0:
key += b'\0'
return key # 返回bytes
def aes(self):
return AES.new(self.key, AES.MODE_ECB) # 初始化加密器
def encrypt(self, text):
aes = self.aes()
return str(base64.encodebytes(aes.encrypt(self.to_16(text))),
encoding='utf8').replace('\n', '') # 加密
def decodebytes(self, text):
aes = self.aes()
return str(aes.decrypt(base64.decodebytes(bytes(
text, encoding='utf8'))).rstrip(b'\0').decode("utf8")) # 解密
class USE_RSA:
"""
生成密钥可保存.pem格式文件
1024位的证书,加密时最大支持117个字节,解密时为128;
2048位的证书,加密时最大支持245个字节,解密时为256。
加密大文件时需要先用AES或者DES加密,再用RSA加密密钥,详细见文档
文档:https://stuvel.eu/files/python-rsa-doc/usage.html#generating-keys
"""
def __init__(self, number=1024):
"""
:param number: 公钥、私钥
"""
self.pubkey, self.privkey = rsa.newkeys(number)
def rsaEncrypt(self, text):
"""
:param test: str
:return: bytes
"""
content = text.encode('utf-8')
crypto = rsa.encrypt(content, self.pubkey)
return crypto
def rsaDecrypt(self, text):
"""
:param text:bytes
:return: str
"""
content = rsa.decrypt(text, self.privkey)
con = content.decode('utf-8')
return con
def savePem(self, path_name, text):
"""
:param path_name: 保存路径
:param text: str
:return:bytes
"""
if "PEM" in path_name.upper():
path_name = path_name[:-4]
with open('{}.pem'.format(path_name), 'bw') as f:
f.write(text.save_pkcs1())
def readPem(self, path_name, key_type):
"""
:param path_name: 密钥文件
:param key_type:类型
:return:
"""
if 'pubkey' in key_type:
self.pubkey = rsa.PublicKey.load_pkcs1(path_name)
else:
self.privkey = rsa.PublicKey.load_pkcs1(path_name)
return True
def sign(self, message, priv_key=None, hash_method='SHA-1'):
"""
生成明文的哈希签名以便还原后对照
:param message: str
:param priv_key:
:param hash_method: 哈希的模式
:return:
"""
if None == priv_key:
priv_key = self.privkey
return rsa.sign(message.encode(), priv_key, hash_method)
def checkSign(self, mess, result, pubkey=None):
"""
验证签名:传入解密后明文、签名、公钥,验证成功返回哈希方法,失败则报错
:param mess: str
:param result: bytes
:param pubkey:
:return: str
"""
if None == pubkey:
pubkey = self.privkey
try:
result = rsa.verify(mess, result, pubkey)
return result
except:
return False
class USE_DES:
"""
des(key,[mode], [IV], [pad], [pad mode])
key:必须正好8字节
mode(模式):ECB、CBC
iv:CBC模式中必须提供长8字节
pad:填充字符
padmode:加密填充模式PAD_NORMAL or PAD_PKCS5
"""
def __init__(self, key, iv):
if not isinstance(key, bytes):
key = bytes(key, encoding="utf8")
if not isinstance(iv, bytes):
iv = bytes(iv, encoding="utf8")
self.key = key
self.iv = iv
def encrypt(self, text):
"""
DES 加密
:param text: 原始字符串
:return: 加密后字符串,bytes
"""
if not isinstance(text, bytes):
text = bytes(text, "utf-8")
secret_key = self.key
iv = self.iv
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(text, padmode=PAD_PKCS5)
return en
def descrypt(self, text):
"""
DES 解密
:param text: 加密后的字符串,bytes
:return: 解密后的字符串
"""
secret_key = self.key
iv = self.iv
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(text, padmode=PAD_PKCS5)
return de.decode()
class USE_DES3:
"""
new(key, mode, *args, **kwargs)
key:必须8bytes倍数介于16-24
mode:
iv:初始化向量适用于MODE_CBC、MODE_CFB、MODE_OFB、MODE_OPENPGP,4种模式
``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB``长度为8bytes
```MODE_OPENPGP```加密时8bytes解密时10bytes
未提供默认随机生成
nonce:仅在 ``MODE_EAX`` and ``MODE_CTR``模式中使用
``MODE_EAX``建议16bytes
``MODE_CTR``建议[0, 7]长度
未提供则随机生成
segment_size:分段大小,仅在 ``MODE_CFB``模式中使用,长度为8倍数,未指定则默认为8
mac_len: 适用``MODE_EAX``模式,身份验证标记的长度(字节),它不能超过8(默认值)
initial_value:适用```MODE_CTR```,计数器的初始值计数器块。默认为**0**。
"""
def __init__(self, key):
self.key = key
self.mode = DES3.MODE_ECB
def encrypt(self, text):
"""
传入明文
:param text:bytes类型,长度是KEY的倍数
:return:
"""
if not isinstance(text, bytes):
text = bytes(text, 'utf-8')
x = len(text) % 8
text = text+b'\0'*x
cryptor = DES3.new(self.key, self.mode)
ciphertext = cryptor.encrypt(text)
return ciphertext
def decrypt(self, text):
cryptor = DES3.new(self.key, self.mode)
plain_text = cryptor.decrypt(text)
st = str(plain_text.decode("utf-8")).rstrip('\0')
return st
def USE_MD5(test):
if not isinstance(test, bytes):
test = bytes(test, 'utf-8')
m = hashlib.md5()
m.update(test)
return m.hexdigest()
def USE_HMAC(key, text):
if not isinstance(key, bytes):
key = bytes(key, 'utf-8')
if not isinstance(text, bytes):
text = bytes(text, 'utf-8')
h = hmac.new(key, text, digestmod='MD5')
return h.hexdigest()
def USE_SHA(text):
if not isinstance(text, bytes):
text = bytes(text, 'utf-8')
sha = hashlib.sha1(text)
encrypts = sha.hexdigest()
return encrypts
if __name__ == '__main__':
aes_test = USE_AES("assssssssdfasasasasa")
a = aes_test.encrypt("测试")
b = aes_test.decodebytes(a)
rsa_test = USE_RSA()
a = rsa_test.rsaEncrypt("测试加密")
b = rsa_test.rsaDecrypt(a)
des_test = USE_DES(b"12345678", b"12345678")
a = des_test.encrypt("测试加密")
b = des_test.descrypt(a)
des3_test = USE_DES3(b"123456789qazxswe")
a = des3_test.encrypt("测试加密")
b = des3_test.decrypt(a)
md5_test = USE_MD5("测试签名")
hmac_test = USE_HMAC("123456", "测试")
sha_test = USE_SHA("测试加密")
Github: https://github.com/dhfjcuff/R-A-M-D-D3-S-M-H/blob/master/RSA-AES-MD5-DES-DES3-MD5-SHA-HMAC.py