[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/paragonie/constant_time_encoding/src/ -> Hex.php (source)

   1  <?php
   2  declare(strict_types=1);
   3  namespace ParagonIE\ConstantTime;
   4  
   5  use RangeException;
   6  use TypeError;
   7  
   8  /**
   9   *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
  10   *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
  11   *
  12   *  Permission is hereby granted, free of charge, to any person obtaining a copy
  13   *  of this software and associated documentation files (the "Software"), to deal
  14   *  in the Software without restriction, including without limitation the rights
  15   *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16   *  copies of the Software, and to permit persons to whom the Software is
  17   *  furnished to do so, subject to the following conditions:
  18   *
  19   *  The above copyright notice and this permission notice shall be included in all
  20   *  copies or substantial portions of the Software.
  21   *
  22   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28   *  SOFTWARE.
  29   */
  30  
  31  /**
  32   * Class Hex
  33   * @package ParagonIE\ConstantTime
  34   */
  35  abstract class Hex implements EncoderInterface
  36  {
  37      /**
  38       * Convert a binary string into a hexadecimal string without cache-timing
  39       * leaks
  40       *
  41       * @param string $binString (raw binary)
  42       * @return string
  43       * @throws TypeError
  44       */
  45      public static function encode(string $binString): string
  46      {
  47          $hex = '';
  48          $len = Binary::safeStrlen($binString);
  49          for ($i = 0; $i < $len; ++$i) {
  50              /** @var array<int, int> $chunk */
  51              $chunk = \unpack('C', $binString[$i]);
  52              $c = $chunk[1] & 0xf;
  53              $b = $chunk[1] >> 4;
  54  
  55              $hex .= \pack(
  56                  'CC',
  57                  (87 + $b + ((($b - 10) >> 8) & ~38)),
  58                  (87 + $c + ((($c - 10) >> 8) & ~38))
  59              );
  60          }
  61          return $hex;
  62      }
  63  
  64      /**
  65       * Convert a binary string into a hexadecimal string without cache-timing
  66       * leaks, returning uppercase letters (as per RFC 4648)
  67       *
  68       * @param string $binString (raw binary)
  69       * @return string
  70       * @throws TypeError
  71       */
  72      public static function encodeUpper(string $binString): string
  73      {
  74          $hex = '';
  75          $len = Binary::safeStrlen($binString);
  76  
  77          for ($i = 0; $i < $len; ++$i) {
  78              /** @var array<int, int> $chunk */
  79              $chunk = \unpack('C', $binString[$i]);
  80              $c = $chunk[1] & 0xf;
  81              $b = $chunk[1] >> 4;
  82  
  83              $hex .= \pack(
  84                  'CC',
  85                  (55 + $b + ((($b - 10) >> 8) & ~6)),
  86                  (55 + $c + ((($c - 10) >> 8) & ~6))
  87              );
  88          }
  89          return $hex;
  90      }
  91  
  92      /**
  93       * Convert a hexadecimal string into a binary string without cache-timing
  94       * leaks
  95       *
  96       * @param string $encodedString
  97       * @param bool $strictPadding
  98       * @return string (raw binary)
  99       * @throws RangeException
 100       */
 101      public static function decode(
 102          string $encodedString,
 103          bool $strictPadding = false
 104      ): string {
 105          $hex_pos = 0;
 106          $bin = '';
 107          $c_acc = 0;
 108          $hex_len = Binary::safeStrlen($encodedString);
 109          $state = 0;
 110          if (($hex_len & 1) !== 0) {
 111              if ($strictPadding) {
 112                  throw new RangeException(
 113                      'Expected an even number of hexadecimal characters'
 114                  );
 115              } else {
 116                  $encodedString = '0' . $encodedString;
 117                  ++$hex_len;
 118              }
 119          }
 120  
 121          /** @var array<int, int> $chunk */
 122          $chunk = \unpack('C*', $encodedString);
 123          while ($hex_pos < $hex_len) {
 124              ++$hex_pos;
 125              $c = $chunk[$hex_pos];
 126              $c_num = $c ^ 48;
 127              $c_num0 = ($c_num - 10) >> 8;
 128              $c_alpha = ($c & ~32) - 55;
 129              $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
 130  
 131              if (($c_num0 | $c_alpha0) === 0) {
 132                  throw new RangeException(
 133                      'Expected hexadecimal character'
 134                  );
 135              }
 136              $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
 137              if ($state === 0) {
 138                  $c_acc = $c_val * 16;
 139              } else {
 140                  $bin .= \pack('C', $c_acc | $c_val);
 141              }
 142              $state ^= 1;
 143          }
 144          return $bin;
 145      }
 146  }