如何在python中使用密码加密文本? [英] How to encrypt text with a password in python?

查看:26
本文介绍了如何在python中使用密码加密文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Google 上很难找到直接的答案.

Surprisingly difficult to find a straight answer to this on Google.

我想从用户处收集一段文本和一条消息,例如 1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc hello world.

I'm wanting to collect a piece of text and a message from a user such as 1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc hello world.

然后我希望能够以某种方式加密/解密带有文本的消息,以便我可以将其保存在我的数据库中,而不必担心如果我的网站被黑客入侵,数据会被暴露,encrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', 'hello world')decrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', <encrypted_text>)

Then I want to be able to encrypt/decrypt the message with the text somehow so that I can save it in my database and not worry about the data being exposed if my website gets hacked, encrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', 'hello world') decrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', <encrypted_text>)

有没有一种简单的方法可以用 python 实现这一点,请有人提供/指导我举个例子.

Is there a simple way to achieve this with python and please can someone provide/direct me to an example.

也许是如何使用诸如 '1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc' 之类的种子创建公钥/私钥对的示例?

Perhaps an example of how to create public/private key pairs using a seed such as '1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc'?

非常感谢:)

为了清楚起见,我正在寻找一种方法来以不确定的方式加密我的用户数据,而不是混淆消息.

Just to be clear I'm looking for a way to encrypt my users data in a determanistic way not obfuscate the message.

如果这意味着我必须使用文本 1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc 作为种子来动态生成 PGP/GPG pub/pri 密钥对,那么这很好,但有什么方法可以做到这一点?

If that means I have to generate a PGP/GPG pub/pri key pair on the fly by using the text 1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc as a seed then that's fine but what's the method to do this?

推荐答案

以下是在 CBC 模式下正确执行的方法,包括 PKCS#7 padding:

Here's how to do it properly in CBC mode, including PKCS#7 padding:

import base64
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random

def encrypt(key, source, encode=True):
    key = SHA256.new(key).digest()  # use SHA-256 over our key to get a proper-sized AES key
    IV = Random.new().read(AES.block_size)  # generate IV
    encryptor = AES.new(key, AES.MODE_CBC, IV)
    padding = AES.block_size - len(source) % AES.block_size  # calculate needed padding
    source += bytes([padding]) * padding  # Python 2.x: source += chr(padding) * padding
    data = IV + encryptor.encrypt(source)  # store the IV at the beginning and encrypt
    return base64.b64encode(data).decode("latin-1") if encode else data

def decrypt(key, source, decode=True):
    if decode:
        source = base64.b64decode(source.encode("latin-1"))
    key = SHA256.new(key).digest()  # use SHA-256 over our key to get a proper-sized AES key
    IV = source[:AES.block_size]  # extract the IV from the beginning
    decryptor = AES.new(key, AES.MODE_CBC, IV)
    data = decryptor.decrypt(source[AES.block_size:])  # decrypt
    padding = data[-1]  # pick the padding value from the end; Python 2.x: ord(data[-1])
    if data[-padding:] != bytes([padding]) * padding:  # Python 2.x: chr(padding) * padding
        raise ValueError("Invalid padding...")
    return data[:-padding]  # remove the padding

它设置为使用 bytes 数据,因此如果您想加密字符串或使用字符串密码,请确保在传递它们之前使用适当的编解码器 encode() 它们到方法.如果您将 encode 参数保留为 Trueencrypt() 输出将是 base64 编码的字符串,并且 decrypt() 源也应该是 base64 字符串.

It's set to work with bytes data, so if you want to encrypt strings or use string passwords make sure you encode() them with a proper codec before passing them to the methods. If you leave the encode parameter to True the encrypt() output will be base64 encoded string, and decrypt() source should be also base64 string.

现在,如果您将其测试为:

Now if you test it as:

my_password = b"secret_AES_key_string_to_encrypt/decrypt_with"
my_data = b"input_string_to_encrypt/decrypt"

print("key:  {}".format(my_password))
print("data: {}".format(my_data))
encrypted = encrypt(my_password, my_data)
print("
enc:  {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec:  {}".format(decrypted))
print("
data match: {}".format(my_data == decrypted))
print("
Second round....")
encrypted = encrypt(my_password, my_data)
print("
enc:  {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec:  {}".format(decrypted))
print("
data match: {}".format(my_data == decrypted))

您的输出将类似于:

key:  b'secret_AES_key_string_to_encrypt/decrypt_with'
data: b'input_string_to_encrypt/decrypt'

enc:  7roSO+P/4eYdyhCbZmraVfc305g5P8VhDBOUDGrXmHw8h5ISsS3aPTGfsTSqn9f5
dec:  b'input_string_to_encrypt/decrypt'

data match: True

Second round....

enc:  BQm8FeoPx1H+bztlZJYZH9foI+IKAorCXRsMjbiYQkqLWbGU3NU50OsR+L9Nuqm6
dec:  b'input_string_to_encrypt/decrypt'

data match: True

证明相同的密钥和相同的数据每次仍然产生不同的密文.

Proving that same key and same data still produce different ciphertext each time.

现在,这比 ECB 好得多,但是...如果您打算使用它进行交流 - 不要!这更多地是为了解释它应该如何构建,而不是真正用于生产环境,尤其不是用于通信,因为它缺少一个关键要素 - 消息身份验证.随意使用它,但你不应该推出自己的加密,有经过严格审查的协议可以帮助你避免常见的陷阱,你应该使用这些.

Now, this is much better than ECB but... if you're going to use this for communication - don't! This is more to explain how it should be constructed, not really to be used in a production environment and especially not for communication as its missing a crucial ingredient - message authentication. Feel free to play with it, but you should not roll your own crypto, there are well vetted protocols that will help you avoid the common pitfalls and you should use those.

这篇关于如何在python中使用密码加密文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆