[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/sodium_compat/src/Core/Base64/ -> Common.php (source)

   1  <?php
   2  
   3  /**
   4   * Class ParagonIE_Sodium_Core_Base64
   5   *
   6   *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
   7   *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
   8   *
   9   * We have to copy/paste the contents into the variant files because PHP 5.2
  10   * doesn't support late static binding, and we have no better workaround
  11   * available that won't break PHP 7+. Therefore, we're forced to duplicate code.
  12   */
  13  abstract class ParagonIE_Sodium_Core_Base64_Common
  14  {
  15      /**
  16       * Encode into Base64
  17       *
  18       * Base64 character set "[A-Z][a-z][0-9]+/"
  19       *
  20       * @param string $src
  21       * @return string
  22       * @throws TypeError
  23       */
  24      public static function encode($src)
  25      {
  26          return self::doEncode($src, true);
  27      }
  28  
  29      /**
  30       * Encode into Base64, no = padding
  31       *
  32       * Base64 character set "[A-Z][a-z][0-9]+/"
  33       *
  34       * @param string $src
  35       * @return string
  36       * @throws TypeError
  37       */
  38      public static function encodeUnpadded($src)
  39      {
  40          return self::doEncode($src, false);
  41      }
  42  
  43      /**
  44       * @param string $src
  45       * @param bool $pad   Include = padding?
  46       * @return string
  47       * @throws TypeError
  48       */
  49      protected static function doEncode($src, $pad = true)
  50      {
  51          $dest = '';
  52          $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
  53          // Main loop (no padding):
  54          for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
  55              /** @var array<int, int> $chunk */
  56              $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
  57              $b0 = $chunk[1];
  58              $b1 = $chunk[2];
  59              $b2 = $chunk[3];
  60  
  61              $dest .=
  62                  self::encode6Bits(               $b0 >> 2       ) .
  63                  self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
  64                  self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
  65                  self::encode6Bits(  $b2                     & 63);
  66          }
  67          // The last chunk, which may have padding:
  68          if ($i < $srcLen) {
  69              /** @var array<int, int> $chunk */
  70              $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
  71              $b0 = $chunk[1];
  72              if ($i + 1 < $srcLen) {
  73                  $b1 = $chunk[2];
  74                  $dest .=
  75                      self::encode6Bits($b0 >> 2) .
  76                      self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
  77                      self::encode6Bits(($b1 << 2) & 63);
  78                  if ($pad) {
  79                      $dest .= '=';
  80                  }
  81              } else {
  82                  $dest .=
  83                      self::encode6Bits( $b0 >> 2) .
  84                      self::encode6Bits(($b0 << 4) & 63);
  85                  if ($pad) {
  86                      $dest .= '==';
  87                  }
  88              }
  89          }
  90          return $dest;
  91      }
  92  
  93      /**
  94       * decode from base64 into binary
  95       *
  96       * Base64 character set "./[A-Z][a-z][0-9]"
  97       *
  98       * @param string $src
  99       * @param bool $strictPadding
 100       * @return string
 101       * @throws RangeException
 102       * @throws TypeError
 103       * @psalm-suppress RedundantCondition
 104       */
 105      public static function decode($src, $strictPadding = false)
 106      {
 107          // Remove padding
 108          $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
 109          if ($srcLen === 0) {
 110              return '';
 111          }
 112  
 113          if ($strictPadding) {
 114              if (($srcLen & 3) === 0) {
 115                  if ($src[$srcLen - 1] === '=') {
 116                      $srcLen--;
 117                      if ($src[$srcLen - 1] === '=') {
 118                          $srcLen--;
 119                      }
 120                  }
 121              }
 122              if (($srcLen & 3) === 1) {
 123                  throw new RangeException(
 124                      'Incorrect padding'
 125                  );
 126              }
 127              if ($src[$srcLen - 1] === '=') {
 128                  throw new RangeException(
 129                      'Incorrect padding'
 130                  );
 131              }
 132          } else {
 133              $src = rtrim($src, '=');
 134              $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
 135          }
 136  
 137          $err = 0;
 138          $dest = '';
 139          // Main loop (no padding):
 140          for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
 141              /** @var array<int, int> $chunk */
 142              $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
 143              $c0 = self::decode6Bits($chunk[1]);
 144              $c1 = self::decode6Bits($chunk[2]);
 145              $c2 = self::decode6Bits($chunk[3]);
 146              $c3 = self::decode6Bits($chunk[4]);
 147  
 148              $dest .= pack(
 149                  'CCC',
 150                  ((($c0 << 2) | ($c1 >> 4)) & 0xff),
 151                  ((($c1 << 4) | ($c2 >> 2)) & 0xff),
 152                  ((($c2 << 6) |  $c3      ) & 0xff)
 153              );
 154              $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
 155          }
 156          // The last chunk, which may have padding:
 157          if ($i < $srcLen) {
 158              /** @var array<int, int> $chunk */
 159              $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
 160              $c0 = self::decode6Bits($chunk[1]);
 161  
 162              if ($i + 2 < $srcLen) {
 163                  $c1 = self::decode6Bits($chunk[2]);
 164                  $c2 = self::decode6Bits($chunk[3]);
 165                  $dest .= pack(
 166                      'CC',
 167                      ((($c0 << 2) | ($c1 >> 4)) & 0xff),
 168                      ((($c1 << 4) | ($c2 >> 2)) & 0xff)
 169                  );
 170                  $err |= ($c0 | $c1 | $c2) >> 8;
 171              } elseif ($i + 1 < $srcLen) {
 172                  $c1 = self::decode6Bits($chunk[2]);
 173                  $dest .= pack(
 174                      'C',
 175                      ((($c0 << 2) | ($c1 >> 4)) & 0xff)
 176                  );
 177                  $err |= ($c0 | $c1) >> 8;
 178              } elseif ($i < $srcLen && $strictPadding) {
 179                  $err |= 1;
 180              }
 181          }
 182          /** @var bool $check */
 183          $check = ($err === 0);
 184          if (!$check) {
 185              throw new RangeException(
 186                  'Base64::decode() only expects characters in the correct base64 alphabet'
 187              );
 188          }
 189          return $dest;
 190      }
 191  
 192      /**
 193       * Uses bitwise operators instead of table-lookups to turn 6-bit integers
 194       * into 8-bit integers.
 195       *
 196       * Base64 character set:
 197       * [A-Z]      [a-z]      [0-9]      +     /
 198       * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
 199       *
 200       * @param int $src
 201       * @return int
 202       */
 203      abstract protected static function decode6Bits($src);
 204  
 205      /**
 206       * Uses bitwise operators instead of table-lookups to turn 8-bit integers
 207       * into 6-bit integers.
 208       *
 209       * @param int $src
 210       * @return string
 211       */
 212      abstract protected static function encode6Bits($src);
 213  }


Generated: Sat Apr 27 01:00:02 2024 Cross-referenced by PHPXref 0.7.1