Как я могу расшифровать что-то с PyCrypto, который был зашифрован с использованием OpenSSL? - PullRequest
1 голос
/ 10 января 2012

У меня есть несколько строк, которые были зашифрованы с использованием 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. Вот примерный скрипт, использующий приведенные выше данные:

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

Вы можете видеть, что соль совпадает, а ключ соответствует первой половине того, что показывает OpenSSL, поэтому я, кажется, на правильном пути, но есть два основных вопроса:

  1. Почему значения для key и iv из OpenSSL в два раза больше, чем позволяет PyCrypto (и предположительно AES256)?
  2. Как мне генерировать правильные значения? Техника, которую я использую, была взята из блога , но если IV всегда должен соответствовать размеру блока (16 байт), MD5 никогда не будет работать. И даже если бы я мог выяснить, откуда взялась другая половина ключа, PyCrypto отказался бы от этого за то, что он слишком длинный.

Я понимаю, что мне нужно будет также удалить отступы, но я оставил это для краткости.

1 Ответ

8 голосов
/ 15 января 2012

У вас есть три проблемы:

  1. Вы используете AES256 (32-байтовый ключ) в OpenSSL и AES128 (16-байтовый ключ) в своем коде Python.
  2. IV вычисление неверно. Каждый шаг в функции получения ключа OpenSSL использует дайджест MD5, вычисленный последним.
  3. Вы смешиваете двоичное и шестнадцатеричное представление. Сохраняйте любое преобразование в шестнадцатеричное как последний шаг перед визуализацией.

Следующий код должен быть правильным:

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'
...