Skip to content

Instantly share code, notes, and snippets.

@Radiergummi
Last active March 3, 2023 13:11
Show Gist options
  • Save Radiergummi/b326219f55edb33759791a78a1c134c3 to your computer and use it in GitHub Desktop.
Save Radiergummi/b326219f55edb33759791a78a1c134c3 to your computer and use it in GitHub Desktop.
A PHP class to encrypt and decrypt strings using a static application secret. Input is converted to hex strings to enable easier handling
<?php
namespace Vendor\Library;
use function bin2hex;
use function hex2bin;
use function openssl_decrypt;
use function openssl_encrypt;
use function random_bytes;
/**
* Cryptor class
*
* The encrypt/decrypt methods are largely taken from here:
*
* @link https://stackoverflow.com/a/46872528/2532203
*/
class Cryptor
{
/**
* Holds the encryption algorithm to use
*/
protected const ENCRYPTION_ALGORITHM = 'AES-256-CBC';
/**
* Holds the hash algorithm to use
*/
protected const HASHING_ALGORITHM = 'sha256';
/**
* Holds the application encryption secret
*
* @var string
*/
protected $secret;
/**
* Cryptor constructor
*
* @param string $secret application encryption secret
*/
public function __construct(string $secret)
{
$this->secret = $secret;
}
/**
* Decrypts a string using the application secret.
*
* @param string $input hex representation of the cipher text
*
* @return string UTF-8 string containing the plain text input
*/
public function decrypt(string $input): string
{
// prevent decrypt failing when $input is not hex or has odd length
// added via suggestion from @markusand, see comment:
// https://gist.github.com/Radiergummi/b326219f55edb33759791a78a1c134c3#gistcomment-2803128
if (strlen($input) % 2 || ! ctype_xdigit($input)) {
return '';
}
// we'll need the binary cipher
$binaryInput = hex2bin($input);
$iv = substr($binaryInput, 0, 16);
$hash = substr($binaryInput, 16, 32);
$cipherText = substr($binaryInput, 48);
$key = hash(self::HASHING_ALGORITHM, $this->secret, true);
// if the HMAC hash doesn't match the hash string, something has gone wrong
if (hash_hmac(self::HASHING_ALGORITHM, $cipherText, $key, true) !== $hash) {
return '';
}
return openssl_decrypt(
$cipherText,
self::ENCRYPTION_ALGORITHM,
$key,
OPENSSL_RAW_DATA,
$iv
);
}
/**
* Encrypts a string using the application secret. This returns a hex representation of the binary cipher text
*
* @param string $input plain text input to encrypt
*
* @return string hex representation of the binary cipher text
* @throws \Exception
*/
public function encrypt(string $input): string
{
$key = hash(self::HASHING_ALGORITHM, $this->secret, true);
$iv = random_bytes(16);
$cipherText = openssl_encrypt(
$input,
self::ENCRYPTION_ALGORITHM,
$key,
OPENSSL_RAW_DATA,
$iv
);
$hash = hash_hmac(self::HASHING_ALGORITHM, $cipherText, $key, true);
return bin2hex($iv . $hash . $cipherText);
}
}
@mdestafadilah
Copy link

Sorry, I've got no idea what CI 2/3 is?

sorry, it's Codeigniter i mean. i have no idea implement this, put as thirt_party or libraries it' self.

@lycifep
Copy link

lycifep commented Mar 3, 2023

Hello.
Decrypt not working in PHP 7.2.
Error, return '':
if (hash_hmac(self::HASHING_ALGORITHM, $cipherText, $key, true) !== $hash) {
return '';
}
Works well in php 7.4.
How to be?

@Radiergummi
Copy link
Author

Support for PHP 7.2 ended years ago - if it does in 7.4, that's your best option 🤷‍♂️

@lycifep
Copy link

lycifep commented Mar 3, 2023

We can't switch to the older version of PHP yet (a lot of legacy code). Can you suggest what could be the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment