对您的问题的简短回答是,您将密码和盐结合起来,并反复对它们进行散列以创建您的密钥。然后将盐附加到密文中,以便生成用于解密的密钥。为了确保我有正确的答案,我做了一些函数来完成这项工作。它们在下面给出。
在我的回答中,我使用了 pycrypto,所以我们需要导入其中的一些库。
import Crypto.Random
from Crypto.Cipher import AES
import hashlib
为了便于阅读,我定义了一些稍后将使用的常量。
# 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
要使用盐,我已经完成了基于密码的加密方案。我使用RSA PKCS #5 standard 进行基于密码的加密密钥生成和填充,适用于 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
要填充文本,您需要计算超出 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
加密需要生成一个随机盐,并将其与密码一起使用来生成加密密钥。使用上述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
解密向后进行,从密文中提取盐并使用它来解密密文的其余部分。然后使用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
如果您有任何其他问题/说明,请告诉我。