基于 Sam Hartzog 的答案,下面是一个示例,它遵循 RFC8018 第 6.2 节中定义的 PBES2(基于密码的加密方案 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}")
输出:
message: a secret message
encrypted: b'gAAAAABjDlH2eaRZmB4rduBdNHUOITV5q4oelpnLRUgI_uyQyNpUyW8h3c2lZYS1MwMpRWIZposcZvag9si1pc4IEK83_CzyBdXF27Aop9WWS6ybxTg9BSo='
decrypted: a secret message
pip install cryptography
)就可以很好地解决这个问题。我认为您看不到简单的 OOTB
基于字符串实现的原因是密码学在字节级别上工作,而不是字符串(可能以任何方式编码)。无论如何,以下内容似乎适用于您概述的简单用例。 创建一个“加密器”并加密一些东西
from cryptography.fernet import Fernet
import base64
entered_pw = "secretpw"
key = base64.b64encode(f"{entered_pw:<32}".encode("utf-8"))
encryptor = Fernet(key=key)
encrypted = encryptor.encrypt(
"my super secret data with a password".encode("utf-8")
)
print(encrypted)
输出:
b'gAAAAABjDVew9-VszAFP1ZdlDz-ZqwdIksCBhLbH8OEJjxEZyEy6cQ4jrxEBHZtHsGtWxHsG0qJIkQ_b5e5Ibx5-1uAa1HXdBwWys6YE7WwhmMPtAbj_VP2F8rKFck7MYvv5nKrZbWGF'
使用正确输入的密码解密结果
from cryptography.fernet import Fernet
import base64
entered_pw = "secretpw"
key = base64.b64encode(f"{entered_pw:<32}".encode("utf-8"))
encryptor = Fernet(key=key)
encrypted = b'gAAAAABjDVew9-VszAFP1ZdlDz-ZqwdIksCBhLbH8OEJjxEZyEy6cQ4jrxEBHZtHsGtWxHsG0qJIkQ_b5e5Ibx5-1uAa1HXdBwWys6YE7WwhmMPtAbj_VP2F8rKFck7MYvv5nKrZbWGF'
print(encryptor.decrypt(encrypted).decode("utf-8"))
输出:
'my super secret data with a password'
如果您在解密时提供错误密码,您将收到 InvalidSignature 异常。 完全披露,我不是密码学专家,所以这可能是一个非常糟糕且不安全的方法,但它似乎是合法的 ́\_(ツ)_/̅。如果有任何加密货币专家想要带我去完成任务,请随意......;)
pip install pyeasyencrypt
代码示例:
import logging, os
# pip install pyeasyencrypt
from pyeasyencrypt.pyeasyencrypt import encrypt_string, decrypt_string
level = os.getenv("LOGGER", "INFO")
logging.basicConfig(level=level)
logger = logging.getLogger(__name__)
def main():
logger.info("Example")
clear_string = 'stringA'
password = "my password"
encrypted_string = encrypt_string(clear_string, password)
decrypted_string = decrypt_string(encrypted_string, password)
logger.info(f"clear_string={clear_string} decrypted_string={decrypt_string} password={password} encrypted_string={encrypted_string}")
logger.debug("Done")
if __name__ == '__main__':
main()
有关源代码的更多详细信息,请查看 githubhttps://github.com/redcorjo/pyeasyencrypthttps://pypi.org/project/pyeasycrypt/