https://security.stackexchange.com/questions/29106/openssl-recover-key-and-iv-by-passphrase
Following code steal from [Simple python functions that provide openssl -aes-256-cbc compatible encrypt/decrypt] (http://joelinoff.com/blog/?p=885)
# ================================================================
# get_key_and_iv
# ================================================================
def get_key_and_iv(password, salt, klen=32, ilen=16, msgdgst='md5'):
'''
Derive the key and the IV from the given password and salt.
This is a niftier implementation than my direct transliteration of
the C++ code although I modified to support different digests.
CITATION: http://stackoverflow.com/questions/13907841/implement-openssl-aes-encryption-in-python
@param password The password to use as the seed.
@param salt The salt.
@param klen The key length.
@param ilen The initialization vector length.
@param msgdgst The message digest algorithm to use.
'''
# equivalent to:
# from hashlib import <mdi> as mdf
# from hashlib import md5 as mdf
# from hashlib import sha512 as mdf
mdf = getattr(__import__('hashlib', fromlist=[msgdgst]), msgdgst)
password = password.encode('ascii', 'ignore') # convert to ASCII
try:
maxlen = klen + ilen
keyiv = mdf(password + salt).digest()
tmp = [keyiv]
while len(tmp) < maxlen:
tmp.append( mdf(tmp[-1] + password + salt).digest() )
keyiv += tmp[-1] # append the last byte
key = keyiv[:klen]
iv = keyiv[klen:klen+ilen]
return key, iv
except UnicodeDecodeError:
return None, None
The decent implementation from the discussion.
import hashlib, binascii
from passlib.utils.pbkdf2 import pbkdf1
def hasher(algo, data):
hashes = {'md5': hashlib.md5, 'sha256': hashlib.sha256,
'sha512': hashlib.sha512}
h = hashes[algo]()
h.update(data)
return h.digest()
# pwd and salt must be bytes objects
def openssl_kdf(algo, pwd, salt, key_size, iv_size):
if algo == 'md5':
temp = pbkdf1(pwd, salt, 1, 16, 'md5')
else:
temp = b''
fd = temp
while len(fd) < key_size + iv_size:
temp = hasher(algo, temp + pwd + salt)
fd += temp
key = fd[0:key_size]
iv = fd[key_size:key_size+iv_size]
print('salt=' + binascii.hexlify(salt).decode('ascii').upper())
print('key=' + binascii.hexlify(key).decode('ascii').upper())
print('iv=' + binascii.hexlify(iv).decode('ascii').upper())
return key, iv
openssl_kdf('md5', b'test', b'\xF6\x81\x8C\xAE\x13\x18\x72\xBD', 32, 16)
generates the same output as:
openssl enc -aes-256-cbc -P -pass pass:test -S F6818CAE131872BD
openssl_kdf('sha256', b'test', b'\xF6\x81\x8C\xAE\x13\x18\x72\xBD', 32, 16)
generates the same output as:
openssl enc -aes-256-cbc -P -pass pass:test -S F6818CAE131872BD -md SHA256
A nodes.js implementation with MD5 only https://github.com/crypto-browserify/EVP_BytesToKey/blob/master/index.js