wp/wp-includes/sodium_compat/src/Core32/ChaCha20.php
changeset 9 177826044cd9
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
       
     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 }