【问题标题】:Decrypting AES-256-CBC cipher with a passcode built using PBKDF2 in Python使用 Python 中使用 PBKDF2 构建的密码解密 AES-256-CBC 密码
【发布时间】:2020-04-23 01:49:29
【问题描述】:

我有一个加密的会话密钥,需要使用 python 解密,但我真的不知道该怎么做。

我已获得密码、salt 和 hmac 密钥。我需要解码的字符串是base64编码的,解码时它是一个管道描述的密钥和到期日期(会话密钥+管道分隔符+日期时间)

“使用 AES-256-CBC 密码和使用 PBKDF2 - 基于密码的密钥派生函数 2 构建的密码对会话密钥进行加密。然后使用 HMAC 密钥对加密的有效负载进行签名。”

我将如何使用 Python 来解决这个问题?最好的库是什么?

以下是我的众多尝试之一(根据@topaco 的评论编辑):

from base64 import b64decode
import hashlib
import pyaes
import os

PASSWORD = b"password provided"
SALT = b"Salt provided"
iv = os.urandom(16)
ciphertext = "message to decode"


passcode = hashlib.pbkdf2_hmac('sha256', PASSWORD, SALT, 1000)
aes = pyaes.AESModeOfOperationCBC(passcode, iv=iv)
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(passcode, iv))
decrypter = encrypter.feed(ciphertext)
decrypter += encrypter.feed()

【问题讨论】:

  • 对于 pyaes 和 AEC-CBC,如果密文长于 1 个块(16 个字节),则应使用 decrypter.feed()herehere。对于其他 Python Crypto 库,请参见例如here.
  • @Topaco - 非常感谢。我还不完全在那里,但我已经根据你的评论更新了我的问题。

标签: python encryption


【解决方案1】:

在贴出的代码中,加解密混淆了。解密需要pyaes.Decrypter

以下代码 sn-p 使用 PBKDF2 生成一个 32 字节的密钥,用于加密明文并使用 AES-256-CBC 解密得到的密文:

from base64 import b64encode
import hashlib
import pyaes
import os

plaintext = 'The quick brown fox jumps over the lazy dog'
password = b'password provided'
salt = b'Salt provided'
iterationCount = 1000

# Create random 16 bytes IV 
iv = os.urandom(16)

# Create 32 bytes key
key = hashlib.pbkdf2_hmac('sha256', password, salt, iterationCount)

# Encryption with AES-256-CBC
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(key, iv))
ciphertext = encrypter.feed(plaintext.encode('utf8'))
ciphertext += encrypter.feed()

# Decryption with AES-256-CBC
decrypter = pyaes.Decrypter(pyaes.AESModeOfOperationCBC(key, iv))
decryptedData = decrypter.feed(ciphertext)
decryptedData += decrypter.feed()

# Display results
def printData(text, data):
    print(text + " (hex):    " + data.hex()) 
    print(text + " (Base64): " + b64encode(data).decode('utf8') + "\n")

printData("16 bytes IV", iv)
printData("32 bytes Key", key)
printData("Ciphertext", ciphertext)
print("Decrypted data (UTF-8): " + decryptedData.decode('utf8') + "\n")

注意:

  • 在您的描述中没有提到摘要和迭代计数。在发布的代码 SHA256 中,使用了 1000 的计数。这两个参数都很关键,即对于解密,必须使用与加密相同的参数。

    另外,IV一般是在加密过程中生成(而不是在解密过程中),并与密文一起传递。

  • 根据您的描述,应用了 PBKDF2、AES-CBC 和 HMAC。通常在这个星座中,生成 PBKDF2 密钥,用于加密明文(这里使用 AES-CBC)并生成 MAC 以验证消息。

    请注意,发布的代码仅提供解密而不提供身份验证。我的代码 sn-p 也没有身份验证。

  • 可以以不同的方式组合各个算法。 Here 讨论了一个可能的变体。尽管这可能是一个评价很高的变体,但这并不意味着底层加密必须坚持下去!

    链接变体将生成的 32 字节密钥拆分为两个 16 字节密钥,用于加密和身份验证。这种方式使用 AES-128 进行加密,这与您描述的 AES-256 加密不同。

    简而言之:要成功执行解密和认证,必须知道某些信息。除了密钥生成,这还包括IV生成、MAC生成(哪些数据用于生成MAC)、数据拼接(密文、IV和MAC的顺序)等。

【讨论】:

    猜你喜欢
    • 2023-02-23
    • 2013-08-11
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多