如何使用使用OpenSSL加密的PyCrypto解密某些内容?

如何使用使用OpenSSL加密的PyCrypto解密某些内容?,openssl,pycrypto,Openssl,Pycrypto,我有几个使用OpenSSL加密的字符串。例如: $ echo "original string" | openssl aes-256-cbc -p -a -pass pass:secret salt=B898FE40EC8155FD key=4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C iv =EFA6105F30F6C462B3D135725A6E1618 U2FsdGVkX1+4mP5A7IFV/VcgRs4

我有几个使用OpenSSL加密的字符串。例如:

$ echo "original string" | openssl aes-256-cbc -p -a -pass pass:secret
salt=B898FE40EC8155FD
key=4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv =EFA6105F30F6C462B3D135725A6E1618
U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy
我想用Python解密这些东西。我正在尝试使用PyCrypto。以下是使用上述数据的exmaple脚本:

from base64 import b64decode, b64encode
from hashlib import md5
from Crypto.Cipher import AES

secret = 'secret'
encoded = 'U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy'
encrypted = b64decode(encoded)
salt = encrypted[8:16]
data = encrypted[16:]
key = md5(secret + salt).hexdigest()
iv = md5(key + secret + salt).hexdigest()[0:16] # which 16 bytes?
dec = AES.new(key, AES.MODE_CBC, iv)
clear = dec.decrypt(data)

try:
    salt_hex = ''.join(["%X" % ord(c) for c in salt])
    print 'salt:     %s' % salt_hex
    print 'expected: %s' % 'B898FE40EC8155FD'
    print 'key:      %s' % key.upper()
    print 'expected: %s' % '4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C'
    print 'iv:       %s' % iv
    print 'expected: %s' % 'EFA6105F30F6C462B3D135725A6E1618'
    print 'result: %s' % clear
except UnicodeDecodeError:
    print 'decryption failed'
以下是输出:

salt:     B898FE40EC8155FD
expected: B898FE40EC8155FD
key:      4899E518743EB0584B0811AE559ED8AD
expected: 4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv:       17988376b72f4a81
expected: EFA6105F30F6C462B3D135725A6E1618
decryption failed
您可以看到salt匹配,密钥匹配OpenSSL显示的前半部分,因此我似乎走对了方向,但有两个主要问题:

  • 为什么OpenSSL中的
    key
    iv
    的值是PyCrypto(大概是AES256)允许的两倍
  • 如何生成正确的值?我使用的技术来自,但是如果IV总是与块大小(16字节)匹配,MD5将永远无法工作。即使我能找出另一半密钥的来源,PyCrypto也会因为太长而拒绝它

  • 我意识到我也需要移除填充物,但为了简洁起见,我省略了它。

    您有三个问题:

  • 在OpenSSL中使用AES256(32字节密钥),在python代码中使用AES128(16字节密钥)
  • IV的计算是错误的。OpenSSL的密钥派生函数中的每一步都使用最后计算的MD5摘要
  • 你混淆了二进制和十六进制表示法。在可视化之前,将任何十六进制的转换作为最后一步
  • 以下代码应正确:

    from base64 import b64decode, b64encode
    from binascii import hexlify
    from Crypto.Cipher import AES
    from Crypto.Hash import MD5
    
    secret = 'secret'
    encoded = 'U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy'
    encrypted = b64decode(encoded)
    salt = encrypted[8:16]
    data = encrypted[16:]
    
    # We need 32 bytes for the AES key, and 16 bytes for the IV
    def openssl_kdf(req):
        prev = ''
        while req>0:
            prev = MD5.new(prev+secret+salt).digest()
            req -= 16
            yield prev
    mat = ''.join([ x for x in openssl_kdf(32+16) ])
    key = mat[0:32]
    iv  = mat[32:48]
    
    dec = AES.new(key, AES.MODE_CBC, iv)
    clear = dec.decrypt(data)
    
    try:
        salt_hex = ''.join(["%X" % ord(c) for c in salt])
        print 'salt:     %s' % salt_hex
        print 'expected: %s' % 'B898FE40EC8155FD'
        print 'key:      %s' % hexlify(key).upper()
        print 'expected: %s' % '4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C'
        print 'iv:       %s' % hexlify(iv).upper()
        print 'expected: %s' % 'EFA6105F30F6C462B3D135725A6E1618'
        print 'result:   %s' % clear
    except UnicodeDecodeError:
        print 'decryption failed'
    

    你有三个问题:

  • 在OpenSSL中使用AES256(32字节密钥),在python代码中使用AES128(16字节密钥)
  • IV的计算是错误的。OpenSSL的密钥派生函数中的每一步都使用最后计算的MD5摘要
  • 你混淆了二进制和十六进制表示法。在可视化之前,将任何十六进制的转换作为最后一步
  • 以下代码应正确:

    from base64 import b64decode, b64encode
    from binascii import hexlify
    from Crypto.Cipher import AES
    from Crypto.Hash import MD5
    
    secret = 'secret'
    encoded = 'U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy'
    encrypted = b64decode(encoded)
    salt = encrypted[8:16]
    data = encrypted[16:]
    
    # We need 32 bytes for the AES key, and 16 bytes for the IV
    def openssl_kdf(req):
        prev = ''
        while req>0:
            prev = MD5.new(prev+secret+salt).digest()
            req -= 16
            yield prev
    mat = ''.join([ x for x in openssl_kdf(32+16) ])
    key = mat[0:32]
    iv  = mat[32:48]
    
    dec = AES.new(key, AES.MODE_CBC, iv)
    clear = dec.decrypt(data)
    
    try:
        salt_hex = ''.join(["%X" % ord(c) for c in salt])
        print 'salt:     %s' % salt_hex
        print 'expected: %s' % 'B898FE40EC8155FD'
        print 'key:      %s' % hexlify(key).upper()
        print 'expected: %s' % '4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C'
        print 'iv:       %s' % hexlify(iv).upper()
        print 'expected: %s' % 'EFA6105F30F6C462B3D135725A6E1618'
        print 'result:   %s' % clear
    except UnicodeDecodeError:
        print 'decryption failed'
    

    效果很好。谢谢我想知道第3点,但由于我得到的是钥匙前半部分的正确值,我认为它一定是正确的。(另外,
    AES.new
    需要一个字符串作为键。)效果很好。谢谢我想知道第3点,但由于我得到的是钥匙前半部分的正确值,我认为它一定是正确的。(另外,
    AES.new
    需要一个字符串作为密钥。)