ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

Salsa20.php (11506B)


      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 }