3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?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)));
based on 3VLT0
Output for 7.0.0 - 7.3.1
Notice: Undefined variable: message in /in/v852r on line 114 Notice: Undefined variable: message 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.
Output for 5.4.45, 5.6.0 - 5.6.38
Notice: Undefined variable: message in /in/v852r on line 114 Notice: Undefined variable: message in /in/v852r on line 116 Fatal error: Uncaught exception 'Exception' with message 'Encryption failure' in /in/v852r:126 Stack trace: #0 /in/v852r(191): QRCrypt::decrypt('I/hF3LEIAZVC/zb...', '[@\xAC\xCA?\x81\xEF\xCF\xEAI\x13\x9E}{i...', true) #1 {main} thrown in /in/v852r on line 126
Process exited with code 255.
Output for 5.5.0 - 5.5.38
Notice: Undefined variable: message in /in/v852r on line 114 Notice: Undefined variable: message in /in/v852r on line 116 Fatal error: Call to undefined function openssl_random_pseudo_bytes() in /in/v852r on line 164
Process exited with code 255.
Output for 5.3.29
Parse error: syntax error, unexpected '[' in /in/v852r on line 145
Process exited with code 255.
Output for 5.0.0 - 5.0.5
Parse error: parse error, unexpected '[' in /in/v852r on line 145
Process exited with code 255.