openssl_encrypt creating a different code from an array value that is not decryptable

Viewed 78

Valuable assistance from members will be greatly appreciated.

I have just begun working on encrypting data stored in MySQL database tables, learning how to encrypt 2-dimensional array values that will be uploaded into tables.

The first problem I am now encountering is that openssl_encrypt is generating different, not decryptable codes compared to when it is generating codes directly from plain text which the latter decrypts without problems.

The second problem is I can’t get the ‘for () {continue} ‘ command to work properly, since I do not want columns or fields [0] and [1] to be encrypted, which is displayed in the this resulting webpage: https://secur-a-doc.com/php-sprdsht-sample6.0

The PHP code I’m using to test is as follows:

<?php
    header( 'Content-Type: text/html; charset=utf-8' );

    echo "Below is a 3-row, 2-dimensional array displaying sections, fields and values";
    $bgyaa = array (
    '[0]' => array ( 
        '[0]' => '2',
        '[1]' => 'bgyaa.ZBRDE5aTZsUGZmWQ',
        '[2]' => '12346',
        '[3]' => 'John Citizen',
        '[4]' => 'noy-pic-1.jpg',
        '[5]' => 'noy-pic-2.jpg',
        '[6]' => 'RESIDENT',
        '[7]' => '777 Sarangani Street',
        '[8]' => '03/27/84',
        '[9]' => 'B',
        '[10]' => '287-865-194',
        '[11]' =>' '),
    '[1]' => array ( 
        '[0]' => '3',
        '[1]' => 'bgyaa.ZMTEtpTC5qVGNTUQ',
        '[2]' => '12347',
        '[3]' => 'Dominador Pridas',
        '[4]' => 'domeng-pic-1.jpg',
        '[5]' => 'domeng-pic-2.jpg',
        '[6]' => 'TENANT',
        '[7]' => '321 Mango Drive',
        '[8]' => '03/27/84',
        '[9]' => 'B',
        '[10]' => '287-865-194',
        '[11]' =>' ' ),
    '[2]' => array ( 
        '[0]' => '4',
        '[1]' => 'bgyaa.ZpcEpteDJOZlBVQQ',
        '[2]' => '12348',
        '[3]' => 'Taylor Swift',
        '[4]' => 'taylorswift-pic-1.jpg',
        '[5]' => 'taylorswift-pic-2.jpg',
        '[6]' => 'TENANT',
        '[7]' => '826 Anonas Street',
        '[8]' => '03/27/84',
        '[9]' => 'B',
        '[10]' => '287-865-194',
        '[11]' =>' ' ), 
        );


    echo "<pre>";
    foreach ($bgyaa as $section => $items)
        {
            foreach ($items as $key => $value)
            {
                echo "$section:\t$key:\t$value<br/>";
            }
        }                       

    $key="c871754451c2b89d4cdb1b14705be457b7fabe967af6a559f3d20c79ded5b5ff18675e56fa77d75fdcd47c34271bb74e372d6d04652f7aa6f529a838ca4aa6bd";
    $iv= "f1e64276d153ad8a"; // this iv value is 16 bytes of hex characters
    $cipher = "aes-256-cbc-hmac-sha256";

    if (in_array($cipher, openssl_get_cipher_methods()))
    {
            $ivlen = openssl_cipher_iv_length($cipher);
        $plain_text = 'John Citizen';
        $encrypted = openssl_encrypt($plain_text, $cipher, $key, $options=0, $iv);
        echo "<br/><br/><br/>Bellw are from direct encrytion of the plain text name<br/>";
        echo "plain text is John Citizen " . "<br/>";
        echo "encrypted text is " . $encrypted . "<br/><br/><br/>";
    }

        echo "And then below are openssl_encrypt (cipher aes-256-cbc) encrypted array codes beside their plain text original values<br/>";
        echo "NOTE that the encrypted code q+vG/KXTZsYExxV5yX7DFw== for the name John Citizen is different to the above, and not decryptable<br/><br/>";
        foreach ($bgyaa as $section => $items)     // section is the sub array (starts from 0)
            // items are rows
        {
            foreach ($items as $key => $value) 
            //key represents field or column
            //value represents the values of row
            {
            if ($items < 2) 
                {
                    continue; //begin from key or field 4
                    }
                if (in_array($cipher, openssl_get_cipher_methods()))
                    {
                        $ivlen = openssl_cipher_iv_length($cipher);             
                        $encrypted = openssl_encrypt($value, $cipher, $key, $options=0, $iv);
                    }                   
                    echo $key . " : " . $encrypted . "  :  " . $value . "<br/>";                            
            }
    }
     
    echo "</pre>";   

?>
1 Answers

You're overwriting the encryption $key in your for loop.

See:

$key="c871754451c2b89d4cdb1b14705be457b7fabe967af6a559f3d20c79ded5b5ff18675e56fa77d75fdcd47c34271bb74e372d6d04652f7aa6f529a838ca4aa6bd";

...

foreach ($bgyaa as $section => $items) // section is the sub array (starts from 0)
    // items are rows
    {
        foreach ($items as $key => $value) {
            // Now the encryption $key has been overwritten with the index. 
            // In your example, to decrypt 'John Citizen', 
            // You would need to decrypt using '[3]' as the encryption key. 
        }
    }
}

Just change the bottom for loop to use a different value for the index variable, like this:

foreach ($items as $index => $value) // changed $key to $index
{
    //key represents field or column
    //value represents the values of row
    if ($items < 2) 
    {
        continue; //begin from key or field 4
    }
    if (in_array($cipher, openssl_get_cipher_methods()))
    {
        $ivlen = openssl_cipher_iv_length($cipher);             
        $encrypted = openssl_encrypt($value, $cipher, $key, $options=0, $iv);
    }    
    // Changed to also use $index instead of $key.   
    echo $index . " : " . $encrypted . "  :  " . $value . "<br/>";                            
}

As for your continue problem, do you actually want your indexes to be formatted as strings like [0] and [1] and not just numbers? If you want numerical indexes, you should just format the arrays like this:

0 => array ( 
    0 => '2',
    1 => 'bgyaa.ZBRDE5aTZsUGZmWQ',
    2' => '12346',
    3 => 'John Citizen'
)

Then you can change the continue condition to be :

if ($index < 2) 
{
    continue; //begin from key or field 4
}

Otherwise, if you want to keep the formatting as literal strings like "[2]", then you'd need to remove the brackets before doing the comparison.

if (str_replace(['[',']'], '', $index) < 2) 
{
    continue; //begin from key or field 4
}

To summarize, this is what I'd recommend for the final change with everything applied:

foreach ($items as $index => $value) // changed $key to $index
{
    //key represents field or column
    //value represents the values of row
    //if ($index < 2)  // UNCOMMENT IF YOU USE NUMERICAL INDEXES
    if (str_replace(['[',']'], '', $index) < 2) // KEEP IF YOU USE STRING INDEXES WITH BRACKETS
    {
        continue; //begin from key or field 4
    }
    if (in_array($cipher, openssl_get_cipher_methods()))
    {
        $ivlen = openssl_cipher_iv_length($cipher);             
        $encrypted = openssl_encrypt($value, $cipher, $key, $options=0, $iv);
    }    
    // Changed to also use $index instead of $key.   
    echo $index . " : " . $encrypted . "  :  " . $value . "<br/>";                            
}
Related