在python3中使用用户设置的密码进行正确的数据加密

tpgth1q7  于 2023-01-10  发布在  Python
关注(0)|答案(3)|浏览(184)

我一直在python中寻找一个合适的数据加密库很长一段时间了,今天我再次需要它,却找不到任何东西,那么有没有办法使用用户设置的密码来加密数据,如果我找到了一些东西,它通常是不安全的,如果我找到了一个好的解决方案,它不支持用户设置的密码,这意味着我卡住了,有什么办法吗?
下面是一些伪代码:

import encryption

encryptor: encryption.Crypt = encryption.Crypt("my secret password")

encryptor.encrypt("hello this is my very secret string")  # => 9oe gyu yp9q*(Y 28j
encryptor.decrypt("9oe gyu yp9q*(Y 28j")  # => hello this is my very secret string

我不关心它是不是一个对象,我只关心它也可以是一个接受密码的函数:

import encryption

encryption.encrypt("hello this is my very secret string", "my secret password")  # => 9oe gyu yp9q*(Y 28j
encryption.decrypt("9oe gyu yp9q*(Y 28j", "my secret password")  # => hello this is my very secret string

我不介意它的加密或解密方式,我只是想有一种方法来做到这一点:),我也不关心它的输出,它可以是二进制的,一个对象,一个字符串,任何东西

jv4diomz

jv4diomz1#

以下示例基于the answer from 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
vtwuwzda

vtwuwzda2#

加密包(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异常。
完全公开,我不是一个密码学Maven,所以这可能是一个非常糟糕和不安全的方法,但它似乎是合法的。如果有任何密码学Maven想批评我,请随意...)

fumotvh3

fumotvh33#

试试这个小python模块作为加密的 Package 器
pip安装使用系统加密
代码示例:

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()

有关源代码的更多详细信息,请访问github https://github.com/redcorjo/pyeasyencrypt
https://pypi.org/project/pyeasyencrypt/

相关问题