wp/wp-includes/sodium_compat/src/Core32/Salsa20.php
changeset 9 177826044cd9
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
       
     1 <?php
       
     2 
       
     3 if (class_exists('ParagonIE_Sodium_Core32_Salsa20', false)) {
       
     4     return;
       
     5 }
       
     6 
       
     7 /**
       
     8  * Class ParagonIE_Sodium_Core32_Salsa20
       
     9  */
       
    10 abstract class ParagonIE_Sodium_Core32_Salsa20 extends ParagonIE_Sodium_Core32_Util
       
    11 {
       
    12     const ROUNDS = 20;
       
    13 
       
    14     /**
       
    15      * Calculate an salsa20 hash of a single block
       
    16      *
       
    17      * @internal You should not use this directly from another application
       
    18      *
       
    19      * @param string $in
       
    20      * @param string $k
       
    21      * @param string|null $c
       
    22      * @return string
       
    23      * @throws SodiumException
       
    24      * @throws TypeError
       
    25      */
       
    26     public static function core_salsa20($in, $k, $c = null)
       
    27     {
       
    28         /**
       
    29          * @var ParagonIE_Sodium_Core32_Int32 $x0
       
    30          * @var ParagonIE_Sodium_Core32_Int32 $x1
       
    31          * @var ParagonIE_Sodium_Core32_Int32 $x2
       
    32          * @var ParagonIE_Sodium_Core32_Int32 $x3
       
    33          * @var ParagonIE_Sodium_Core32_Int32 $x4
       
    34          * @var ParagonIE_Sodium_Core32_Int32 $x5
       
    35          * @var ParagonIE_Sodium_Core32_Int32 $x6
       
    36          * @var ParagonIE_Sodium_Core32_Int32 $x7
       
    37          * @var ParagonIE_Sodium_Core32_Int32 $x8
       
    38          * @var ParagonIE_Sodium_Core32_Int32 $x9
       
    39          * @var ParagonIE_Sodium_Core32_Int32 $x10
       
    40          * @var ParagonIE_Sodium_Core32_Int32 $x11
       
    41          * @var ParagonIE_Sodium_Core32_Int32 $x12
       
    42          * @var ParagonIE_Sodium_Core32_Int32 $x13
       
    43          * @var ParagonIE_Sodium_Core32_Int32 $x14
       
    44          * @var ParagonIE_Sodium_Core32_Int32 $x15
       
    45          * @var ParagonIE_Sodium_Core32_Int32 $j0
       
    46          * @var ParagonIE_Sodium_Core32_Int32 $j1
       
    47          * @var ParagonIE_Sodium_Core32_Int32 $j2
       
    48          * @var ParagonIE_Sodium_Core32_Int32 $j3
       
    49          * @var ParagonIE_Sodium_Core32_Int32 $j4
       
    50          * @var ParagonIE_Sodium_Core32_Int32 $j5
       
    51          * @var ParagonIE_Sodium_Core32_Int32 $j6
       
    52          * @var ParagonIE_Sodium_Core32_Int32 $j7
       
    53          * @var ParagonIE_Sodium_Core32_Int32 $j8
       
    54          * @var ParagonIE_Sodium_Core32_Int32 $j9
       
    55          * @var ParagonIE_Sodium_Core32_Int32 $j10
       
    56          * @var ParagonIE_Sodium_Core32_Int32 $j11
       
    57          * @var ParagonIE_Sodium_Core32_Int32 $j12
       
    58          * @var ParagonIE_Sodium_Core32_Int32 $j13
       
    59          * @var ParagonIE_Sodium_Core32_Int32 $j14
       
    60          * @var ParagonIE_Sodium_Core32_Int32 $j15
       
    61          */
       
    62         if (self::strlen($k) < 32) {
       
    63             throw new RangeException('Key must be 32 bytes long');
       
    64         }
       
    65         if ($c === null) {
       
    66             $x0  = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
       
    67             $x5  = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
       
    68             $x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
       
    69             $x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));
       
    70         } else {
       
    71             $x0  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
       
    72             $x5  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
       
    73             $x10 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
       
    74             $x15 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
       
    75         }
       
    76         $x1  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4));
       
    77         $x2  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4));
       
    78         $x3  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4));
       
    79         $x4  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4));
       
    80         $x6  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
       
    81         $x7  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
       
    82         $x8  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
       
    83         $x9  = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
       
    84         $x11 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4));
       
    85         $x12 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4));
       
    86         $x13 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4));
       
    87         $x14 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4));
       
    88 
       
    89         $j0  = clone $x0;
       
    90         $j1  = clone $x1;
       
    91         $j2  = clone $x2;
       
    92         $j3  = clone $x3;
       
    93         $j4  = clone $x4;
       
    94         $j5  = clone $x5;
       
    95         $j6  = clone $x6;
       
    96         $j7  = clone $x7;
       
    97         $j8  = clone $x8;
       
    98         $j9  = clone $x9;
       
    99         $j10  = clone $x10;
       
   100         $j11  = clone $x11;
       
   101         $j12  = clone $x12;
       
   102         $j13  = clone $x13;
       
   103         $j14  = clone $x14;
       
   104         $j15  = clone $x15;
       
   105 
       
   106         for ($i = self::ROUNDS; $i > 0; $i -= 2) {
       
   107             $x4  = $x4->xorInt32($x0->addInt32($x12)->rotateLeft(7));
       
   108             $x8  = $x8->xorInt32($x4->addInt32($x0)->rotateLeft(9));
       
   109             $x12 = $x12->xorInt32($x8->addInt32($x4)->rotateLeft(13));
       
   110             $x0  = $x0->xorInt32($x12->addInt32($x8)->rotateLeft(18));
       
   111 
       
   112             $x9  = $x9->xorInt32($x5->addInt32($x1)->rotateLeft(7));
       
   113             $x13 = $x13->xorInt32($x9->addInt32($x5)->rotateLeft(9));
       
   114             $x1  = $x1->xorInt32($x13->addInt32($x9)->rotateLeft(13));
       
   115             $x5  = $x5->xorInt32($x1->addInt32($x13)->rotateLeft(18));
       
   116 
       
   117             $x14 = $x14->xorInt32($x10->addInt32($x6)->rotateLeft(7));
       
   118             $x2  = $x2->xorInt32($x14->addInt32($x10)->rotateLeft(9));
       
   119             $x6  = $x6->xorInt32($x2->addInt32($x14)->rotateLeft(13));
       
   120             $x10 = $x10->xorInt32($x6->addInt32($x2)->rotateLeft(18));
       
   121 
       
   122             $x3  = $x3->xorInt32($x15->addInt32($x11)->rotateLeft(7));
       
   123             $x7  = $x7->xorInt32($x3->addInt32($x15)->rotateLeft(9));
       
   124             $x11 = $x11->xorInt32($x7->addInt32($x3)->rotateLeft(13));
       
   125             $x15 = $x15->xorInt32($x11->addInt32($x7)->rotateLeft(18));
       
   126 
       
   127             $x1  = $x1->xorInt32($x0->addInt32($x3)->rotateLeft(7));
       
   128             $x2  = $x2->xorInt32($x1->addInt32($x0)->rotateLeft(9));
       
   129             $x3  = $x3->xorInt32($x2->addInt32($x1)->rotateLeft(13));
       
   130             $x0  = $x0->xorInt32($x3->addInt32($x2)->rotateLeft(18));
       
   131 
       
   132             $x6  = $x6->xorInt32($x5->addInt32($x4)->rotateLeft(7));
       
   133             $x7  = $x7->xorInt32($x6->addInt32($x5)->rotateLeft(9));
       
   134             $x4  = $x4->xorInt32($x7->addInt32($x6)->rotateLeft(13));
       
   135             $x5  = $x5->xorInt32($x4->addInt32($x7)->rotateLeft(18));
       
   136 
       
   137             $x11 = $x11->xorInt32($x10->addInt32($x9)->rotateLeft(7));
       
   138             $x8  = $x8->xorInt32($x11->addInt32($x10)->rotateLeft(9));
       
   139             $x9  = $x9->xorInt32($x8->addInt32($x11)->rotateLeft(13));
       
   140             $x10 = $x10->xorInt32($x9->addInt32($x8)->rotateLeft(18));
       
   141 
       
   142             $x12 = $x12->xorInt32($x15->addInt32($x14)->rotateLeft(7));
       
   143             $x13 = $x13->xorInt32($x12->addInt32($x15)->rotateLeft(9));
       
   144             $x14 = $x14->xorInt32($x13->addInt32($x12)->rotateLeft(13));
       
   145             $x15 = $x15->xorInt32($x14->addInt32($x13)->rotateLeft(18));
       
   146         }
       
   147 
       
   148         $x0  = $x0->addInt32($j0);
       
   149         $x1  = $x1->addInt32($j1);
       
   150         $x2  = $x2->addInt32($j2);
       
   151         $x3  = $x3->addInt32($j3);
       
   152         $x4  = $x4->addInt32($j4);
       
   153         $x5  = $x5->addInt32($j5);
       
   154         $x6  = $x6->addInt32($j6);
       
   155         $x7  = $x7->addInt32($j7);
       
   156         $x8  = $x8->addInt32($j8);
       
   157         $x9  = $x9->addInt32($j9);
       
   158         $x10 = $x10->addInt32($j10);
       
   159         $x11 = $x11->addInt32($j11);
       
   160         $x12 = $x12->addInt32($j12);
       
   161         $x13 = $x13->addInt32($j13);
       
   162         $x14 = $x14->addInt32($j14);
       
   163         $x15 = $x15->addInt32($j15);
       
   164 
       
   165         return $x0->toReverseString() .
       
   166             $x1->toReverseString() .
       
   167             $x2->toReverseString() .
       
   168             $x3->toReverseString() .
       
   169             $x4->toReverseString() .
       
   170             $x5->toReverseString() .
       
   171             $x6->toReverseString() .
       
   172             $x7->toReverseString() .
       
   173             $x8->toReverseString() .
       
   174             $x9->toReverseString() .
       
   175             $x10->toReverseString() .
       
   176             $x11->toReverseString() .
       
   177             $x12->toReverseString() .
       
   178             $x13->toReverseString() .
       
   179             $x14->toReverseString() .
       
   180             $x15->toReverseString();
       
   181     }
       
   182 
       
   183     /**
       
   184      * @internal You should not use this directly from another application
       
   185      *
       
   186      * @param int $len
       
   187      * @param string $nonce
       
   188      * @param string $key
       
   189      * @return string
       
   190      * @throws SodiumException
       
   191      * @throws TypeError
       
   192      */
       
   193     public static function salsa20($len, $nonce, $key)
       
   194     {
       
   195         if (self::strlen($key) !== 32) {
       
   196             throw new RangeException('Key must be 32 bytes long');
       
   197         }
       
   198         $kcopy = '' . $key;
       
   199         $in = self::substr($nonce, 0, 8) . str_repeat("\0", 8);
       
   200         $c = '';
       
   201         while ($len >= 64) {
       
   202             $c .= self::core_salsa20($in, $kcopy, null);
       
   203             $u = 1;
       
   204             // Internal counter.
       
   205             for ($i = 8; $i < 16; ++$i) {
       
   206                 $u += self::chrToInt($in[$i]);
       
   207                 $in[$i] = self::intToChr($u & 0xff);
       
   208                 $u >>= 8;
       
   209             }
       
   210             $len -= 64;
       
   211         }
       
   212         if ($len > 0) {
       
   213             $c .= self::substr(
       
   214                 self::core_salsa20($in, $kcopy, null),
       
   215                 0,
       
   216                 $len
       
   217             );
       
   218         }
       
   219         try {
       
   220             ParagonIE_Sodium_Compat::memzero($kcopy);
       
   221         } catch (SodiumException $ex) {
       
   222             $kcopy = null;
       
   223         }
       
   224         return $c;
       
   225     }
       
   226 
       
   227     /**
       
   228      * @internal You should not use this directly from another application
       
   229      *
       
   230      * @param string $m
       
   231      * @param string $n
       
   232      * @param int $ic
       
   233      * @param string $k
       
   234      * @return string
       
   235      * @throws SodiumException
       
   236      * @throws TypeError
       
   237      */
       
   238     public static function salsa20_xor_ic($m, $n, $ic, $k)
       
   239     {
       
   240         $mlen = self::strlen($m);
       
   241         if ($mlen < 1) {
       
   242             return '';
       
   243         }
       
   244         $kcopy = self::substr($k, 0, 32);
       
   245         $in = self::substr($n, 0, 8);
       
   246         // Initialize the counter
       
   247         $in .= ParagonIE_Sodium_Core32_Util::store64_le($ic);
       
   248 
       
   249         $c = '';
       
   250         while ($mlen >= 64) {
       
   251             $block = self::core_salsa20($in, $kcopy, null);
       
   252             $c .= self::xorStrings(
       
   253                 self::substr($m, 0, 64),
       
   254                 self::substr($block, 0, 64)
       
   255             );
       
   256             $u = 1;
       
   257             for ($i = 8; $i < 16; ++$i) {
       
   258                 $u += self::chrToInt($in[$i]);
       
   259                 $in[$i] = self::intToChr($u & 0xff);
       
   260                 $u >>= 8;
       
   261             }
       
   262 
       
   263             $mlen -= 64;
       
   264             $m = self::substr($m, 64);
       
   265         }
       
   266 
       
   267         if ($mlen) {
       
   268             $block = self::core_salsa20($in, $kcopy, null);
       
   269             $c .= self::xorStrings(
       
   270                 self::substr($m, 0, $mlen),
       
   271                 self::substr($block, 0, $mlen)
       
   272             );
       
   273         }
       
   274         try {
       
   275             ParagonIE_Sodium_Compat::memzero($block);
       
   276             ParagonIE_Sodium_Compat::memzero($kcopy);
       
   277         } catch (SodiumException $ex) {
       
   278             $block = null;
       
   279             $kcopy = null;
       
   280         }
       
   281 
       
   282         return $c;
       
   283     }
       
   284 
       
   285     /**
       
   286      * @internal You should not use this directly from another application
       
   287      *
       
   288      * @param string $message
       
   289      * @param string $nonce
       
   290      * @param string $key
       
   291      * @return string
       
   292      * @throws SodiumException
       
   293      * @throws TypeError
       
   294      */
       
   295     public static function salsa20_xor($message, $nonce, $key)
       
   296     {
       
   297         return self::xorStrings(
       
   298             $message,
       
   299             self::salsa20(
       
   300                 self::strlen($message),
       
   301                 $nonce,
       
   302                 $key
       
   303             )
       
   304         );
       
   305     }
       
   306 }