Reputation: 4306
I have a string encrypted using this command :
echo 'hello world' | openssl enc -pass pass:MYPASSWORD -aes-256-cbc -md sha3-256 -pbkdf2 -iter 10000 -out crypt
that is stored in a crypt
file
I would like to know how to decrypt this file in php
I understand I need to use a combination of these two functions
openssl_pbkdf2
openssl_decrypt
However I fail to understand
openssl_pbkdf2
requires a salt
parameter and key_length
openssl_decrypt
requires a iv
parameterhow do i provide these 3 parameters ?
Upvotes: 0
Views: 1121
Reputation: 4306
Ok as the information were scatered all accross the internet I gather all it here, hoping it will save somebody times in the future
if you just want the code, jump to the end
it took me quite some time to understand this fact. As this question state, the format is not based on any standard.
so you need to extract these values from the file, as of openssl 1.1.1 the format is the following
(you can find the exact implementation here: https://github.com/openssl/openssl/blob/f7d2427ac3404ce1ed555bf61885eeb0432b5789/apps/enc.c )
Salted__
The IV is not a random one, uncorrelated from anything. The IV is derivated from the password
openssl_pbkdf2
returns 1 string, but this is BOTH the IV and the KEY concatenated (it's not explained in the php documentation) but you can see it here in the c code
Once you get this it's actually straitghforward
openssl_pbkdf2
which gives you key
+ iv
key
and iv
in dedicated variableopenssl_decrypt
along with the ciphered text (stripped from the salt header)Here's the code
<?php
$content = file_get_contents('crypt');
$salt = mb_substr($content, 8, 8, '8bit');
$derivatedKey = openssl_pbkdf2(
'MYPASSOWRD',
$salt,
// key_length is 48 bytes because
// the key itself is 32 bytes (256 bits, because aes 256)
// and the IV is 16 bytes (returned by openssl_cipher_iv_length)
// so 32+16 -> 48
key_length: 48,
// 10000 is a of 2021 the amount recommended by the NIST
// see https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63b.pdf section 5.1.1.2
// quote:
// For PBKDF2, the cost factor is an iteration count: the more times the PBKDF2 function is
// iterated, the longer it takes to compute the password hash. Therefore, the iteration count
// SHOULD be as large as verification server performance will allow, typically at least 10,000
// iterations.
iterations: 10000,
// for the same reason we use sha3-256
// quote:
// A memory-hard function SHOULD be used because it increases the cost of an attack.
// The key derivation function SHALL use an approved one-way function such as
// Keyed Hash Message Authentication Code (HMAC) [FIPS 198-1],
// any approved hash function in SP 800-107, Secure Hash Algorithm 3 (SHA-3)
digest_algo: 'sha3-256'
);
// the key itself is 32 bytes (i.e 256 bits, because aes *256*)
$key = mb_substr($derivatedKey, 0, 32, '8bit');
$iv = mb_substr($derivatedKey, 32, openssl_cipher_iv_length('aes-256-cbc'), '8bit');
// 16 is the 8 bytes of `Salted__` and 8 bytes of salt itself
$cypherText = mb_substr($content, 16, encoding: '8bit');
echo openssl_decrypt($cypherText, 'aes-256-cbc', $key, iv: $iv);
Upvotes: 2