Python中Cryptography庫實現(xiàn)加密解密
先介紹與加密解密有關(guān)的幾個基本概念。
- 加密(Encryption):加密是將明文轉(zhuǎn)換為密文的過程,使得未經(jīng)授權(quán)的人無法讀懂。
- 解密(Decryption):解密是將密文轉(zhuǎn)換為明文的過程,使得原始信息可以被正確的人閱讀。
- 密鑰(Key):密鑰是加密和解密過程中的關(guān)鍵。它可以是單個數(shù)字、字符串或者是更復(fù)雜的密鑰對象。
- 算法:算法是加密和解密過程中的具體步驟。
cryptography是一個強大的Python庫,提供了一套豐富的加密相關(guān)的操作,用于安全地處理數(shù)據(jù)。它旨在提供簡單易用的加密方法,同時也支持更高級的加密需求,使這項技術(shù)變得易于使用。cryptography庫包含兩個主要的高級組件:Fernet(對稱加密)和hazmat(危險材料層)。
主要特點
- 易用性:cryptography庫的設(shè)計初衷是易于使用,盡量減少安全漏洞的出現(xiàn)。
- 安全性:它提供了最新的加密算法,并且經(jīng)過安全專家的審查。
- 靈活性:對于需要直接訪問加密算法的高級用戶,cryptography提供了hazmat模塊。
主要組件
Fernet:提供了對稱加密的實現(xiàn),非常適合用于加密和解密可以安全共享密鑰的場景。使用Fernet非常簡單,只需要一個密鑰就可以進行安全的數(shù)據(jù)加密和解密。
hazmat(Hazardous Materials):這個模塊提供了底層加密原語(如塊密碼、消息摘要算法等)。它是為那些需要執(zhí)行特定加密操作的高級用戶設(shè)計的,但使用時需要格外小心,因為不當(dāng)?shù)氖褂每赡軐?dǎo)致安全問題。
官方文檔https://cryptography.io/en/latest/
在Windows平臺上安裝cryptography,可在cmd命令行中,輸入如下命令:
pip install cryptography
回車,默認(rèn)情況使用國外線路較慢,我們可以使用國內(nèi)的鏡像網(wǎng)站:
豆瓣:https://pypi.doubanio.com/simple/
清華:https://pypi.tuna.tsinghua.edu.cn/simple
電腦上安裝了多個Python版本,你可以為特定版本的Python安裝模塊(庫、包)。例如我的電腦中安裝了多個Python版本,要在Python 3.10版本中安裝,并使用清華的鏡像,cmd命令行中,輸入如下命令
py -3.10 -m pip install cryptography -i https://pypi.tuna.tsinghua.edu.cn/simple
示例
1、生成私鑰和獲取公鑰
# -*- coding: utf-8 -*-
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
# 生成私鑰
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
# 獲取公鑰
public_key = private_key.public_key()
2、私鑰和公鑰序列化
# 私鑰序列化
private_key_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# 保存私鑰到文件
with open('private.key', 'wb') as f:
f.write(private_key_pem)
# 公鑰序列化
public_key_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# 保存公鑰到文件
with open('public.pem', 'wb') as f:
f.write(public_key_pem)
3、私鑰和公鑰的反序列化
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
# 從文件加載私鑰
with open("private.key", "rb") as private_key_file:
private_key = serialization.load_pem_private_key(
private_key_file.read(),
password=None,
backend=default_backend()
)
# 從文件加載公鑰
with open("public.pem", "rb") as public_pem_file:
public_key = serialization.load_pem_public_key(
public_pem_file.read(),
backend=default_backend()
)
4、公鑰加密私鑰解密
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 公鑰解密
message = 'Hello'
encrypted = public_key.encrypt(
plaintext=message.encode('utf-8'),
padding=padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(encrypted)
# b'm\xf2\x8d\xa84\xbe\x13\xe1...'
# 私鑰解密
original_message = private_key.decrypt(
ciphertext=encrypted,
padding=padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(original_message.decode('utf-8'))
# Hello
5、私鑰簽名公鑰驗簽
# -*- coding: utf-8 -*-
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 私鑰簽名
message = 'Hello'
signature = private_key.sign(
data=message.encode('utf-8'),
padding=padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
algorithm=hashes.SHA256()
)
print(signature)
# b'm\xf2\x8d\xa84\xbe\x13\xe1...'
# 公鑰驗簽 如果驗證失敗拋出異常cryptography.exceptions.InvalidSignature
public_key.verify(
signature=signature,
data='Hello'.encode('utf-8'),
padding=padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
algorithm=hashes.SHA256()
)
簡單示例:使用Fernet進行數(shù)據(jù)加密和解密源碼:
from cryptography.fernet import Fernet
# 生成密鑰
key = Fernet.generate_key()
cipher_suite = Fernet(key)
# 加密數(shù)據(jù)
data = b"Hello, cryptography!"
encrypted_data = cipher_suite.encrypt(data)
print(f"Encrypted: {encrypted_data}")
# 解密數(shù)據(jù)
decrypted_data = cipher_suite.decrypt(encrypted_data)
print(f"Decrypted: {decrypted_data}")
運行效果:

圖形用戶界面的文件加密解密程序
使用tkinter添加界面的加密解密程序,當(dāng)用戶點擊“加密文件”或“解密文件”按鈕時,程序會從這個文本框中獲取密鑰,并使用它進行相應(yīng)的加密或解密操作。加密和解密的文件將會被保存在與原文件相同的目錄下,加密文件的文件名在原圖片文件名前添加enc_,解密文件的文件名在原加密圖片文件名前添加dec_
先給出運行效果:

源碼如下:
import tkinter as tk
from tkinter import filedialog
from cryptography.fernet import Fernet
import os
def encrypt(filename, key, status_label):
try:
f = Fernet(key.encode()) # 將密鑰從字符串轉(zhuǎn)換為字節(jié)
with open(filename, "rb") as file:
file_data = file.read()
encrypted_data = f.encrypt(file_data)
dir_name, base_filename = os.path.split(filename)
# 分離目錄和文件名
encrypted_filename = f"enc_{base_filename}"
# 將加密文件保存在原始目錄中
encrypted_file_path = os.path.join(dir_name, encrypted_filename)
with open(encrypted_file_path, "wb") as file:
file.write(encrypted_data)
status_label.config(text=f"提示:文件已加密:{encrypted_filename}")
except Exception as e:
status_label.config(text=f"提示:加密失敗: {str(e)}")
def decrypt(filename, key, status_label):
try:
f = Fernet(key.encode()) # 將密鑰從字符串轉(zhuǎn)換為字節(jié)
with open(filename, "rb") as file:
encrypted_data = file.read()
decrypted_data = f.decrypt(encrypted_data)
# 分離目錄和文件名
dir_name, base_filename = os.path.split(filename)
decrypted_filename = f"dec_{base_filename}"
# 將解密文件保存在原始目錄中
decrypted_file_path = os.path.join(dir_name, decrypted_filename)
with open(decrypted_file_path, "wb") as file:
file.write(decrypted_data)
status_label.config(text=f"提示:文件已解密:{decrypted_filename}")
except Exception as e:
status_label.config(text=f"提示:解密失敗: {str(e)}")
# 創(chuàng)建GUI界面
def select_file(operation, key_entry, status_label):
key = key_entry.get() # 從文本框獲取密鑰
if not key:
status_label.config(text="提示:操作失?。何摧斎朊荑€")
return
file_path = filedialog.askopenfilename()
if file_path: # 如果file_path不是空字符串
if operation == 'encrypt':
encrypt(file_path, key, status_label)
elif operation == 'decrypt':
decrypt(file_path, key, status_label)
else:
status_label.config(text="提示:沒有選擇文件")
def main():
root = tk.Tk()
root.title("加密解密程序")
tk.Label(root, text="密鑰:").pack()
key_entry = tk.Entry(root, show='*', width=50) # 密鑰輸入框
key_entry.insert(0, 'X3Q8PvDs2EzKHK-8TjgUE8HkZ8QeuOe0S7-3VVqjTDI=') # 設(shè)置默認(rèn)值
key_entry.pack()
status_label = tk.Label(root, text="提示:請選擇操作", height=2)
status_label.pack()
tk.Button(root, text="加密文件", command=lambda: select_file('encrypt', key_entry, status_label)).pack()
tk.Button(root, text="解密文件", command=lambda: select_file('decrypt', key_entry, status_label)).pack()
root.mainloop()
if __name__ == "__main__":
main()
cryptography庫提供了許多高級功能,提供了多種密碼學(xué)算法,包括對稱加密、非對稱加密、哈希函數(shù)、簽名、密鑰管理等等。支持多種加密標(biāo)準(zhǔn),包括AES、DES、RSA、SSL/TLS等等,同時也提供了許多密碼學(xué)工具,如密碼學(xué)隨機數(shù)生成器、PBKDF2函數(shù)、密碼學(xué)算法器等等。關(guān)于這些詳情請閱讀相關(guān)文檔,在此僅舉以下是一個簡單的例子,展示了如何生成RSA密鑰對、使用公鑰進行加密以及使用私鑰進行解密,源碼如下:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# 生成RSA密鑰對
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 將私鑰序列化并保存到文件
with open("private_key.pem", "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
# 將公鑰序列化并保存到文件
with open("public_key.pem", "wb") as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
# 讀取公鑰進行加密
with open("public_key.pem", "rb") as f:
public_key = serialization.load_pem_public_key(
f.read(),
backend=default_backend()
)
message = "Hello, RSA Cryptography!".encode()
encrypted = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 讀取私鑰進行解密
with open("private_key.pem", "rb") as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=None,
backend=default_backend()
)
original_message = private_key.decrypt(
encrypted,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 顯示解密后的消息
print(original_message.decode())
這個例子首先生成了一個2048位的RSA密鑰對,將私鑰保存到private_key.pem文件中,將公鑰保存到public_key.pem文件中。接下來,代碼從public_key.pem文件中讀取公鑰用于加密消息,從private_key.pem文件中讀取私鑰用于解密消息。最后,使用公鑰對一段消息進行加密,然后使用私鑰將消息解密。padding.OAEP是一種常用的填充方式,與SHA-256哈希算法一起使用,以確保加密過程的安全性。
到此這篇關(guān)于Python中Cryptography庫實現(xiàn)加密解密的文章就介紹到這了,更多相關(guān)Python Cryptography加密解密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python光學(xué)仿真理解Jones矩陣學(xué)習(xí)
這篇文章主要為大家介紹了Python光學(xué)仿真理解Jones矩陣的學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2021-10-10
python matplotlib imshow熱圖坐標(biāo)替換/映射實例
這篇文章主要介紹了python matplotlib imshow熱圖坐標(biāo)替換/映射實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Python 關(guān)于模塊和加載模塊的實現(xiàn)
這篇文章主要介紹了Python 關(guān)于模塊和加載模塊的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
python算法與數(shù)據(jù)結(jié)構(gòu)朋友圈與水杯實驗題分析實例
這篇文章主要介紹了python算法與數(shù)據(jù)結(jié)構(gòu)朋友圈與水杯實驗題分析,總的來說這并不是難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路2022-12-12
python2.7 json 轉(zhuǎn)換日期的處理的示例
這篇文章主要介紹了python2.7 json 轉(zhuǎn)換日期的處理的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03

