筆記如何使用 Python Fernet 對稱式進行資料加解密,以及搭配 PBKDF2HMAC 的方式,使用密碼加密 Fernet 的金鑰。
說明
前置作業需要先使用 pip
安裝 library:
pip install pycryptodome
generateKey.py
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os
import base64
def generate_save_key(password, file_path="encrypted_key.bin"):
fernet_key = Fernet.generate_key()
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA512(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
cipher = Fernet(key)
encrypted_fernet_key = cipher.encrypt(fernet_key)
with open(file_path, "wb") as file:
file.write(salt + encrypted_fernet_key)
接著就可以建立 key file:
password = "12345678"
file_path = "encrypted_key.bin"
generate_save_key(password, file_path)
loadKey.py
def load_key(password, file_path="encrypted_key.bin"):
with open(file_path, "rb") as file:
salt = file.read(16)
encrypted_fernet_key = file.read()
kdf = PBKDF2HMAC(
algorithm=hashes.SHA512(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
cipher = Fernet(key)
fernet_key = cipher.decrypt(encrypted_fernet_key)
return fernet_key
可以透過以下的方式,讓使用者輸入密碼取回真正的 Fernet key:
password = input('please input password:')
fernet_key = load_key(password, 'encrypted_key.bin')
EncryptDecrypt.py
藉由取回的 Fernet key
,可以搭配 Fernet
物件來進行加解密的操作,加密的資料必須是 Binary 所以加密前必須進行 Encode
,解密的資料則必須透過 Decode
的方式還原為原本的內容。
def encrypt(data, fernet_key):
cipher = Fernet(fernet_key)
return cipher.encrypt(data.encode())
def decrypt(encrypted_data, fernet_key):
cipher = Fernet(fernet_key)
return cipher.decrypt(encrypted_data).decode()
main.py
with open('business.txt', 'r', encoding='utf8') as f:
data_to_encrypt = '\n'.join(f.readlines())
encrypted_data = encrypt(data_to_encrypt, fernet_key)
with open('encrypted_text.bin', 'wb') as f:
f.write(encrypted_data)
print(f"Encrypted: {encrypted_data}")
以上示範如何將文字檔的內容讀取,並且藉由 Fernet 加密後另存為 encrypted_text.bin
。
with open('encrypted_text.bin', 'rb') as f:
encrypted_data = f.read()
decrypted_data = decrypt(encrypted_data, fernet_key)
print(f"Decrypted: {decrypted_data}")
以上示範如何讀取 encrypted_text.bin
並且解密回原本的內容。