使用salt在python中加密/解密数据

Tab*_*iko 17 python encryption

我想知道如何使用生成的salt密钥加密数据,然后使用python解密它?

我已经通过很多网站和模块,他们看起来都很好看加密部分,但没有人可以解密.

我主要担心的是有很强的盐密钥,可能会在很短的时间内生成,然后使用该密钥加密数据 - 特别是我正在研究使用salt密钥加密JSON编码数据,将加密数据发送到另一方(侦听客户端)然后根据用于生成salt密钥的算法解密那里的数据.

我发现mcrypt模块在这方面效果最好,但是没有太多关于python-mcrypt模块的文档(目前它已经过时而没有维护).

101*_*100 44

对您的问题的简短回答是,您将密码和salt组合在一起并重复哈希以创建密钥.然后将salt附加到密文上,以便生成解密密钥.为了确保我有正确的答案,我做了一些功能来完成工作.它们如下.

在我的回答中,我已经使用了pycrypto,所以我们需要导入一些这些库.

import Crypto.Random
from Crypto.Cipher import AES
import hashlib
Run Code Online (Sandbox Code Playgroud)

为了提高可读性,我已经定义了一些我将在稍后使用的常量.

# 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
Run Code Online (Sandbox Code Playgroud)

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

要生成密钥,密码和盐将连接在一起.此组合根据要求进行多次散列.

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

    key = password + salt

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

    return key
Run Code Online (Sandbox Code Playgroud)

要填充文本,你可以计算出除了16的偶数之外还有多少额外字节.如果是0,则添加16字节的填充,如果是1,则添加15,等等.这样你总是添加填充.您填充的字符是与填充字节数(chr(padding_size))的值相同的字符,以帮助删除末尾的填充(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
Run Code Online (Sandbox Code Playgroud)

加密需要生成随机盐并将其与密码一起使用以生成加密密钥.使用上述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.MODE_ECB)

    padded_plaintext = pad_text(plaintext, AES_MULTIPLE)

    ciphertext = cipher.encrypt(padded_plaintext)

    ciphertext_with_salt = salt + ciphertext

    return ciphertext_with_salt
Run Code Online (Sandbox Code Playgroud)

解密继续进行,从密文中拉出盐并使用它来解密密文的其余部分.然后明文用unpadded 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
Run Code Online (Sandbox Code Playgroud)

如果您有任何其他问题/说明,请与我们联系.


Art*_* B. 5

除了RNCryptor之外,您不需要其他任何东西:

import rncryptor

data = '...'
password = '...'

# rncryptor.RNCryptor's methods
cryptor = rncryptor.RNCryptor()
encrypted_data = cryptor.encrypt(data, password)
decrypted_data = cryptor.decrypt(encrypted_data, password)
assert data == decrypted_data

# rncryptor's functions
encrypted_data = rncryptor.encrypt(data, password)
decrypted_data = rncryptor.decrypt(encrypted_data, password)
assert data == decrypted_data
Run Code Online (Sandbox Code Playgroud)

它提供了语义上安全的加密(每种加密均使用随机盐和IV)加密,并包括通过HMAC进行的安全完整性检查(密文无法在不注意的情况下进行操作)。

RNCryptor也有一种特定的数据格式,因此您不必考虑它和许多语言的实现。