|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-12-25 19:04 UTC] anthon dot pang at gmail dot com
Description:
------------
openssl_error_string() returns a dubious message, "error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length" when decrypting even though the payload was successfully decrypted
(In the test script, the payload was produced using sjcl.)
Test script:
---------------
<?php
$password = 'password';
$input = json_decode('{"iv":"A0DOQPxWAlJ5LHjoyg==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Kk+ws1Xj0Xo=","ct":"NCPpLCHLLO5mBOGpSUpHdXPgKZA="}', true);
$digest = hash_pbkdf2('sha256', $password, base64_decode($input['salt']), $input['iter'], 0, true);
$cipher = $input['cipher'] . '-' . $input['ks'] . '-' . $input['mode'];
$ct = substr(base64_decode($input['ct']), 0, - $input['ts'] / 8);
$tag = substr(base64_decode($input['ct']), - $input['ts'] / 8);
$iv = base64_decode($input['iv']);
$adata = $input['adata'];
$dt = openssl_decrypt($ct, $cipher, $digest, OPENSSL_RAW_DATA, $iv, $tag, $adata);
var_dump($dt);
while ($msg = openssl_error_string()) {
echo $msg . "\n";
}
Expected result:
----------------
string(12) "Hello World!"
Actual result:
--------------
string(12) "Hello World!"
error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Nov 08 02:00:02 2025 UTC |
What are we missing here? I got the same warning when I changed $password to a 16 character string; and $digest is a hash, so it's always a 32 byte string. <?php $password = 'passwordpassword'; $input = json_decode('{"iv":"A0DOQPxWAlJ5LHjoyg==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"iGC2RaDrxUk=","ct":"3X3DKTIIE0VN0SzC9gH8k4wK3DNAsA=="}', true); $digest = hash_pbkdf2('sha256', $password, base64_decode($input['salt']), $input['iter'], 0, true); $cipher = $input['cipher'] . '-' . $input['ks'] . '-' . $input['mode']; $ct = substr(base64_decode($input['ct']), 0, - $input['ts'] / 8); $tag = substr(base64_decode($input['ct']), - $input['ts'] / 8); $iv = base64_decode($input['iv']); $adata = $input['adata']; $dt = openssl_decrypt($ct, $cipher, $digest, OPENSSL_RAW_DATA, $iv, $tag, $adata); var_dump($dt); while ($msg = openssl_error_string()) { echo $msg . "\n"; }First of all I have to correct myself as it's of course about algorithm key length not block size even it is the same for aes-128 (it means 16 bytes). But for aes-256 the block size is still 128 but key size is 256 (which would be btw fine for your example) What you are doing wrong is passing 32 bytes digest to openssl_decrypt. It needs to be 16 if you use aes-128 and you don't want to see the error. What happen internally is that it tries to set cipher key length but it won't succeed for AES as its key length cannot be changed (that's why the OpenSSL error). Then the value is trimmed so it means that this openssl_decrypt($ct, $cipher, $digest, OPENSSL_RAW_DATA, $iv, $tag, $adata); is exactly the same as openssl_decrypt($ct, $cipher, substr($digest, 0, 16), OPENSSL_RAW_DATA, $iv, $tag, $adata); The second will just not give you an error. Instead of substr you can specify output size already in hash_pbkdf2. In your case: hash_pbkdf2('sha256', $password, base64_decode($input['salt']), $input['iter'], 16, true)