Skip to content

Instantly share code, notes, and snippets.

@bradleyhodges
Created May 16, 2017 11:17
Show Gist options
  • Save bradleyhodges/73fe29d5cf4b9a400b48463b41424f6a to your computer and use it in GitHub Desktop.
Save bradleyhodges/73fe29d5cf4b9a400b48463b41424f6a to your computer and use it in GitHub Desktop.
<?php
class SaferCrypto extends UnsafeCrypto {
const HASH_ALGO = 'sha256';
public static function encrypt($message, $key, $encode = false) {
list($encKey, $authKey) = self::splitKeys($key);
$ciphertext = parent::encrypt($message, $encKey);
$mac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true);
if ($encode) {
return base64_encode($mac.$ciphertext);
}
return $mac.$ciphertext;
}
public static function decrypt($message, $key, $encoded = false) {
list($encKey, $authKey) = self::splitKeys($key);
if ($encoded) {
$message = base64_decode($message, true);
if ($message === false) {
throw new Exception('Encryption failure');
}
}
$hs = mb_strlen(hash(self::HASH_ALGO, '', true), '8bit');
$mac = mb_substr($message, 0, $hs, '8bit');
$ciphertext = mb_substr($message, $hs, null, '8bit');
$calculated = hash_hmac(
self::HASH_ALGO,
$ciphertext,
$authKey,
true
);
if (!self::hashEquals($mac, $calculated)) {
throw new Exception('Encryption failure');
}
$plaintext = parent::decrypt($ciphertext, $encKey);
return $plaintext;
}
protected static function splitKeys($masterKey) {
return [
hash_hmac(self::HASH_ALGO, 'ENCRYPTION', $masterKey, true),
hash_hmac(self::HASH_ALGO, 'AUTHENTICATION', $masterKey, true)
];
}
protected static function hashEquals($a, $b) {
if (function_exists('hash_equals')) {
return hash_equals($a, $b);
}
$nonce = openssl_random_pseudo_bytes(32);
return hash_hmac(self::HASH_ALGO, $a, $nonce) === hash_hmac(self::HASH_ALGO, $b, $nonce);
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment