字符串与bytes
s = "我爱你"
a = s.encode("utf-8")
b = a.decode("utf-8")
print(a) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
print(b) # 我爱你
binascii
binascii模块以更合适的方式展示16进制的字节
import binascii
s = "我爱你"
a = s.encode("utf-8")
b = binascii.b2a_hex(a)
c = binascii.a2b_hex(b)
print(a) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
print(b) # b'e68891e788b1e4bda0'
print(c) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
URL编码
URL编码是一种浏览器用来避免URL中出现特殊字符的编码方式。其原理便是将超出ASCII范围的字符转换成带%的16进制格式。
from urllib import parse
url = "https://www.baidu.com?value=我爱你"
a = parse.quote(url)
b = parse.unquote(a)
print(a) # https%3A//www.baidu.com%3Fvalue%3D%E6%88%91%E7%88%B1%E4%BD%A0
print(b) # https://www.baidu.com?value=我爱你
Base64编码
原理
- 将所有字符转化为ASCII码。
- 将ASCII码转化为8位二进制 。
- 将二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位。
- 统一在6位二进制前补两个0凑足8位。
- 将补0后的二进制转为十进制。
- 从Base64编码表获取十进制对应的Base64编码。
import base64
s = "我爱你"
a = base64.b64encode(s.encode("utf-8"))
b = base64.b64decode(a)
print(a) # b'5oiR54ix5L2g'
print(b.decode("utf-8")) # 我爱你
MD5编码
特点
1、长度固定
2、抗修改性,对于原数据进行任何改变,MD5都会改变
3、强碰撞性,不同文件的MD5值基本上是唯一的
4、不可逆性
import hashlib
s = "我爱你"
md5 = hashlib.md5()
md5.update(s.encode("utf-8"))
a = md5.hexdigest()
key = "123456"
md5_2 = hashlib.md5(bytes(key, encoding="utf-8")) # 如果有参数,在原先的基础上在做一层加密
md5_2.update(s.encode("utf-8"))
b = md5_2.hexdigest()
print(a) # 4f2016c6b934d55bd7120e5d0e62cce3
print(b) # 5054fb0f1535be3289f1ba92027e8325
计算大文件的md5值
import hashlib
def get_file_md5(file):
m = hashlib.md5()
while True:
data = file.read(10240)
if not data:
break
m.update(data)
return m.hexdigest()
FILE_NAME = "D:/Steam/game.zip"
with open(FILE_NAME, 'rb') as f:
file_md5 = get_file_md5(f)
print(file_md5)
hmac
import hmac
s = "我爱你"
salt = "123456"
hm = hmac.new(s.encode(encoding="utf-8"), salt.encode(encoding="utf-8"), "MD5")
print(hm.digest()) # b'\x17\xae\xe8\xc3f\xb0\xd0\xee\xd1\x87\xa3=\x1b\xd8%\xb1'
print(hm.hexdigest()) # 17aee8c366b0d0eed187a33d1bd825b1
sha1加密
Security Hash Algorithm(安全哈希算法)。sha1基于MD5,加密后的数据长度更长,更安全。
import hashlib
s = "我爱你"
a = hashlib.sha1(s.encode(encoding="utf-8")).hexdigest()
print(a) # 5890a73fed38bf09622c34ad9391f1d09c0ec100
DES加密
对称加密体质。DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密的和解密用的是同一个算法。
DES算法的入口参数有3个,key、data、mode。key为工作密钥,7个字节。data为需要加解密的数据。mode为DES的工作模式。
密钥长64位,由56位key和第8、16、24、32、40、48、56、64位校验位组成。
DES加密需要第三方依赖包。pip install pycryptodome
from Crypto.Cipher import DES
import binascii
def pad(text):
"""
如果加密文本不是8的倍数,需要对文本进行填充
:param text:
:return:
"""
pad_text = (8 - len(text) % 8) * "*" if len(text) % 8 else ""
return text + pad_text
key = "12345678"
s = "hello, my friend"
des = DES.new(key.encode("utf-8"), DES.MODE_ECB)
data = pad(s)
encrypted_data = des.encrypt(data.encode("utf-8"))
plain_data = des.decrypt(encrypted_data)
print(data) # hello, my friend
print(binascii.b2a_hex(encrypted_data)) # b'8d0c263b163a0b90eafe513008caa8f6'
print(plain_data) # b'hello, my friend'
AES
Advanced Encryption Standard
from Crypto.Cipher import AES
from Crypto import Random
import binascii
data = "我爱你"
key = "12345678abcdefgh" # b密钥key必须位16位、24位或32位
iv = Random.new().read(AES.block_size)
aes_encrypt = AES.new(key.encode("utf-8"), AES.MODE_CFB, iv)
cipher_text = iv + aes_encrypt.encrypt(data.encode("utf-8"))
aes_decrypt = AES.new(key.encode("utf-8"), AES.MODE_CFB, cipher_text[:16])
decrypt_text = aes_decrypt.decrypt(cipher_text[16:])
print(binascii.b2a_hex(iv)) # b'c491c0df41490bb643976ae0672a9b1c'
print(binascii.b2a_hex(cipher_text)) # b'c491c0df41490bb643976ae0672a9b1c598dfd7be91cfbc1ad'
print(decrypt_text.decode("utf-8")) # 我爱你
RSA
非对称加密
使用openssl,keytools等工具生成一对公私钥对,使用被公钥加密的数据可以使用私钥来解密,反之亦然,使用私钥加密的数据也可以被公钥加密。
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import binascii
class MyRSA:
def __init__(self):
self.private_rsa_key = "" # 密钥
self.rsa_public_pem = "" # 公钥
def create_rsa_key(self, password):
key = RSA.generate(1024)
encrypted_key = key.exportKey(passphrase=password.encode("utf-8"), pkcs=8,
protection="scryptAndAES128-CBC")
self.private_rsa_key = encrypted_key
self.rsa_public_pem = key.publickey().exportKey()
def encrypt(self, text):
recipient_key = RSA.import_key(self.rsa_public_pem)
cipher_rsa = PKCS1_v1_5.new(recipient_key)
encrypted_text = cipher_rsa.encrypt(text.encode("utf-8"))
return encrypted_text
def decrypt(self, encrypted_text, password):
private_key = RSA.import_key(self.private_rsa_key, password)
cipher_rsa = PKCS1_v1_5.new(private_key)
text = cipher_rsa.decrypt(encrypted_text, None)
return text
password = "123456"
rsa = MyRSA()
rsa.create_rsa_key(password)
encrypted_text = rsa.encrypt("我爱你")
decrypted_text = rsa.decrypt(encrypted_text, password)
print(binascii.b2a_hex(encrypted_text))
print(decrypted_text.decode("utf-8"))
print(binascii.b2a_hex(rsa.private_rsa_key))
print(binascii.b2a_hex(rsa.rsa_public_pem))
转载文章:Python 常见加密方式和实现