balmet.com

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

ChaCha20.php (12934B)


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