3v4l.org

run code in 300+ PHP versions simultaneously
<?php if (PHP_VERSION_ID < 70000) { die('no'); } /** * Use HKDF to derive multiple keys from one. * http://tools.ietf.org/html/rfc5869 * * @param string $hash Hash Function * @param string $ikm Initial Keying Material * @param int $length How many bytes? * @param string $info What sort of key are we deriving? * @param string $salt * @return string * @throws Exception */ function hash_hkdf(string $algo, string $ikm, int $length, string $info = '', $salt = null) { $digest_length = mb_strlen(hash_hmac($algo, '', '', true), '8bit'); // Sanity-check the desired output length. if (empty($length) || !is_int($length) || $length < 0 || $length > 255 * $digest_length) { throw new Exception("Bad output length requested of HKDF."); } // "if [salt] not provided, is set to a string of HashLen zeroes." if ($salt === null) { $salt = str_repeat("\x00", $digest_length); } // HKDF-Extract: // PRK = HMAC-Hash(salt, IKM) // The salt is the HMAC key. $prk = hash_hmac($algo, $ikm, $salt, true); // HKDF-Expand: // This check is useless, but it serves as a reminder to the spec. if (mb_strlen($prk, '8bit') < $digest_length) { throw new Exception('HKDF-Expand failed'); } // T(0) = '' $t = ''; $last_block = ''; for ($block_index = 1; mb_strlen($t, '8bit') < $length; ++$block_index) { // T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??) $last_block = hash_hmac( $algo, $last_block . $info . chr($block_index), $prk, true ); // T = T(1) | T(2) | T(3) | ... | T(N) $t .= $last_block; } // ORM = first L octets of T $orm = mb_substr($t, 0, $length, '8bit'); if ($orm === false) { throw new Exception('Unexpected error'); } return $orm; } /** * Encrypt a message with AES-256-CTR + HMAC-SHA256 * @param string $message * @param string $key * @return string */ function aes256ctr_hmacsha256_encrypt(string $message, string $key) { $iv = random_bytes(16); $salt = random_bytes(16); $eKey = hash_hkdf('sha256', $key, 32, 'Encryption Key', $salt); $aKey = hash_hkdf('sha256', $key, 32, 'Authentication Key', $salt); $ciphertext = $iv . $salt . openssl_encrypt( $message, 'aes-256-ctr', $eKey, OPENSSL_RAW_DATA, $iv ); $mac = hash_hmac('sha256', $ciphertext, $aKey, true); return base64_encode($mac . $ciphertext); } /** * Decrypt a message with AES-256-CTR + HMAC-SHA256 * @param string $message * @param string $key * @return string * @throws Exception */ function aes256ctr_hmacsha256_decrypt(string $ciphertext, string $key) { $decode = base64_decode($ciphertext); if ($decode === false) { throw new Exception("Encoding error"); } $mac = mb_substr($decode, 0, 32, '8bit'); $iv = mb_substr($decode, 32, 16, '8bit'); $salt = mb_substr($decode, 48, 16, '8bit'); $ciphertext = mb_substr($decode, 64, null, '8bit'); $aKey = hash_hkdf('sha256', $key, 32, 'Authentication Key', $salt); $calcMac = hash_hmac('sha256', $iv . $salt . $ciphertext, $aKey, true); if (!hash_equals($calcMac, $mac)) { throw new Exception("Invalid message"); } $eKey = hash_hkdf('sha256', $key, 32, 'Encryption Key', $salt); return openssl_decrypt( $ciphertext, 'aes-256-ctr', $eKey, OPENSSL_RAW_DATA, $iv ); } $key = random_bytes(32); $message = "This code rocks"; $ciphertext = aes256ctr_hmacsha256_encrypt($message, $key); var_dump($ciphertext); $plaintext = aes256ctr_hmacsha256_decrypt($ciphertext, $key); var_dump($plaintext);

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.4.00.0070.00814.85
7.3.120.0080.00814.77
7.3.110.0070.01114.74
7.3.100.0100.00514.72
7.3.90.0080.00514.84
7.3.80.0070.00914.77
7.3.70.0080.00814.63
7.3.60.0050.00814.70
7.3.50.0040.00714.77
7.3.40.0040.00714.66
7.3.30.0030.00814.72
7.3.20.0090.00316.60
7.3.10.0070.00416.50
7.3.00.0030.00816.39
7.2.250.0110.00715.01
7.2.240.0070.01114.83
7.2.230.0120.00314.86
7.2.220.0060.00914.97
7.2.210.0070.00814.66
7.2.200.0030.01314.82
7.2.190.0040.01114.65
7.2.180.0060.00614.88
7.2.170.0100.00714.88
7.1.330.0100.00315.57
7.1.320.0020.00715.59
7.1.310.0040.01115.57
7.1.300.0070.00715.50
7.1.290.0070.00415.35
7.1.280.0080.00515.49
7.1.270.0080.00615.58
7.1.260.0050.00515.70
7.1.70.0000.01016.98
7.1.60.0100.01419.19
7.1.50.0100.01316.84
7.1.00.0030.07322.50
7.0.200.0000.00816.44
7.0.100.0070.07320.04
7.0.90.0200.07020.01
7.0.80.0070.06720.07
7.0.70.0100.04720.02
7.0.60.0130.04320.05
7.0.50.0170.05020.48
7.0.40.0070.08720.14
7.0.30.0170.07720.20
7.0.20.0070.05020.19
7.0.10.0030.06020.06
7.0.00.0030.08720.13
5.6.280.0100.06720.79
5.6.250.0070.03020.57
5.6.240.0070.05020.64
5.6.230.0030.04720.63
5.6.220.0100.04720.65
5.6.210.0100.07320.67
5.6.200.0130.04321.04
5.6.190.0100.07321.09
5.6.180.0000.09021.12
5.6.170.0070.09021.09
5.6.160.0100.05720.93
5.6.150.0100.07321.08
5.6.140.0070.07721.06
5.6.130.0070.05021.04
5.6.120.0070.07020.96
5.6.110.0000.04721.13
5.6.100.0070.04020.95
5.6.90.0200.06021.12
5.6.80.0200.06720.37
5.6.70.0070.07020.47
5.6.60.0030.05020.38
5.6.50.0100.07320.56
5.6.40.0130.04020.45
5.6.30.0070.03720.38
5.6.20.0130.04020.24
5.6.10.0070.05020.38
5.6.00.0070.03720.36
5.5.380.0030.05020.41
5.5.370.0030.04720.39
5.5.360.0100.06020.39
5.5.350.0070.05320.48
5.5.340.0170.04020.92
5.5.330.0070.06720.87
5.5.320.0070.08020.65
5.5.310.0100.06720.89
5.5.300.0100.07720.64
5.5.290.0070.06020.92
5.5.280.0030.06720.90
5.5.270.0130.06720.87
5.5.260.0100.03720.91
5.5.250.0030.07020.71
5.5.240.0070.08020.14
5.5.230.0070.07720.18
5.5.220.0030.04020.02
5.5.210.0130.04020.28
5.5.200.0170.06020.24
5.5.190.0100.04720.23
5.5.180.0130.07020.09
5.5.160.0070.07019.95
5.5.150.0100.07020.13
5.5.140.0030.08020.21
5.5.130.0000.04320.15
5.5.120.0070.04020.15
5.5.110.0070.03720.25
5.5.100.0070.04320.14
5.5.90.0070.03720.05
5.5.80.0030.03720.06
5.5.70.0100.06720.09
5.5.60.0070.03320.09
5.5.50.0030.03720.16
5.5.40.0170.06020.05
5.5.30.0100.07020.14
5.5.20.0000.05020.11
5.5.10.0100.06720.05
5.5.00.0070.03320.04

preferences:
16.72 ms | 401 KiB | 5 Q