3

I currently have a PHP application that uses data-at-rest encryption to store sensitive information onto a database that I can later decrypt for use in my application.

Here is the current code I'm using. I kno...i kno...it's not very secure at all but it works fine for what I using it for. I'm not storing credit card numbers, social security number, or anything like that. Mainly just names and addresses.

define('CRYPTO_KEY', 'some-key');

function decrypt($val){
    $val = urlencode($val);
    $data = base64_decode(urldecode($val));
    $iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
    $val = rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_128,
            hash('sha256', CRYPTO_KEY, true),
            substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
            MCRYPT_MODE_CBC,
            $iv
        ),
    "\0"
    );
    return $val;
}

function enc($val){
    $iv = mcrypt_create_iv(
        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
        MCRYPT_DEV_URANDOM
    );

    $val = urlencode(base64_encode(
        $iv .
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            hash('sha256', CRYPTO_KEY, true),
            $selection,
            MCRYPT_MODE_CBC,
            $iv
        )
    )); 
    return $val;
}

The problem I'm running into is that I just upgraded from PHP 5.5 to PHP 7.1. Now in PHP 7.1 my encrypt/decrypt function throws a ton of warnings out stating that the following function are deprecated:

  • mcrypt_get_iv_size()
  • mcrypt_create_iv()
  • mcrypt_encrypt()
  • mcrypt_decrypt()

I was doing some research and found that the new recommendations are to use libraries like libsodium or OpenSSL found HERE

I looked into both but the documentation is way too technical for me to understand. I can't even figure out how to install libsodium, let alone use it.

My question is, does anyone have a decent encrypt/decrypt function that is compatible with PHP 7.1 or higher they'd be willing to share?

Better yet, would anyone be willing to provide instructions on how to use libsodium or OpenSSL for data encryption/decryption?

FYI - I'm currently using a shared hosting platform with cPanle. I have composer installed and understand how to install packages through it. I have never used PECL or PEAR

Austin
  • 1,619
  • 7
  • 25
  • 51
  • 2
    Note: http://php.net/manual/en/function.mcrypt-encrypt.php and http://php.net/manual/en/function.mcrypt-decrypt.php states ***Warning** This function has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.* – Funk Forty Niner Oct 19 '17 at 19:24
  • 6
    @fred I know that's why I'm reaching out to the community for a better way – Austin Oct 19 '17 at 19:25
  • 1
    found a few https://stackoverflow.com/questions/37250852/replace-deprecated-mcrypt-cbc-with-mcrypt-encrypt --- https://stackoverflow.com/questions/41272257/php-7-mcrypt-deprecated-need-alternative --- https://stackoverflow.com/questions/9993909/replace-mcrypt-with-openssl if those help and https://stackoverflow.com/questions/41740600/php7-1-mcrypt-alternative could be a dupe in here. – Funk Forty Niner Oct 19 '17 at 19:26
  • What are you actually trying to prevent by doing this? If you are storing the encryption/decryption key directly in the PHP source like that, anyone with access to your code can decrypt anything they want easily. – Mike Oct 19 '17 at 20:03
  • 1
    Also see [Use openssl_encrypt to replace Mcrypt for 3DES-ECB encryption](http://stackoverflow.com/q/39467008/608639), [Can't decrypt using pgcrypto from AES-256-CBC but AES-128-CBC is OK](http://stackoverflow.com/q/43550818/608639), [MCrypt rijndael-128 to OpenSSL aes-128-ecb conversion](http://stackoverflow.com/q/45218465/608639), etc. Also see [Upgrading my encryption library from Mcrypt to OpenSSL](http://stackoverflow.com/q/43329513), [Replace Mcrypt with OpenSSL](http://stackoverflow.com/q/9993909/608639) and [Preparing for removal of Mcrypt in PHP](http://stackoverflow.com/q/42696657) – jww Oct 19 '17 at 23:16

2 Answers2

1

This is a bit of an old question, but I figured I'd answer anyway.

As of PHP 7.2, Libsodium is enabled as a core module. There's nothing else you need to install, it will "just work" moving forward.

For PHP 7.1, I'd recommend the Pecl extension for Libsodium. You can install it just like you would any other Pecl extension:

pecl install libsodium

In any case, I'd highly recommend using the sodium_compat library as a wrapper around Libsodium. It's compatible with PHP all the way back to 5.2 and even ships with a PHP-native implementation of Libsodium if the Pecl module is missing.

Note: The PHP-native implementation is significantly slower than the compiled extension, but if you're having trouble upgrading to 7.2 or installing the Pecl module it will at least get you started.

As for your existing code, consider the following as an upgrade to use sodium_compat:

define('CRYPTO_KEY', 'some-key');

function decrypt($val){
    $key = base64_decode(CRYPTO_KEY);
    $data = base64_decode(urldecode($val));
    $nonce = substr($data, 0, ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);
    $ciphertext = substr($data, ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);

    $plaintext = ParagonIE_Sodium_Compat::crypto_secretbox_open($ciphertext, $nonce, $key);
    if ($plaintext === false) {
        throw new Exception("Bad ciphertext");
    }

    return $plaintext;
}

function enc($val){
    $key = base64_decode(CRYPTO_KEY);

    $nonce = random_bytes(ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);
    $ciphertext = ParagonIE_Sodium_Compat::crypto_secretbox($val, $nonce, $key);

    return urlencode(base64_encode($nonce . $ciphertext));
}

The additional ParagonIE_Sodium_Compat:: namespacing is if you're using sodium_compat. If you're able to just upgrade to PHP 7.2 you could dump that and use the native methods and constants directly. They're all named pretty similarly, so I won't belabor it here.

Note: As mentioned by others in the comments, storing your secret key hard-coded alongside the code that does the crypto is not a good idea. I copied it here to illustrate how your code would change to use Libsodium, not as an endorsement of the way CRYPTO_KEY is defined.

EAMann
  • 4,128
  • 2
  • 29
  • 48
0

Here is a way to encrypt Php 7 with Open SSL. This is a sure fire way to encrypt and decrypt your data. The only thing to keep in mind is that when searching your database for certain parameters you will need to decrypt before the search starts. First you start out with a key. Then there is an encrypt function as well as a decrypt function.

Key you can change to whatever you want. Store it on your server or another server.

    $key = 'qkwjdiw239&&jdafweihbrhnan&^%$ggdnawhd4njshjwuuO';

Next is the encrypt php function.

    function encryptthis($data, $key) {
    $encryption_key = base64_decode($key);
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, 
    $iv);
    return base64_encode($encrypted . '::' . $iv);
    }

Then to decrypt use this function.

    function decryptthis($data, $key) {
    $encryption_key = base64_decode($key);
    list($encrypted_data, $iv) = array_pad(explode('::', base64_decode($data), 
    2),2,null);
    return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, 
    $iv);
    }

To see code for a working example with a form please see this webpage. https://a1websitepro.com/data-encryption-php-mysql-methods-implementation-open-ssl-encrypt/