Search code examples
phpencryptionphp-openssl

PHP openssl_decrypt returns strange output about 10% of the time


Using all the knowledge I could find on the internet I came up with a salt openssl encrypt and decrypt function. It works 90% of the time but every once in a wile the decrypt returns wither an empty sting or random bytes that have nothing to do with the encrypted data. The code I'm using is:

function Encrypt($subject, $method, $saltLength, $key){
    if($method==0){
        $salt=random_bytes($saltLength);
        $key=hash('sha256', $salt.$key);
        $iv=random_bytes(16);
        $encrypt=base64_encode(openssl_encrypt($subject, 'aes-256-ctr', $key, 0, $iv));
        $return=base64_encode("$method:$salt:$iv:$encrypt");
    }
    return($return);
}
function Decrypt($subject, $key){
    $components = explode( ':', base64_decode($subject));
    $method=$components[0];
    if($method==0){
        $salt=$components[1];
        $key = hash('sha256', $salt.$key);
        $iv=$components[2];
        $encrypt=base64_decode($components[3]);
        $return=(openssl_decrypt($encrypt, 'aes-256-ctr', $key, 0, $iv));
    }
    return($return);
}

$testE=Encrypt('Test', 0, 20, 'Key0');
var_dump($testE);
echo('<br><br>');
$testD=Decrypt($testE, 'Key0');
var_dump($testD);
echo('<br><br>');
$testD=Decrypt($testE, 'Key0');
var_dump($testD);
echo('<br><br>');

And an example of the faulty results for this code would be:

string(72) "MDrVsJAIE8OFjyM6y5dt+xkij5m/rTrHTnzeWs0IRrTKvNR1L7wfOmJrSlNRWFIzUFQwPQ==" 

string(1) "�" 

string(1) "�" 

Or the return of a completely empty string:

string(72) "MDrQ+5c83vJXnva1OjrbJ2RWGjU5ajrwCn+qCneIIOqh48Gt0JmbOllsZFVUMHRuUFQwPQ==" 

string(0) "" 

string(0) "" 

The reason I did the decrypt twice is to see if the fault is in the decrypt or the encrypt, the results clearly show that the encrypt is faulty in some way.

My question is what is causing this faulty encryption of the data? & can I improve this method and make it even more secure ?


Solution

  • While not the answer to why it is happening, oftentimes the result is what is most important.

    If that is the case, then, if you get 90% accuracy, a while loop will quickly get you on your way.....

    while(strlen($testD) < 5) {
        $testD=Decrypt($testE, 'Key0');
    }
    

    If your goal is to figure out what causes the minor faults, then you may have to look much deeper into the core code. However, in my position, "get it done and move on" is often what the bosses say, so finding a working solution for gathering the info is often what I have to work with.