[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/phpseclib/phpseclib/phpseclib/Crypt/ -> DH.php (source)

   1  <?php
   2  
   3  /**
   4   * Pure-PHP (EC)DH implementation
   5   *
   6   * PHP version 5
   7   *
   8   * Here's an example of how to compute a shared secret with this library:
   9   * <code>
  10   * <?php
  11   * include 'vendor/autoload.php';
  12   *
  13   * $ourPrivate = \phpseclib3\Crypt\DH::createKey();
  14   * $secret = DH::computeSecret($ourPrivate, $theirPublic);
  15   *
  16   * ?>
  17   * </code>
  18   *
  19   * @author    Jim Wigginton <terrafrost@php.net>
  20   * @copyright 2016 Jim Wigginton
  21   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  22   * @link      http://phpseclib.sourceforge.net
  23   */
  24  
  25  namespace phpseclib3\Crypt;
  26  
  27  use phpseclib3\Crypt\Common\AsymmetricKey;
  28  use phpseclib3\Crypt\DH\Parameters;
  29  use phpseclib3\Crypt\DH\PrivateKey;
  30  use phpseclib3\Crypt\DH\PublicKey;
  31  use phpseclib3\Exception\NoKeyLoadedException;
  32  use phpseclib3\Exception\UnsupportedOperationException;
  33  use phpseclib3\Math\BigInteger;
  34  
  35  /**
  36   * Pure-PHP (EC)DH implementation
  37   *
  38   * @author  Jim Wigginton <terrafrost@php.net>
  39   */
  40  abstract class DH extends AsymmetricKey
  41  {
  42      /**
  43       * Algorithm Name
  44       *
  45       * @var string
  46       */
  47      const ALGORITHM = 'DH';
  48  
  49      /**
  50       * DH prime
  51       *
  52       * @var \phpseclib3\Math\BigInteger
  53       */
  54      protected $prime;
  55  
  56      /**
  57       * DH Base
  58       *
  59       * Prime divisor of p-1
  60       *
  61       * @var \phpseclib3\Math\BigInteger
  62       */
  63      protected $base;
  64  
  65      /**
  66       * Public Key
  67       *
  68       * @var \phpseclib3\Math\BigInteger
  69       */
  70      protected $publicKey;
  71  
  72      /**
  73       * Create DH parameters
  74       *
  75       * This method is a bit polymorphic. It can take any of the following:
  76       *  - two BigInteger's (prime and base)
  77       *  - an integer representing the size of the prime in bits (the base is assumed to be 2)
  78       *  - a string (eg. diffie-hellman-group14-sha1)
  79       *
  80       * @return Parameters
  81       */
  82      public static function createParameters(...$args)
  83      {
  84          $class = new \ReflectionClass(static::class);
  85          if ($class->isFinal()) {
  86              throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')');
  87          }
  88  
  89          $params = new Parameters();
  90          if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) {
  91              //if (!$args[0]->isPrime()) {
  92              //    throw new \InvalidArgumentException('The first parameter should be a prime number');
  93              //}
  94              $params->prime = $args[0];
  95              $params->base = $args[1];
  96              return $params;
  97          } elseif (count($args) == 1 && is_numeric($args[0])) {
  98              $params->prime = BigInteger::randomPrime($args[0]);
  99              $params->base = new BigInteger(2);
 100              return $params;
 101          } elseif (count($args) != 1 || !is_string($args[0])) {
 102              throw new \InvalidArgumentException('Valid parameters are either: two BigInteger\'s (prime and base), a single integer (the length of the prime; base is assumed to be 2) or a string');
 103          }
 104          switch ($args[0]) {
 105              // see http://tools.ietf.org/html/rfc2409#section-6.2 and
 106              // http://tools.ietf.org/html/rfc2412, appendex E
 107              case 'diffie-hellman-group1-sha1':
 108                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 109                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 110                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 111                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
 112                  break;
 113              // see http://tools.ietf.org/html/rfc3526#section-3
 114              case 'diffie-hellman-group14-sha1': // 2048-bit MODP Group
 115              case 'diffie-hellman-group14-sha256':
 116                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 117                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 118                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 119                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
 120                           '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
 121                           '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
 122                           'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
 123                           '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
 124                  break;
 125              // see https://tools.ietf.org/html/rfc3526#section-4
 126              case 'diffie-hellman-group15-sha512': // 3072-bit MODP Group
 127                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 128                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 129                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 130                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
 131                           '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
 132                           '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
 133                           'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
 134                           '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
 135                           'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
 136                           'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
 137                           'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
 138                           '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';
 139                  break;
 140              // see https://tools.ietf.org/html/rfc3526#section-5
 141              case 'diffie-hellman-group16-sha512': // 4096-bit MODP Group
 142                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 143                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 144                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 145                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
 146                           '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
 147                           '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
 148                           'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
 149                           '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
 150                           'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
 151                           'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
 152                           'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
 153                           '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
 154                           '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
 155                           'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
 156                           '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
 157                           '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF';
 158                  break;
 159              // see https://tools.ietf.org/html/rfc3526#section-6
 160              case 'diffie-hellman-group17-sha512': // 6144-bit MODP Group
 161                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 162                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 163                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 164                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
 165                           '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
 166                           '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
 167                           'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
 168                           '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
 169                           'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
 170                           'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
 171                           'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
 172                           '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
 173                           '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
 174                           'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
 175                           '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
 176                           '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' .
 177                           'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' .
 178                           'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' .
 179                           'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' .
 180                           'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' .
 181                           '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' .
 182                           'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' .
 183                           'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' .
 184                           '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF';
 185                  break;
 186              // see https://tools.ietf.org/html/rfc3526#section-7
 187              case 'diffie-hellman-group18-sha512': // 8192-bit MODP Group
 188                  $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
 189                           '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
 190                           '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
 191                           'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
 192                           '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
 193                           '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
 194                           'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
 195                           '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' .
 196                           'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' .
 197                           'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' .
 198                           'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' .
 199                           '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' .
 200                           '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' .
 201                           'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' .
 202                           '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' .
 203                           '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' .
 204                           'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' .
 205                           'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' .
 206                           'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' .
 207                           'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' .
 208                           '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' .
 209                           'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' .
 210                           'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' .
 211                           '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4' .
 212                           '38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED' .
 213                           '2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652D' .
 214                           'E3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B' .
 215                           '4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6' .
 216                           '6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851D' .
 217                           'F9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92' .
 218                           '4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA' .
 219                           '9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF';
 220                  break;
 221              default:
 222                  throw new \InvalidArgumentException('Invalid named prime provided');
 223          }
 224  
 225          $params->prime = new BigInteger($prime, 16);
 226          $params->base = new BigInteger(2);
 227  
 228          return $params;
 229      }
 230  
 231      /**
 232       * Create public / private key pair.
 233       *
 234       * The rationale for the second parameter is described in http://tools.ietf.org/html/rfc4419#section-6.2 :
 235       *
 236       * "To increase the speed of the key exchange, both client and server may
 237       *  reduce the size of their private exponents.  It should be at least
 238       *  twice as long as the key material that is generated from the shared
 239       *  secret.  For more details, see the paper by van Oorschot and Wiener
 240       *  [VAN-OORSCHOT]."
 241       *
 242       * $length is in bits
 243       *
 244       * @param Parameters $params
 245       * @param int $length optional
 246       * @return DH\PrivateKey
 247       */
 248      public static function createKey(Parameters $params, $length = 0)
 249      {
 250          $class = new \ReflectionClass(static::class);
 251          if ($class->isFinal()) {
 252              throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
 253          }
 254  
 255          $one = new BigInteger(1);
 256          if ($length) {
 257              $max = $one->bitwise_leftShift($length);
 258              $max = $max->subtract($one);
 259          } else {
 260              $max = $params->prime->subtract($one);
 261          }
 262  
 263          $key = new PrivateKey();
 264          $key->prime = $params->prime;
 265          $key->base = $params->base;
 266          $key->privateKey = BigInteger::randomRange($one, $max);
 267          $key->publicKey = $key->base->powMod($key->privateKey, $key->prime);
 268          return $key;
 269      }
 270  
 271      /**
 272       * Compute Shared Secret
 273       *
 274       * @param PrivateKey|EC $private
 275       * @param PublicKey|BigInteger|string $public
 276       * @return mixed
 277       */
 278      public static function computeSecret($private, $public)
 279      {
 280          if ($private instanceof PrivateKey) { // DH\PrivateKey
 281              switch (true) {
 282                  case $public instanceof PublicKey:
 283                      if (!$private->prime->equals($public->prime) || !$private->base->equals($public->base)) {
 284                          throw new \InvalidArgumentException('The public and private key do not share the same prime and / or base numbers');
 285                      }
 286                      return $public->publicKey->powMod($private->privateKey, $private->prime)->toBytes(true);
 287                  case is_string($public):
 288                      $public = new BigInteger($public, -256);
 289                      // fall-through
 290                  case $public instanceof BigInteger:
 291                      return $public->powMod($private->privateKey, $private->prime)->toBytes(true);
 292                  default:
 293                      throw new \InvalidArgumentException('$public needs to be an instance of DH\PublicKey, a BigInteger or a string');
 294              }
 295          }
 296  
 297          if ($private instanceof EC\PrivateKey) {
 298              switch (true) {
 299                  case $public instanceof EC\PublicKey:
 300                      $public = $public->getEncodedCoordinates();
 301                      // fall-through
 302                  case is_string($public):
 303                      $point = $private->multiply($public);
 304                      switch ($private->getCurve()) {
 305                          case 'Curve25519':
 306                          case 'Curve448':
 307                              $secret = $point;
 308                              break;
 309                          default:
 310                              // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned
 311                              $secret = substr($point, 1, (strlen($point) - 1) >> 1);
 312                      }
 313                      /*
 314                      if (($secret[0] & "\x80") === "\x80") {
 315                          $secret = "\0$secret";
 316                      }
 317                      */
 318                      return $secret;
 319                  default:
 320                      throw new \InvalidArgumentException('$public needs to be an instance of EC\PublicKey or a string (an encoded coordinate)');
 321              }
 322          }
 323      }
 324  
 325      /**
 326       * Load the key
 327       *
 328       * @param string $key
 329       * @param string $password optional
 330       * @return AsymmetricKey
 331       */
 332      public static function load($key, $password = false)
 333      {
 334          try {
 335              return EC::load($key, $password);
 336          } catch (NoKeyLoadedException $e) {
 337          }
 338  
 339          return parent::load($key, $password);
 340      }
 341  
 342      /**
 343       * OnLoad Handler
 344       *
 345       * @return bool
 346       */
 347      protected static function onLoad(array $components)
 348      {
 349          if (!isset($components['privateKey']) && !isset($components['publicKey'])) {
 350              $new = new Parameters();
 351          } else {
 352              $new = isset($components['privateKey']) ?
 353                  new PrivateKey() :
 354                  new PublicKey();
 355          }
 356  
 357          $new->prime = $components['prime'];
 358          $new->base = $components['base'];
 359  
 360          if (isset($components['privateKey'])) {
 361              $new->privateKey = $components['privateKey'];
 362          }
 363          if (isset($components['publicKey'])) {
 364              $new->publicKey = $components['publicKey'];
 365          }
 366  
 367          return $new;
 368      }
 369  
 370      /**
 371       * Determines which hashing function should be used
 372       *
 373       * @param string $hash
 374       */
 375      public function withHash($hash)
 376      {
 377          throw new UnsupportedOperationException('DH does not use a hash algorithm');
 378      }
 379  
 380      /**
 381       * Returns the hash algorithm currently being used
 382       *
 383       */
 384      public function getHash()
 385      {
 386          throw new UnsupportedOperationException('DH does not use a hash algorithm');
 387      }
 388  
 389      /**
 390       * Returns the parameters
 391       *
 392       * A public / private key is only returned if the currently loaded "key" contains an x or y
 393       * value.
 394       *
 395       * @see self::getPublicKey()
 396       * @return mixed
 397       */
 398      public function getParameters()
 399      {
 400          $type = DH::validatePlugin('Keys', 'PKCS1', 'saveParameters');
 401  
 402          $key = $type::saveParameters($this->prime, $this->base);
 403          return DH::load($key, 'PKCS1');
 404      }
 405  }