angelovcom.net

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

ChaCha20.php (14511B)


      1 <?php
      2 
      3 if (class_exists('ParagonIE_Sodium_Core32_ChaCha20', false)) {
      4     return;
      5 }
      6 
      7 /**
      8  * Class ParagonIE_Sodium_Core32_ChaCha20
      9  */
     10 class ParagonIE_Sodium_Core32_ChaCha20 extends ParagonIE_Sodium_Core32_Util
     11 {
     12     /**
     13      * The ChaCha20 quarter round function. Works on four 32-bit integers.
     14      *
     15      * @internal You should not use this directly from another application
     16      *
     17      * @param ParagonIE_Sodium_Core32_Int32 $a
     18      * @param ParagonIE_Sodium_Core32_Int32 $b
     19      * @param ParagonIE_Sodium_Core32_Int32 $c
     20      * @param ParagonIE_Sodium_Core32_Int32 $d
     21      * @return array<int, ParagonIE_Sodium_Core32_Int32>
     22      * @throws SodiumException
     23      * @throws TypeError
     24      */
     25     protected static function quarterRound(
     26         ParagonIE_Sodium_Core32_Int32 $a,
     27         ParagonIE_Sodium_Core32_Int32 $b,
     28         ParagonIE_Sodium_Core32_Int32 $c,
     29         ParagonIE_Sodium_Core32_Int32 $d
     30     ) {
     31         /** @var ParagonIE_Sodium_Core32_Int32 $a */
     32         /** @var ParagonIE_Sodium_Core32_Int32 $b */
     33         /** @var ParagonIE_Sodium_Core32_Int32 $c */
     34         /** @var ParagonIE_Sodium_Core32_Int32 $d */
     35 
     36         # a = PLUS(a,b); d = ROTATE(XOR(d,a),16);
     37         $a = $a->addInt32($b);
     38         $d = $d->xorInt32($a)->rotateLeft(16);
     39 
     40         # c = PLUS(c,d); b = ROTATE(XOR(b,c),12);
     41         $c = $c->addInt32($d);
     42         $b = $b->xorInt32($c)->rotateLeft(12);
     43 
     44         # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8);
     45         $a = $a->addInt32($b);
     46         $d = $d->xorInt32($a)->rotateLeft(8);
     47 
     48         # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
     49         $c = $c->addInt32($d);
     50         $b = $b->xorInt32($c)->rotateLeft(7);
     51 
     52         return array($a, $b, $c, $d);
     53     }
     54 
     55     /**
     56      * @internal You should not use this directly from another application
     57      *
     58      * @param ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx
     59      * @param string $message
     60      *
     61      * @return string
     62      * @throws SodiumException
     63      * @throws TypeError
     64      */
     65     public static function encryptBytes(
     66         ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx,
     67         $message = ''
     68     ) {
     69         $bytes = self::strlen($message);
     70 
     71         /** @var ParagonIE_Sodium_Core32_Int32 $x0 */
     72         /** @var ParagonIE_Sodium_Core32_Int32 $x1 */
     73         /** @var ParagonIE_Sodium_Core32_Int32 $x2 */
     74         /** @var ParagonIE_Sodium_Core32_Int32 $x3 */
     75         /** @var ParagonIE_Sodium_Core32_Int32 $x4 */
     76         /** @var ParagonIE_Sodium_Core32_Int32 $x5 */
     77         /** @var ParagonIE_Sodium_Core32_Int32 $x6 */
     78         /** @var ParagonIE_Sodium_Core32_Int32 $x7 */
     79         /** @var ParagonIE_Sodium_Core32_Int32 $x8 */
     80         /** @var ParagonIE_Sodium_Core32_Int32 $x9 */
     81         /** @var ParagonIE_Sodium_Core32_Int32 $x10 */
     82         /** @var ParagonIE_Sodium_Core32_Int32 $x11 */
     83         /** @var ParagonIE_Sodium_Core32_Int32 $x12 */
     84         /** @var ParagonIE_Sodium_Core32_Int32 $x13 */
     85         /** @var ParagonIE_Sodium_Core32_Int32 $x14 */
     86         /** @var ParagonIE_Sodium_Core32_Int32 $x15 */
     87 
     88         /*
     89         j0 = ctx->input[0];
     90         j1 = ctx->input[1];
     91         j2 = ctx->input[2];
     92         j3 = ctx->input[3];
     93         j4 = ctx->input[4];
     94         j5 = ctx->input[5];
     95         j6 = ctx->input[6];
     96         j7 = ctx->input[7];
     97         j8 = ctx->input[8];
     98         j9 = ctx->input[9];
     99         j10 = ctx->input[10];
    100         j11 = ctx->input[11];
    101         j12 = ctx->input[12];
    102         j13 = ctx->input[13];
    103         j14 = ctx->input[14];
    104         j15 = ctx->input[15];
    105         */
    106         /** @var ParagonIE_Sodium_Core32_Int32 $j0 */
    107         $j0  = $ctx[0];
    108         /** @var ParagonIE_Sodium_Core32_Int32 $j1 */
    109         $j1  = $ctx[1];
    110         /** @var ParagonIE_Sodium_Core32_Int32 $j2 */
    111         $j2  = $ctx[2];
    112         /** @var ParagonIE_Sodium_Core32_Int32 $j3 */
    113         $j3  = $ctx[3];
    114         /** @var ParagonIE_Sodium_Core32_Int32 $j4 */
    115         $j4  = $ctx[4];
    116         /** @var ParagonIE_Sodium_Core32_Int32 $j5 */
    117         $j5  = $ctx[5];
    118         /** @var ParagonIE_Sodium_Core32_Int32 $j6 */
    119         $j6  = $ctx[6];
    120         /** @var ParagonIE_Sodium_Core32_Int32 $j7 */
    121         $j7  = $ctx[7];
    122         /** @var ParagonIE_Sodium_Core32_Int32 $j8 */
    123         $j8  = $ctx[8];
    124         /** @var ParagonIE_Sodium_Core32_Int32 $j9 */
    125         $j9  = $ctx[9];
    126         /** @var ParagonIE_Sodium_Core32_Int32 $j10 */
    127         $j10 = $ctx[10];
    128         /** @var ParagonIE_Sodium_Core32_Int32 $j11 */
    129         $j11 = $ctx[11];
    130         /** @var ParagonIE_Sodium_Core32_Int32 $j12 */
    131         $j12 = $ctx[12];
    132         /** @var ParagonIE_Sodium_Core32_Int32 $j13 */
    133         $j13 = $ctx[13];
    134         /** @var ParagonIE_Sodium_Core32_Int32 $j14 */
    135         $j14 = $ctx[14];
    136         /** @var ParagonIE_Sodium_Core32_Int32 $j15 */
    137         $j15 = $ctx[15];
    138 
    139         $c = '';
    140         for (;;) {
    141             if ($bytes < 64) {
    142                 $message .= str_repeat("\x00", 64 - $bytes);
    143             }
    144 
    145             $x0 =  clone $j0;
    146             $x1 =  clone $j1;
    147             $x2 =  clone $j2;
    148             $x3 =  clone $j3;
    149             $x4 =  clone $j4;
    150             $x5 =  clone $j5;
    151             $x6 =  clone $j6;
    152             $x7 =  clone $j7;
    153             $x8 =  clone $j8;
    154             $x9 =  clone $j9;
    155             $x10 = clone $j10;
    156             $x11 = clone $j11;
    157             $x12 = clone $j12;
    158             $x13 = clone $j13;
    159             $x14 = clone $j14;
    160             $x15 = clone $j15;
    161 
    162             # for (i = 20; i > 0; i -= 2) {
    163             for ($i = 20; $i > 0; $i -= 2) {
    164                 # QUARTERROUND( x0,  x4,  x8,  x12)
    165                 list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12);
    166 
    167                 # QUARTERROUND( x1,  x5,  x9,  x13)
    168                 list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13);
    169 
    170                 # QUARTERROUND( x2,  x6,  x10,  x14)
    171                 list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14);
    172 
    173                 # QUARTERROUND( x3,  x7,  x11,  x15)
    174                 list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15);
    175 
    176                 # QUARTERROUND( x0,  x5,  x10,  x15)
    177                 list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15);
    178 
    179                 # QUARTERROUND( x1,  x6,  x11,  x12)
    180                 list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12);
    181 
    182                 # QUARTERROUND( x2,  x7,  x8,  x13)
    183                 list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13);
    184 
    185                 # QUARTERROUND( x3,  x4,  x9,  x14)
    186                 list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14);
    187             }
    188             /*
    189             x0 = PLUS(x0, j0);
    190             x1 = PLUS(x1, j1);
    191             x2 = PLUS(x2, j2);
    192             x3 = PLUS(x3, j3);
    193             x4 = PLUS(x4, j4);
    194             x5 = PLUS(x5, j5);
    195             x6 = PLUS(x6, j6);
    196             x7 = PLUS(x7, j7);
    197             x8 = PLUS(x8, j8);
    198             x9 = PLUS(x9, j9);
    199             x10 = PLUS(x10, j10);
    200             x11 = PLUS(x11, j11);
    201             x12 = PLUS(x12, j12);
    202             x13 = PLUS(x13, j13);
    203             x14 = PLUS(x14, j14);
    204             x15 = PLUS(x15, j15);
    205             */
    206             $x0 = $x0->addInt32($j0);
    207             $x1 = $x1->addInt32($j1);
    208             $x2 = $x2->addInt32($j2);
    209             $x3 = $x3->addInt32($j3);
    210             $x4 = $x4->addInt32($j4);
    211             $x5 = $x5->addInt32($j5);
    212             $x6 = $x6->addInt32($j6);
    213             $x7 = $x7->addInt32($j7);
    214             $x8 = $x8->addInt32($j8);
    215             $x9 = $x9->addInt32($j9);
    216             $x10 = $x10->addInt32($j10);
    217             $x11 = $x11->addInt32($j11);
    218             $x12 = $x12->addInt32($j12);
    219             $x13 = $x13->addInt32($j13);
    220             $x14 = $x14->addInt32($j14);
    221             $x15 = $x15->addInt32($j15);
    222 
    223             /*
    224             x0 = XOR(x0, LOAD32_LE(m + 0));
    225             x1 = XOR(x1, LOAD32_LE(m + 4));
    226             x2 = XOR(x2, LOAD32_LE(m + 8));
    227             x3 = XOR(x3, LOAD32_LE(m + 12));
    228             x4 = XOR(x4, LOAD32_LE(m + 16));
    229             x5 = XOR(x5, LOAD32_LE(m + 20));
    230             x6 = XOR(x6, LOAD32_LE(m + 24));
    231             x7 = XOR(x7, LOAD32_LE(m + 28));
    232             x8 = XOR(x8, LOAD32_LE(m + 32));
    233             x9 = XOR(x9, LOAD32_LE(m + 36));
    234             x10 = XOR(x10, LOAD32_LE(m + 40));
    235             x11 = XOR(x11, LOAD32_LE(m + 44));
    236             x12 = XOR(x12, LOAD32_LE(m + 48));
    237             x13 = XOR(x13, LOAD32_LE(m + 52));
    238             x14 = XOR(x14, LOAD32_LE(m + 56));
    239             x15 = XOR(x15, LOAD32_LE(m + 60));
    240             */
    241             $x0  =  $x0->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,  0, 4)));
    242             $x1  =  $x1->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,  4, 4)));
    243             $x2  =  $x2->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,  8, 4)));
    244             $x3  =  $x3->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4)));
    245             $x4  =  $x4->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 16, 4)));
    246             $x5  =  $x5->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 20, 4)));
    247             $x6  =  $x6->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 24, 4)));
    248             $x7  =  $x7->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 28, 4)));
    249             $x8  =  $x8->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 32, 4)));
    250             $x9  =  $x9->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 36, 4)));
    251             $x10 = $x10->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 40, 4)));
    252             $x11 = $x11->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 44, 4)));
    253             $x12 = $x12->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 48, 4)));
    254             $x13 = $x13->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 52, 4)));
    255             $x14 = $x14->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 56, 4)));
    256             $x15 = $x15->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 60, 4)));
    257 
    258             /*
    259                 j12 = PLUSONE(j12);
    260                 if (!j12) {
    261                     j13 = PLUSONE(j13);
    262                 }
    263              */
    264             /** @var ParagonIE_Sodium_Core32_Int32 $j12 */
    265             $j12 = $j12->addInt(1);
    266             if ($j12->limbs[0] === 0 && $j12->limbs[1] === 0) {
    267                 $j13 = $j13->addInt(1);
    268             }
    269 
    270             /*
    271             STORE32_LE(c + 0, x0);
    272             STORE32_LE(c + 4, x1);
    273             STORE32_LE(c + 8, x2);
    274             STORE32_LE(c + 12, x3);
    275             STORE32_LE(c + 16, x4);
    276             STORE32_LE(c + 20, x5);
    277             STORE32_LE(c + 24, x6);
    278             STORE32_LE(c + 28, x7);
    279             STORE32_LE(c + 32, x8);
    280             STORE32_LE(c + 36, x9);
    281             STORE32_LE(c + 40, x10);
    282             STORE32_LE(c + 44, x11);
    283             STORE32_LE(c + 48, x12);
    284             STORE32_LE(c + 52, x13);
    285             STORE32_LE(c + 56, x14);
    286             STORE32_LE(c + 60, x15);
    287             */
    288 
    289             $block = $x0->toReverseString() .
    290                 $x1->toReverseString() .
    291                 $x2->toReverseString() .
    292                 $x3->toReverseString() .
    293                 $x4->toReverseString() .
    294                 $x5->toReverseString() .
    295                 $x6->toReverseString() .
    296                 $x7->toReverseString() .
    297                 $x8->toReverseString() .
    298                 $x9->toReverseString() .
    299                 $x10->toReverseString() .
    300                 $x11->toReverseString() .
    301                 $x12->toReverseString() .
    302                 $x13->toReverseString() .
    303                 $x14->toReverseString() .
    304                 $x15->toReverseString();
    305 
    306             /* Partial block */
    307             if ($bytes < 64) {
    308                 $c .= self::substr($block, 0, $bytes);
    309                 break;
    310             }
    311 
    312             /* Full block */
    313             $c .= $block;
    314             $bytes -= 64;
    315             if ($bytes <= 0) {
    316                 break;
    317             }
    318             $message = self::substr($message, 64);
    319         }
    320         /* end for(;;) loop */
    321 
    322         $ctx[12] = $j12;
    323         $ctx[13] = $j13;
    324         return $c;
    325     }
    326 
    327     /**
    328      * @internal You should not use this directly from another application
    329      *
    330      * @param int $len
    331      * @param string $nonce
    332      * @param string $key
    333      * @return string
    334      * @throws SodiumException
    335      * @throws TypeError
    336      */
    337     public static function stream($len = 64, $nonce = '', $key = '')
    338     {
    339         return self::encryptBytes(
    340             new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce),
    341             str_repeat("\x00", $len)
    342         );
    343     }
    344 
    345     /**
    346      * @internal You should not use this directly from another application
    347      *
    348      * @param int $len
    349      * @param string $nonce
    350      * @param string $key
    351      * @return string
    352      * @throws SodiumException
    353      * @throws TypeError
    354      */
    355     public static function ietfStream($len, $nonce = '', $key = '')
    356     {
    357         return self::encryptBytes(
    358             new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce),
    359             str_repeat("\x00", $len)
    360         );
    361     }
    362 
    363     /**
    364      * @internal You should not use this directly from another application
    365      *
    366      * @param string $message
    367      * @param string $nonce
    368      * @param string $key
    369      * @param string $ic
    370      * @return string
    371      * @throws SodiumException
    372      * @throws TypeError
    373      */
    374     public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '')
    375     {
    376         return self::encryptBytes(
    377             new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce, $ic),
    378             $message
    379         );
    380     }
    381 
    382     /**
    383      * @internal You should not use this directly from another application
    384      *
    385      * @param string $message
    386      * @param string $nonce
    387      * @param string $key
    388      * @param string $ic
    389      * @return string
    390      * @throws SodiumException
    391      * @throws TypeError
    392      */
    393     public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
    394     {
    395         return self::encryptBytes(
    396             new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce, $ic),
    397             $message
    398         );
    399     }
    400 }