3v4l.org

run code in 300+ PHP versions simultaneously
<?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)));
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:
49.5 ms | 402 KiB | 8 Q