用盐加密/解密python中的数据 [英] Encrypt / decrypt data in python with salt

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

问题描述

我想知道基本上如何使用生成的盐键加密数据,然后使用python解密?



我已经走了很多网站和模块,他们都看起来很棒的encrpytion部分,但没有一个可以解密似乎。



我的主要关注点是具有强大的盐键,这可能是几个hunderd时间产生的,然后使用该密钥加密数据 - 特别是我正在使用salt键对JSON编码数据进行加密,将加密数据发送给另一方(侦听客户端),然后根据用于生成盐密钥的算法对其中的数据进行解密。



我发现mcrypt模块最适合使用,但python-mcrypt模块没有太多的文档(目前是过时且未被维护)。

解决方案

您的问题的简短答案是您将密码和盐组合并重复哈希,以创建密钥。然后,您将盐附加到密文上,以便您可以生成解密密钥。为了确保我有正确的答案,我做了一些功能来做这个工作。他们在下面给出。



在我的答案中,我使用了pycrypto,所以我们需要导入一些这些库。

 导入Crypto.Random 
来自Crypto.Cipher import AES
import hashlib

为了帮助可读性,我已经定义了一些我以后会使用的常量。

 #salt size(以字节为单位)
SALT_SIZE = 16

#密钥生成中的迭代次数
NUMBER_OF_ITERATIONS = 20

#AES
所需的大小倍数AES_MULTIPLE = 16

要使用盐,我已经完成了基于密码的加密方案。我已经使用 RSA PKCS#5标准进行密码加密密钥生成和填充,适用于AES加密算法。



要生成密钥,密码和盐被连接。这个组合可以根据要求进行多次散列。

  def generate_key(password,salt,iterations):
assert iterations > 0

key = password + salt

在范围内(迭代):
key = hashlib.sha256(key).digest()

返回键

要填充文本,您会发现有多少额外的字节超出如果为0,则添加16个字节的填充,如果为1,则添加15等。这样您总是添加填充。你填充的字符是与填充字节数相同的字符( chr(padding_size)),以帮助删除最后的填充( ord(padded_text [-1]))。

  def pad_text ,多个):
extra_bytes = len(text)%multiple

padding_size = multiple - extra_bytes

padding = chr(padding_size)* padding_size

padded_text = text + padding

return padded_text

def unpad_text(padded_text):
padding_size = ord(padded_text [-1])$ ​​b
$ b text = padded_text [: - padding_size]

返回文本

加密需要生成一个随机盐并使用它与密码一起生成加密密钥。使用上述 pad_text 函数填充文本,然后使用加密对象进行加密。结果,密文和盐被连接并返回。如果你想发送这个明文,你需要用base64进行编码。

  def encrypt(plaintext,password) 
salt = Crypto.Random.get_random_bytes(SALT_SIZE)

key = generate_key(password,salt,NUMBER_OF_ITERATIONS)

cipher = AES.new(key,AES。

padded_plaintext = pad_text(plaintext,AES_MULTIPLE)

ciphertext = cipher.encrypt(padded_plaintext)

ciphertext_with_salt = salt + ciphertext

return ciphertext_with_salt

解密向后退,从密文中拉出盐,并使用解密其余的密文。然后,使用 unpad_text

  def decrypt(ciphertext,密码)
salt = ciphertext [0:SALT_SIZE]

ciphertext_sans_salt = ciphertext [SALT_SIZE:]

key = generate_key(password,salt,NUMBER_OF_ITERATIONS)

cipher = AES.new(key,AES.MODE_ECB)

padded_plaintext = cipher.decrypt(ciphertext_sans_salt)

plaintext = unpad_text(padded_plaintext)

返回明文

如果您有任何其他问题/说明,请通知我。 / p>

I'd like to know basically how can I encrypt data with a generated salt key and then decrypt it using python ?

i've gone trough a lot of websites and modules, and they all look great at encrpytion part, but none can decrypt as it seems.

My main concern is to have strong salt key, that'd be probably generated over few hunderd times, then use that key to encrypt data - in particular I'm looking into encrypting JSON encoded data with the salt key, sending the encrypted data to the other side ( listening client ) and then decrypt the data there based on the algorithm that is used to generate the salt key.

I've found that mcrypt module would work best with this, but there isn't much documentation for python-mcrypt module ( that's currently being outdated and not maintained).

解决方案

The short answer to your question is that you combine the password and the salt and hash them repeatedly to create your key. Then you append the salt onto the ciphertext so that you can generate the key for decryption. To ensure that I had the right answer, I made a few functions to do the work. They are given below.

In my answer, I've made use of pycrypto, so we need to import a few of those libraries.

import Crypto.Random
from Crypto.Cipher import AES
import hashlib

To aid readability, I've defined a few constants that I'll use later on.

# salt size in bytes
SALT_SIZE = 16

# number of iterations in the key generation
NUMBER_OF_ITERATIONS = 20

# the size multiple required for AES
AES_MULTIPLE = 16

To use a salt, I've done a password-based encryption scheme. I've used the RSA PKCS #5 standard for password-based encryption key generation and padding, adapted for the AES encryption algorithm.

To generate the key, the password and the salt are concatenated. This combination is hashed as many times as requested.

def generate_key(password, salt, iterations):
    assert iterations > 0

    key = password + salt

    for i in range(iterations):
        key = hashlib.sha256(key).digest()  

    return key

To pad the text, you figure out how many extra bytes you have beyond an even multiple of 16. If it is 0, you add 16 bytes of padding, if it is 1, you add 15, etc. This way you always add padding. The character you pad with is the character with the same value as the number of padding bytes (chr(padding_size)), to aid the removal of the padding at the end (ord(padded_text[-1])).

def pad_text(text, multiple):
    extra_bytes = len(text) % multiple

    padding_size = multiple - extra_bytes

    padding = chr(padding_size) * padding_size

    padded_text = text + padding

    return padded_text

def unpad_text(padded_text):
    padding_size = ord(padded_text[-1])

    text = padded_text[:-padding_size]

    return text

Encryption requires generating a random salt and using that along with the password to generate the encryption key. The text is padded using the above pad_text function and then encrypted with a cipher object. The ciphertext and salt are concatenated and returned as a result. If you wanted to send this as plaintext, you would need to encode it with base64.

def encrypt(plaintext, password):
    salt = Crypto.Random.get_random_bytes(SALT_SIZE)

    key = generate_key(password, salt, NUMBER_OF_ITERATIONS)

    cipher = AES.new(key, AES.MODE_ECB)

    padded_plaintext = pad_text(plaintext, AES_MULTIPLE)

    ciphertext = cipher.encrypt(padded_plaintext)

    ciphertext_with_salt = salt + ciphertext

    return ciphertext_with_salt

Decryption proceeds backwards, pulling the salt off of the ciphertext and using that to decrypt the remainder of the ciphertext. Then the plaintext is unpadded using unpad_text.

def decrypt(ciphertext, password):
    salt = ciphertext[0:SALT_SIZE]

    ciphertext_sans_salt = ciphertext[SALT_SIZE:]

    key = generate_key(password, salt, NUMBER_OF_ITERATIONS)

    cipher = AES.new(key, AES.MODE_ECB)

    padded_plaintext = cipher.decrypt(ciphertext_sans_salt)

    plaintext = unpad_text(padded_plaintext)

    return plaintext

Let me know if you have any other questions/clarifications.

这篇关于用盐加密/解密python中的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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