wp/wp-includes/sodium_compat/src/Core/X25519.php
changeset 9 177826044cd9
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
       
     1 <?php
       
     2 
       
     3 if (class_exists('ParagonIE_Sodium_Core_X25519', false)) {
       
     4     return;
       
     5 }
       
     6 
       
     7 /**
       
     8  * Class ParagonIE_Sodium_Core_X25519
       
     9  */
       
    10 abstract class ParagonIE_Sodium_Core_X25519 extends ParagonIE_Sodium_Core_Curve25519
       
    11 {
       
    12     /**
       
    13      * Alters the objects passed to this method in place.
       
    14      *
       
    15      * @internal You should not use this directly from another application
       
    16      *
       
    17      * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
       
    18      * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
       
    19      * @param int $b
       
    20      * @return void
       
    21      * @psalm-suppress MixedAssignment
       
    22      */
       
    23     public static function fe_cswap(
       
    24         ParagonIE_Sodium_Core_Curve25519_Fe $f,
       
    25         ParagonIE_Sodium_Core_Curve25519_Fe $g,
       
    26         $b = 0
       
    27     ) {
       
    28         $f0 = (int) $f[0];
       
    29         $f1 = (int) $f[1];
       
    30         $f2 = (int) $f[2];
       
    31         $f3 = (int) $f[3];
       
    32         $f4 = (int) $f[4];
       
    33         $f5 = (int) $f[5];
       
    34         $f6 = (int) $f[6];
       
    35         $f7 = (int) $f[7];
       
    36         $f8 = (int) $f[8];
       
    37         $f9 = (int) $f[9];
       
    38         $g0 = (int) $g[0];
       
    39         $g1 = (int) $g[1];
       
    40         $g2 = (int) $g[2];
       
    41         $g3 = (int) $g[3];
       
    42         $g4 = (int) $g[4];
       
    43         $g5 = (int) $g[5];
       
    44         $g6 = (int) $g[6];
       
    45         $g7 = (int) $g[7];
       
    46         $g8 = (int) $g[8];
       
    47         $g9 = (int) $g[9];
       
    48         $b = -$b;
       
    49         $x0 = ($f0 ^ $g0) & $b;
       
    50         $x1 = ($f1 ^ $g1) & $b;
       
    51         $x2 = ($f2 ^ $g2) & $b;
       
    52         $x3 = ($f3 ^ $g3) & $b;
       
    53         $x4 = ($f4 ^ $g4) & $b;
       
    54         $x5 = ($f5 ^ $g5) & $b;
       
    55         $x6 = ($f6 ^ $g6) & $b;
       
    56         $x7 = ($f7 ^ $g7) & $b;
       
    57         $x8 = ($f8 ^ $g8) & $b;
       
    58         $x9 = ($f9 ^ $g9) & $b;
       
    59         $f[0] = $f0 ^ $x0;
       
    60         $f[1] = $f1 ^ $x1;
       
    61         $f[2] = $f2 ^ $x2;
       
    62         $f[3] = $f3 ^ $x3;
       
    63         $f[4] = $f4 ^ $x4;
       
    64         $f[5] = $f5 ^ $x5;
       
    65         $f[6] = $f6 ^ $x6;
       
    66         $f[7] = $f7 ^ $x7;
       
    67         $f[8] = $f8 ^ $x8;
       
    68         $f[9] = $f9 ^ $x9;
       
    69         $g[0] = $g0 ^ $x0;
       
    70         $g[1] = $g1 ^ $x1;
       
    71         $g[2] = $g2 ^ $x2;
       
    72         $g[3] = $g3 ^ $x3;
       
    73         $g[4] = $g4 ^ $x4;
       
    74         $g[5] = $g5 ^ $x5;
       
    75         $g[6] = $g6 ^ $x6;
       
    76         $g[7] = $g7 ^ $x7;
       
    77         $g[8] = $g8 ^ $x8;
       
    78         $g[9] = $g9 ^ $x9;
       
    79     }
       
    80 
       
    81     /**
       
    82      * @internal You should not use this directly from another application
       
    83      *
       
    84      * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
       
    85      * @return ParagonIE_Sodium_Core_Curve25519_Fe
       
    86      */
       
    87     public static function fe_mul121666(ParagonIE_Sodium_Core_Curve25519_Fe $f)
       
    88     {
       
    89         $h = array(
       
    90             self::mul((int) $f[0], 121666, 17),
       
    91             self::mul((int) $f[1], 121666, 17),
       
    92             self::mul((int) $f[2], 121666, 17),
       
    93             self::mul((int) $f[3], 121666, 17),
       
    94             self::mul((int) $f[4], 121666, 17),
       
    95             self::mul((int) $f[5], 121666, 17),
       
    96             self::mul((int) $f[6], 121666, 17),
       
    97             self::mul((int) $f[7], 121666, 17),
       
    98             self::mul((int) $f[8], 121666, 17),
       
    99             self::mul((int) $f[9], 121666, 17)
       
   100         );
       
   101 
       
   102         /** @var int $carry9 */
       
   103         $carry9 = ($h[9] + (1 << 24)) >> 25;
       
   104         $h[0] += self::mul($carry9, 19, 5);
       
   105         $h[9] -= $carry9 << 25;
       
   106         /** @var int $carry1 */
       
   107         $carry1 = ($h[1] + (1 << 24)) >> 25;
       
   108         $h[2] += $carry1;
       
   109         $h[1] -= $carry1 << 25;
       
   110         /** @var int $carry3 */
       
   111         $carry3 = ($h[3] + (1 << 24)) >> 25;
       
   112         $h[4] += $carry3;
       
   113         $h[3] -= $carry3 << 25;
       
   114         /** @var int $carry5 */
       
   115         $carry5 = ($h[5] + (1 << 24)) >> 25;
       
   116         $h[6] += $carry5;
       
   117         $h[5] -= $carry5 << 25;
       
   118         /** @var int $carry7 */
       
   119         $carry7 = ($h[7] + (1 << 24)) >> 25;
       
   120         $h[8] += $carry7;
       
   121         $h[7] -= $carry7 << 25;
       
   122 
       
   123         /** @var int $carry0 */
       
   124         $carry0 = ($h[0] + (1 << 25)) >> 26;
       
   125         $h[1] += $carry0;
       
   126         $h[0] -= $carry0 << 26;
       
   127         /** @var int $carry2 */
       
   128         $carry2 = ($h[2] + (1 << 25)) >> 26;
       
   129         $h[3] += $carry2;
       
   130         $h[2] -= $carry2 << 26;
       
   131         /** @var int $carry4 */
       
   132         $carry4 = ($h[4] + (1 << 25)) >> 26;
       
   133         $h[5] += $carry4;
       
   134         $h[4] -= $carry4 << 26;
       
   135         /** @var int $carry6 */
       
   136         $carry6 = ($h[6] + (1 << 25)) >> 26;
       
   137         $h[7] += $carry6;
       
   138         $h[6] -= $carry6 << 26;
       
   139         /** @var int $carry8 */
       
   140         $carry8 = ($h[8] + (1 << 25)) >> 26;
       
   141         $h[9] += $carry8;
       
   142         $h[8] -= $carry8 << 26;
       
   143 
       
   144         foreach ($h as $i => $value) {
       
   145             $h[$i] = (int) $value;
       
   146         }
       
   147         return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
       
   148     }
       
   149 
       
   150     /**
       
   151      * @internal You should not use this directly from another application
       
   152      *
       
   153      * Inline comments preceded by # are from libsodium's ref10 code.
       
   154      *
       
   155      * @param string $n
       
   156      * @param string $p
       
   157      * @return string
       
   158      * @throws SodiumException
       
   159      * @throws TypeError
       
   160      */
       
   161     public static function crypto_scalarmult_curve25519_ref10($n, $p)
       
   162     {
       
   163         # for (i = 0;i < 32;++i) e[i] = n[i];
       
   164         $e = '' . $n;
       
   165         # e[0] &= 248;
       
   166         $e[0] = self::intToChr(
       
   167             self::chrToInt($e[0]) & 248
       
   168         );
       
   169         # e[31] &= 127;
       
   170         # e[31] |= 64;
       
   171         $e[31] = self::intToChr(
       
   172             (self::chrToInt($e[31]) & 127) | 64
       
   173         );
       
   174         # fe_frombytes(x1,p);
       
   175         $x1 = self::fe_frombytes($p);
       
   176         # fe_1(x2);
       
   177         $x2 = self::fe_1();
       
   178         # fe_0(z2);
       
   179         $z2 = self::fe_0();
       
   180         # fe_copy(x3,x1);
       
   181         $x3 = self::fe_copy($x1);
       
   182         # fe_1(z3);
       
   183         $z3 = self::fe_1();
       
   184 
       
   185         # swap = 0;
       
   186         /** @var int $swap */
       
   187         $swap = 0;
       
   188 
       
   189         # for (pos = 254;pos >= 0;--pos) {
       
   190         for ($pos = 254; $pos >= 0; --$pos) {
       
   191             # b = e[pos / 8] >> (pos & 7);
       
   192             /** @var int $b */
       
   193             $b = self::chrToInt(
       
   194                     $e[(int) floor($pos / 8)]
       
   195                 ) >> ($pos & 7);
       
   196             # b &= 1;
       
   197             $b &= 1;
       
   198             # swap ^= b;
       
   199             $swap ^= $b;
       
   200             # fe_cswap(x2,x3,swap);
       
   201             self::fe_cswap($x2, $x3, $swap);
       
   202             # fe_cswap(z2,z3,swap);
       
   203             self::fe_cswap($z2, $z3, $swap);
       
   204             # swap = b;
       
   205             $swap = $b;
       
   206             # fe_sub(tmp0,x3,z3);
       
   207             $tmp0 = self::fe_sub($x3, $z3);
       
   208             # fe_sub(tmp1,x2,z2);
       
   209             $tmp1 = self::fe_sub($x2, $z2);
       
   210 
       
   211             # fe_add(x2,x2,z2);
       
   212             $x2 = self::fe_add($x2, $z2);
       
   213 
       
   214             # fe_add(z2,x3,z3);
       
   215             $z2 = self::fe_add($x3, $z3);
       
   216 
       
   217             # fe_mul(z3,tmp0,x2);
       
   218             $z3 = self::fe_mul($tmp0, $x2);
       
   219 
       
   220             # fe_mul(z2,z2,tmp1);
       
   221             $z2 = self::fe_mul($z2, $tmp1);
       
   222 
       
   223             # fe_sq(tmp0,tmp1);
       
   224             $tmp0 = self::fe_sq($tmp1);
       
   225 
       
   226             # fe_sq(tmp1,x2);
       
   227             $tmp1 = self::fe_sq($x2);
       
   228 
       
   229             # fe_add(x3,z3,z2);
       
   230             $x3 = self::fe_add($z3, $z2);
       
   231 
       
   232             # fe_sub(z2,z3,z2);
       
   233             $z2 = self::fe_sub($z3, $z2);
       
   234 
       
   235             # fe_mul(x2,tmp1,tmp0);
       
   236             $x2 = self::fe_mul($tmp1, $tmp0);
       
   237 
       
   238             # fe_sub(tmp1,tmp1,tmp0);
       
   239             $tmp1 = self::fe_sub($tmp1, $tmp0);
       
   240 
       
   241             # fe_sq(z2,z2);
       
   242             $z2 = self::fe_sq($z2);
       
   243 
       
   244             # fe_mul121666(z3,tmp1);
       
   245             $z3 = self::fe_mul121666($tmp1);
       
   246 
       
   247             # fe_sq(x3,x3);
       
   248             $x3 = self::fe_sq($x3);
       
   249 
       
   250             # fe_add(tmp0,tmp0,z3);
       
   251             $tmp0 = self::fe_add($tmp0, $z3);
       
   252 
       
   253             # fe_mul(z3,x1,z2);
       
   254             $z3 = self::fe_mul($x1, $z2);
       
   255 
       
   256             # fe_mul(z2,tmp1,tmp0);
       
   257             $z2 = self::fe_mul($tmp1, $tmp0);
       
   258         }
       
   259 
       
   260         # fe_cswap(x2,x3,swap);
       
   261         self::fe_cswap($x2, $x3, $swap);
       
   262 
       
   263         # fe_cswap(z2,z3,swap);
       
   264         self::fe_cswap($z2, $z3, $swap);
       
   265 
       
   266         # fe_invert(z2,z2);
       
   267         $z2 = self::fe_invert($z2);
       
   268 
       
   269         # fe_mul(x2,x2,z2);
       
   270         $x2 = self::fe_mul($x2, $z2);
       
   271         # fe_tobytes(q,x2);
       
   272         return self::fe_tobytes($x2);
       
   273     }
       
   274 
       
   275     /**
       
   276      * @internal You should not use this directly from another application
       
   277      *
       
   278      * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY
       
   279      * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ
       
   280      * @return ParagonIE_Sodium_Core_Curve25519_Fe
       
   281      */
       
   282     public static function edwards_to_montgomery(
       
   283         ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY,
       
   284         ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ
       
   285     ) {
       
   286         $tempX = self::fe_add($edwardsZ, $edwardsY);
       
   287         $tempZ = self::fe_sub($edwardsZ, $edwardsY);
       
   288         $tempZ = self::fe_invert($tempZ);
       
   289         return self::fe_mul($tempX, $tempZ);
       
   290     }
       
   291 
       
   292     /**
       
   293      * @internal You should not use this directly from another application
       
   294      *
       
   295      * @param string $n
       
   296      * @return string
       
   297      * @throws SodiumException
       
   298      * @throws TypeError
       
   299      */
       
   300     public static function crypto_scalarmult_curve25519_ref10_base($n)
       
   301     {
       
   302         # for (i = 0;i < 32;++i) e[i] = n[i];
       
   303         $e = '' . $n;
       
   304 
       
   305         # e[0] &= 248;
       
   306         $e[0] = self::intToChr(
       
   307             self::chrToInt($e[0]) & 248
       
   308         );
       
   309 
       
   310         # e[31] &= 127;
       
   311         # e[31] |= 64;
       
   312         $e[31] = self::intToChr(
       
   313             (self::chrToInt($e[31]) & 127) | 64
       
   314         );
       
   315 
       
   316         $A = self::ge_scalarmult_base($e);
       
   317         if (
       
   318             !($A->Y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)
       
   319                 ||
       
   320             !($A->Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)
       
   321         ) {
       
   322             throw new TypeError('Null points encountered');
       
   323         }
       
   324         $pk = self::edwards_to_montgomery($A->Y, $A->Z);
       
   325         return self::fe_tobytes($pk);
       
   326     }
       
   327 }