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
salt=436172616D656C00
key=D0F4428B02B161F125FF3FA1FDD98AFE
IV=6F26A9F743FAD01BBC68417A398359A6
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:
salt=436172616D656C00
key=6354F3AE1EEF92EAE4406759A5882B46
IV=8ACE6C6AE7E1EBDEE45342D0C9087422
Hash0 (the SHA-512 hash without iterations) in this example is
d0f4428b02b161f125ff3fa1fdd98afe6f26a9f743fad01bbc68417a398359a675fe9c7bbf87315f7e4d2b8ef40e578a86eec2acdd95511329af2a9d69f59e76
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:
35841649790d6ce2d0ac2b3fe338aba5121858494006aa098f84e06f21587b77adf14f1c5c0a1530db628acfd5d6123d46e449b9619a41a5a6e32ab9230a31e4
And according to the OpenSSL command with -iter 1 set, the hash should start with
6354F3AE1EEF92EAE4406759A5882B468ACE6C6AE7E1EBDEE45342D0C9087422
If you would like to see my code, I can upload it to github or my virtual private server and share it.
The key and IV is derived by concatenating D_1, D_2, etc until enough data is available for the key and IV. D_i is defined as:
data is a buffer containing datal bytes which is used to derive the keying data. count is the iteration count to use. The derived key and IV will be written to key and iv respectively.
D_i = HASH^count(D_(i-1) || data || salt)
– B345T Mar 29 '21 at 01:37EVP_BytesToKeyis not a PBKDF described in PKCS#5 (PBE) which defines PBKDF1 and PBKDF2; it's similar but proprietary to OpenSSL. – Maarten Bodewes Mar 29 '21 at 07:44enc ... -iter 1automatically uses PBKDF2 (which uses HMAC) and notEVP_BytesToKey(which uses a plain hash); see the man page on your system or on the web. @MaartenBodewes: in some cases including this oneEVP_BytesToKeyis almost PBKDF1; see my comparison at https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/#35614 . – dave_thompson_085 Mar 30 '21 at 01:04enc ... -iter 1in 1.1.1 does NOT give the warning about 'deprecated key derivation used' which should clue you in that PBKDF2 was used (andEVP_BytesTokeywas not) – dave_thompson_085 Mar 30 '21 at 02:06