字符串與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進制的字節(jié)
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中出現(xiàn)特殊字符的編碼方式。其原理便是將超出ASCII范圍的字符轉(zhuǎn)換成帶%的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編碼
原理
- 將所有字符轉(zhuǎn)化為ASCII碼。
- 將ASCII碼轉(zhuǎn)化為8位二進制 。
- 將二進制3個歸成一組(不足3個在后邊補0)共24位,再拆分成4組,每組6位。
- 統(tǒng)一在6位二進制前補兩個0湊足8位。
- 將補0后的二進制轉(zhuǎn)為十進制。
- 從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、抗修改性,對于原數(shù)據(jù)進行任何改變,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")) # 如果有參數(shù),在原先的基礎(chǔ)上在做一層加密
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,加密后的數(shù)據(jù)長度更長,更安全。
import hashlib
s = "我愛你"
a = hashlib.sha1(s.encode(encoding="utf-8")).hexdigest()
print(a) # 5890a73fed38bf09622c34ad9391f1d09c0ec100
DES加密
對稱加密體質(zhì)。DES是一個分組加密算法,典型的DES以64位為分組對數(shù)據(jù)加密,加密的和解密用的是同一個算法。
DES算法的入口參數(shù)有3個,key、data、mode。key為工作密鑰,7個字節(jié)。data為需要加解密的數(shù)據(jù)。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的倍數(shù),需要對文本進行填充
: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等工具生成一對公私鑰對,使用被公鑰加密的數(shù)據(jù)可以使用私鑰來解密,反之亦然,使用私鑰加密的數(shù)據(jù)也可以被公鑰加密。
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))
轉(zhuǎn)載文章:Python 常見加密方式和實現(xiàn)