建立在萨姆·哈佐格的回答 https://stackoverflow.com/a/73535983/373815,下面是一个示例,它遵循 PBES2(基于密码的加密方案 2)中定义的逻辑RFC8018,第 6.2 节 https://www.rfc-editor.org/rfc/rfc8018#section-6.2。然而,它缺乏编码算法的选择和参数。
#!/usr/bin/python
import base64
import secrets
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
KDF_ALGORITHM = hashes.SHA256()
KDF_LENGTH = 32
KDF_ITERATIONS = 120000
def encrypt(plaintext: str, password: str) -> (bytes, bytes):
# Derive a symmetric key using the passsword and a fresh random salt.
salt = secrets.token_bytes(16)
kdf = PBKDF2HMAC(
algorithm=KDF_ALGORITHM, length=KDF_LENGTH, salt=salt,
iterations=KDF_ITERATIONS)
key = kdf.derive(password.encode("utf-8"))
# Encrypt the message.
f = Fernet(base64.urlsafe_b64encode(key))
ciphertext = f.encrypt(plaintext.encode("utf-8"))
return ciphertext, salt
def decrypt(ciphertext: bytes, password: str, salt: bytes) -> str:
# Derive the symmetric key using the password and provided salt.
kdf = PBKDF2HMAC(
algorithm=KDF_ALGORITHM, length=KDF_LENGTH, salt=salt,
iterations=KDF_ITERATIONS)
key = kdf.derive(password.encode("utf-8"))
# Decrypt the message
f = Fernet(base64.urlsafe_b64encode(key))
plaintext = f.decrypt(ciphertext)
return plaintext.decode("utf-8")
def main():
password = "aStrongPassword"
message = "a secret message"
encrypted, salt = encrypt(message, password)
decrypted = decrypt(encrypted, password, salt)
print(f"message: {message}")
print(f"encrypted: {encrypted}")
print(f"decrypted: {decrypted}")
Output:
message: a secret message
encrypted: b'gAAAAABjDlH2eaRZmB4rduBdNHUOITV5q4oelpnLRUgI_uyQyNpUyW8h3c2lZYS1MwMpRWIZposcZvag9si1pc4IEK83_CzyBdXF27Aop9WWS6ybxTg9BSo='
decrypted: a secret message