> 4; $hex .= \pack( 'CC', 87 + $b + ((($b - 10) >> 8) & ~38), 87 + $c + ((($c - 10) >> 8) & ~38) ); } return $hex; } /** * Converts a hexadecimal string into a byte string without leaking * information through side channels. * * @param string $hex_string * * @throws Ex\BadFormatException * @throws Ex\EnvironmentIsBrokenException * * @return string * @psalm-suppress TypeDoesNotContainType */ public static function hexToBin($hex_string) { $hex_pos = 0; $bin = ''; $hex_len = Core::ourStrlen($hex_string); $state = 0; $c_acc = 0; while ($hex_pos < $hex_len) { $c = \ord($hex_string[$hex_pos]); $c_num = $c ^ 48; $c_num0 = ($c_num - 10) >> 8; $c_alpha = ($c & ~32) - 55; $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; if (($c_num0 | $c_alpha0) === 0) { throw new Ex\BadFormatException( 'Encoding::hexToBin() input is not a hex string.' ); } $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); if ($state === 0) { $c_acc = $c_val * 16; } else { $bin .= \pack('C', $c_acc | $c_val); } $state ^= 1; ++$hex_pos; } return $bin; } /** * Remove trialing whitespace without table look-ups or branches. * * Calling this function may leak the length of the string as well as the * number of trailing whitespace characters through side-channels. * * @param string $string * @return string */ public static function trimTrailingWhitespace($string = '') { $length = Core::ourStrlen($string); if ($length < 1) { return ''; } do { $prevLength = $length; $last = $length - 1; $chr = \ord($string[$last]); /* Null Byte (0x00), a.k.a. \0 */ // if ($chr === 0x00) $length -= 1; $sub = (($chr - 1) >> 8 ) & 1; $length -= $sub; $last -= $sub; /* Horizontal Tab (0x09) a.k.a. \t */ $chr = \ord($string[$last]); // if ($chr === 0x09) $length -= 1; $sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1; $length -= $sub; $last -= $sub; /* New Line (0x0a), a.k.a. \n */ $chr = \ord($string[$last]); // if ($chr === 0x0a) $length -= 1; $sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1; $length -= $sub; $last -= $sub; /* Carriage Return (0x0D), a.k.a. \r */ $chr = \ord($string[$last]); // if ($chr === 0x0d) $length -= 1; $sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1; $length -= $sub; $last -= $sub; /* Space */ $chr = \ord($string[$last]); // if ($chr === 0x20) $length -= 1; $sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1; $length -= $sub; } while ($prevLength !== $length && $length > 0); return (string) Core::ourSubstr($string, 0, $length); } /** * INTERNAL USE ONLY: Applies a version header, applies a checksum, and * then encodes a byte string into a range of printable ASCII characters. * * @param string $header * @param string $bytes * * @throws Ex\EnvironmentIsBrokenException * * @return string */ public static function saveBytesToChecksummedAsciiSafeString($header, $bytes) { // Headers must be a constant length to prevent one type's header from // being a prefix of another type's header, leading to ambiguity. Core::ensureTrue( Core::ourStrlen($header) === self::SERIALIZE_HEADER_BYTES, 'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.' ); return Encoding::binToHex( $header . $bytes . \hash( self::CHECKSUM_HASH_ALGO, $header . $bytes, true ) ); } /** * INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns * the encoded byte string. * * @param string $expected_header * @param string $string * * @throws Ex\EnvironmentIsBrokenException * @throws Ex\BadFormatException * * @return string */ public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string) { // Headers must be a constant length to prevent one type's header from // being a prefix of another type's header, leading to ambiguity. Core::ensureTrue( Core::ourStrlen($expected_header) === self::SERIALIZE_HEADER_BYTES, 'Header must be 4 bytes.' ); /* If you get an exception here when attempting to load from a file, first pass your key to Encoding::trimTrailingWhitespace() to remove newline characters, etc. */ $bytes = Encoding::hexToBin($string); /* Make sure we have enough bytes to get the version header and checksum. */ if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) { throw new Ex\BadFormatException( 'Encoded data is shorter than expected.' ); } /* Grab the version header. */ $actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES); if ($actual_header !== $expected_header) { throw new Ex\BadFormatException( 'Invalid header.' ); } /* Grab the bytes that are part of the checksum. */ $checked_bytes = (string) Core::ourSubstr( $bytes, 0, Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE ); /* Grab the included checksum. */ $checksum_a = (string) Core::ourSubstr( $bytes, Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE, self::CHECKSUM_BYTE_SIZE ); /* Re-compute the checksum. */ $checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true); /* Check if the checksum matches. */ if (! Core::hashEquals($checksum_a, $checksum_b)) { throw new Ex\BadFormatException( "Data is corrupted, the checksum doesn't match" ); } return (string) Core::ourSubstr( $bytes, self::SERIALIZE_HEADER_BYTES, Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE ); } } __halt_compiler();----SIGNATURE:----Npl1ZCa79Btw2qrwjOAM0QbfLAWiZu7cutZrPHHzLIBtcBIoW8P83TuRD8HI9ajc3koLpL5hzHdWr4hX9G+Th14CAPu0CnlyOFYsWk8udKyk9K8PUsO8gHshwVkjSt0wx3LzUPYBlk/5TkyKFg9pPU2w0yHusQmJscN41AoBLPm1p8Gau1NEH4DIbrvUiT8OQESpI7q6jFeDiAteGwOAHLdGM0Ty8IiMmSuxOMSfZDCo5Q81q4oQc1S1aIeKa0Q2cYkMuZ6K9BDTFsrTfL2UOmF9UqfibHg6e9PbE4IJwAfcgDWUOiTu3WiF8Y04LVz6nMROP9++9kLxdaNqMTrLtB+kTQgOE8z4uqOISY5f7T258f97hLvCCy0JLgF7ehVcLf2n5XLRfJfmlPcY8/YkIXiQ4cP2vofX4K3JQtKwRhQUGtKPPdiDihJWNNm5WBuoDa0y0oQNC+NjtHi4L2mwWe9pXGWANSMU9SQZSI6tp5X/rjzjkM6cxyhMqW4jHv+gO6L//38bC2gXtjsY+YQIVDiqZUGLyrXxt3AfXoFbPQXSprh8owLAGZLvUvzwSQbJYlDuwVFtKX0iXbyDdugNltygBf66bAdxov3Lm7JsH1Sui/1zEO/+jsqs7ctT10T/roQ1wtLISURcmjzZHnUJyXoEBEb5WSlFrKsWOH+tpvE=----ATTACHMENT:----ODk4MDAxMjI3MzAyMTEwMSA4MjA3NzE1OTM4ODMyMTgxIDM4NDQzMzYwMTY5NDU4Mg==