0

I encrypted a file using openssl using the below command

cat input.txt
hello world
openssl aes-256-cbc -pass pass:'00112233445566778899aabbccddeeff' -iv a2a8a78be66075c94ca5be53c8865251 -nosalt -base64 -in input.txt -out output.txt
cat output.txt
pt7DqtAwtTjPbTlzVApucQ==

How can i decrypt the file using python Crypto package. I tried the below and it didn't work.

>>> from Crypto.Cipher import AES
>>> from base64 import b64decode
>>> with open('output.txt') as f:
...     aes = AES.new('00112233445566778899aabbccddeeff', AES.MODE_CBC, IV='a2a8a78be66075c94ca5be53c8865251'.decode('hex'))
...     print(aes.decrypt(b64decode(f.read())))
...
L�|�L   ��O�*$&9�

I need a way to encrypt a file using openssl aes-256-cbc cipher and decrypt in python

rogue-one
  • 11,259
  • 7
  • 53
  • 75

1 Answers1

4

The password is not the key. Openssl uses EVP_BytesToKey to create an appropriate key (& IV, if necessary) from the password and the salt.

As James K Polk mentions in a comment, you can use the -P (or -p) option to tell Openssl to print the key (in hex ), which you can then pass to Crypto.Cipher. Alternatively, you can implement EVP_BytesToKey in Python, as shown below. This is a simplified version of EVP_BytesToKey that uses no salt, and the default value of 1 for the count arg.

As the EVP_BytesToKey docs state, this is a rather weak password derivation function. As the hashlib docs mention, modern password derivation normally performs hundreds of thousands of hashes to make password hashing attacks very slow.

We also need a function to remove the PKCS7 padding from the decrypted data bytes. The unpad function below simply assumes that the padding data is valid. In real software the unpad function must verify that the padded data is valid to prevent padding-based attacks. My unpad function also assumes the data has been encoded as UTF-8 bytes and decodes the unpadded data to text.

from __future__ import print_function
from Crypto.Cipher import AES
from base64 import b64decode
from hashlib import md5

def evp_simple(data):
    out = ''
    while len(out) < 32:
        out += md5(out + data).digest()
    return out[:32]

def unpad(s):
    offset = ord(s[-1])
    return s[:-offset].decode('utf-8')

iv = 'a2a8a78be66075c94ca5be53c8865251'.decode('hex')
passwd = '00112233445566778899aabbccddeeff'
key = evp_simple(passwd)
print('key', key.encode('hex'))

aes = AES.new(key, AES.MODE_CBC, IV=iv)

data = b64decode('pt7DqtAwtTjPbTlzVApucQ==')

raw = aes.decrypt(data)
print(repr(raw), len(raw))
plain = unpad(raw)
print(repr(plain), len(plain))

output

key b4377f7babf2991b7d6983c4d3e19cd4dd37e31af1c9c689ca22e90e365be18b
'hello world\n\x04\x04\x04\x04' 16
u'hello world\n' 12

That code will not run on Python 3, so here's a Python 3 version.

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

def evp_simple(data):
    out = b''
    while len(out) < 32:
        out += md5(out + data).digest()
    return out[:32]

def unpad(s):
    offset = s[-1]
    return s[:-offset].decode('utf-8')

iv = bytes.fromhex('a2a8a78be66075c94ca5be53c8865251')
passwd = b'00112233445566778899aabbccddeeff'
key = evp_simple(passwd)

aes = AES.new(key, AES.MODE_CBC, IV=iv)

data = b64decode('pt7DqtAwtTjPbTlzVApucQ==')

raw = aes.decrypt(data)
print(repr(raw), len(raw))
plain = unpad(raw)
print(repr(plain), len(plain))

output

b'hello world\n\x04\x04\x04\x04' 16
'hello world\n' 12
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182