I have been writing my own implementation of the Advanced Encryption Standard with cipher block chaining in python3 for the last several months, mimicking the OpenSSL command line interface. I can successfully encrypt a message or binary with the OpenSSL implementation of AES and then decrypt it with my python3 program (and vice versa).

I am currently working on PBKDF1 SHA-512 Key Iterations.

OpenSSL generates the key and IV for the password “Sparky” using PBKDF1 SHA-512 like so:

OpenSSL command to use to follow along is this:

printf "hi" | openssl enc -aes-128-cbc -md sha512 -p -S 436172616D656C00 -k “Sparky” 

which means that


In python3, the same Key and IV can be obtained like this:

import hashlib

salt = "436172616D656C00"
passwd = "Sparky”.encode(“utf-8")
salted = passwd + bytes.fromhex(salt)
Key = hashlib.sha512(salted).hexdigest()[0:32]
IV = hashlib.sha512(salted).hexdigest()[32:64]

The key and IV can be found in substrings of the SHA-512 hash.

So I’m not having trouble obtaining the Key and the IV without iterations, but I can’t figure out how to generate the next iteration of the Key (-iter 1)

According to several sources on the internet the iteration function hashes the resultant hash n times. I think something else or something additional is going though because I have tried to hash Hash#0 and the resultant hash does not contain the expected strings for the Key and IV.

So the result of the same OpenSSL command above but with -iter 1 added yields:

printf "hi" | openssl enc -aes-128-cbc -md sha512 -p -S 436172616D656C00 -k "Sparky" -iter 1

results in:


Hash0 (the SHA-512 hash without iterations) in this example is


If I were to take this hash which I know to be good for the 0-th iteration, and hash it again, I would get:


And according to the OpenSSL command with -iter 1 set, the hash should start with


If you would like to see my code, I can upload it to github or my virtual private server and share it.

  • 1
    $\begingroup$ "I have been reverse engineering and writing the Advanced Encryption Standard" - It is a well known standard since more than 20 years. What do you mean by reverse engineering AES? Of were you reverse engineering thy Python library? Again, why? The source code of many Python libraries is open source, means you can get the source code for free and there is nothing to reverse engineer. $\endgroup$
    – mentallurg
    Commented Mar 28, 2021 at 20:17
  • 1
    $\begingroup$ "the goal is to figure out what OpenSSL is doing when it iterates through derived keys" - Just look at the source code of OpenSSL and you will see that. $\endgroup$
    – mentallurg
    Commented Mar 28, 2021 at 21:37
  • 1
    $\begingroup$ I haven't said it is Python. I said it is open source. See the Git repository of OpenSSL. $\endgroup$
    – mentallurg
    Commented Mar 28, 2021 at 23:20
  • 1
    $\begingroup$ I propose we assume the OP wanted to write: For several months, I've been reverse-engineering openssl's Advanced Encryption Standard with cipher block chaining encryption, and rewriting it in python3. @mentallurg $\endgroup$
    – fgrieu
    Commented Mar 29, 2021 at 9:51
  • 1
    $\begingroup$ OP: specifying enc ... -iter 1 automatically uses PBKDF2 (which uses HMAC) and not EVP_BytesToKey (which uses a plain hash); see the man page on your system or on the web. @MaartenBodewes: in some cases including this one EVP_BytesToKey is almost PBKDF1; see my comparison at crypto.stackexchange.com/questions/3298/… . $\endgroup$ Commented Mar 30, 2021 at 1:04

1 Answer 1


Thank you all for all of the excellent help. I am happy to say that with your help I have found the answer to my initial question and more. The code below accepts a [string] password, [hex string] salt, [int] key size, and [int] iteration count, and returns a tuple containing the correct key and IV for PBKDF2. OpenSSL PBKDF2 uses 10,000 iterations by default. Leave the salt in the command as double quotes if there is no salt.


printf "Today is a good day!" | openssl enc -aes-192-cbc -md sha512 -pbkdf2 -S 436172616d656c73 -k "Sparky" -p

results in:




The same salt, key, and IV can be obtained by using the code and class below:

from pbkdf2 import kdf

key, iv = kdf.pbkdf2(“Sparky”,”436172616D656C73”,192,10000)

results in:

key=37A12300EF8D3442B266B41172154DFE0836803C4257AFB6 iv=E2FC1F1DF27AB4A6F303EDD6537EEE53

“Sparky” is the password “436172616D656C73” is the salt 192 is the AES-CBC key size 10,000 is the number of hmac iterations (pbkdf2)

And here is the Python3 code (pbkdf2.py).

Import hashlib

import hmac

class kdf:

def pbkdf2(passwd, salt, size, iterations):

    dictionary = {128:((0,32),(32,64)), 192:((0,48),(48,80)), 256:((0,64),(64,96))}

    k = b = hmac.new(passwd.encode("utf-8"), bytes.fromhex(salt) + b'\x00\x00\x00\x01' if len(salt) > 0 else b'\x00\x00\x00\x01', hashlib.sha512).digest()

    for i in range(2, iterations + 1):
        b = hmac.new(passwd.encode("utf-8"), b, hashlib.sha512).digest()
        k = bytes(i ^ j for i, j in zip(k, b))

    key = k.hex()[dictionary.get(size)[0][0]:dictionary.get(size)[0][1]]
    _iv = k.hex()[dictionary.get(size)[1][0]:dictionary.get(size)[1][1]]

    return key,_iv
  • $\begingroup$ FYI Python 3.4 up hashlib provides pbkdf2 which usually is optimized $\endgroup$ Commented Apr 1, 2021 at 0:01
  • 1
    $\begingroup$ @dave_thompson_085 I’m writing this program for my resume so I’m trying to write all of the code from scratch. $\endgroup$
    – B345T
    Commented Apr 1, 2021 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.