@ 2016-03-16T14:08:58Z <?php
class QR
{
const METHOD = "aes-256-ctr";
/**
*
* Encrypts (without authenticating)
*
* @param string $input - json encoded array
* @param string $key - encryption key (raw binary expected)
* @param boolean $encode - set to TRUE to return base64-encoded
* @return string (raw binary)
*/
public static function encrypt($input, $key, $encode = false)
{
$nonceSize = openssl_cipher_iv_length(self::METHOD);
$nonce = openssl_random_pseudo_bytes($nonceSize);
$ciphertext = openssl_encrypt(
$input,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$nonce
);
//Pack the IV and ciphertext together - concatenate
return ($encode ? base64_encode($nonce.$ciphertext) : $nonce.$ciphertext);
}
/**
*
* Decrypts (but does not verify)
*
* @param string $input - ciphertext message
* @param string $key - encryption key
* @param boolean $encoded - are we expecting an encoded string?
* @return string
*/
public static function decrypt($input, $key, $encoded = false)
{
if($encoded){
$input = base64_decode($message, true);
if($input===false){
throw new Exception("Encryption failure");
}
}
$nonceSize = openssl_cipher_iv_length(self::METHOD);
$nonce = mb_substr($input, 0, $nonceSize, "8bit");
$ciphertext = mb_substr($input, $nonceSize, null, "8bit");
$plaintext = openssl_decrypt(
$ciphertext,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$nonce
);
return $plaintext;
}
}
class QRCrypt extends QR
{
const HASH_ALGO = "sha256";
/**
* Encrypts then MACs an input
*
* @param string $input - plaintext input
* @param string $key - encryption key (raw binary expected)
* @param boolean $encode - set to TRUE to return a base64-encoded string
* @return string (raw binary)
*/
public static function encrypt($input, $key, $encode = false)
{
list($encKey, $authKey) = self::splitKeys($key);
//Pass to QR::encrypt
$ciphertext = parent::encrypt($input, $encKey);
//Calculate a MAC of hte IV and ciphertext
$mac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true);
return ($encode ? base64_encode($mac.$ciphertext) : $mac.$ciphertext);
}
/**
* Decrypts an input (after verifying integrity)
*
* @param string $input - ciphertext input
* @param string $key - encryption key (raw binary expected)
* @param boolean $encoded - are we expecting an encoded string?
* @return string (raw binary)
*/
public static function decrypt($input, $key, $encoded = false)
{
list($encKey, $authKey) = self::splitKeys($key);
if($encoded){
$input = base64_decode($input, true);
if($input===false){
throw new Exception("Encryption failure");
}
}
//Hash size in case HASH_ALGO is changed
$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");
}
//Pass to QR::decrypt
$plaintext = parent::decrypt($ciphertext, $encKey);
return $plaintext;
}
/**
* Splits a key into two separate keys; one for encryption
* and the other for authenticaiton
*
* @param string $masterKey (raw binary)
* @return array (two raw binary strings)
*/
protected static function splitKeys($masterKey)
{
// You really want to implement HKDF here instead!
return [
hash_hmac(self::HASH_ALGO, 'ENCRYPTION', $masterKey, true),
hash_hmac(self::HASH_ALGO, 'AUTHENTICATION', $masterKey, true)
];
}
/**
* Compare two strings without leaking timing information
*
* @param string $a
* @param string $b
* @ref https://paragonie.com/b/WS1DLx6BnpsdaVQW
* @return boolean
*/
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);
}
}
/**
* QR Code encryption/decryption
*
*/
//Set key here
$key = '5B40ACCA3F81EFCFEA49139E7D7B6944ED716B76726F88DE2ECFAD30457ADD01';
//Set directory of qr.classes.php here with trailing slash
$class = "./";
//Set input here
$input = 'I/hF3LEIAZVC/zbi6naANeS2Zn82CsKcbvjX6CE1xIT8Vo7rJ8jytm60hGwv09JwWQH+npIcfp/0HD37ReP3JbwSk4h+eZqBSUHZPiN5mZY=';
//Are we encrypting or decrypting? (Set to "decrypt" for decryption)
$decrypt = "decrypt";
/********************************************************************************/
$key = hex2bin($key);
$input = trim(htmlspecialchars_decode($input));
$decrypt = $decrypt=="decrypt" ? true : false;
exit(($decrypt ? QRCrypt::decrypt($input,$key,true) : QRCrypt::encrypt($input,$key,true)));
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Output for git.master , git.master_jit , rfc.property-hooks Warning: Undefined variable $message in /in/v852r on line 114
Deprecated: mb_substr(): Passing null to parameter #1 ($string) of type string is deprecated in /in/v852r on line 114
Warning: Undefined variable $message in /in/v852r on line 116
Deprecated: mb_substr(): Passing null to parameter #1 ($string) of type string is deprecated in /in/v852r on line 116
Fatal error: Uncaught Exception: Encryption failure in /in/v852r:126
Stack trace:
#0 /in/v852r(191): QRCrypt::decrypt('#\xF8E\xDC\xB1\x08\x01\x95B\xFF6\xE2\xEAv\x80...', '[@\xAC\xCA?\x81\xEF\xCF\xEAI\x13\x9E}{i...', true)
#1 {main}
thrown in /in/v852r on line 126
Process exited with code 255 . This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.
Active branches Archived branches Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page
preferences:dark mode live preview
49.5 ms | 402 KiB | 8 Q