[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/Crypt/ -> DSA.php (source)

   1  <?php
   2  
   3  /**
   4   * Pure-PHP FIPS 186-4 compliant implementation of DSA.
   5   *
   6   * PHP version 5
   7   *
   8   * Here's an example of how to create signatures and verify signatures with this library:
   9   * <code>
  10   * <?php
  11   * include 'vendor/autoload.php';
  12   *
  13   * $private = \phpseclib3\Crypt\DSA::createKey();
  14   * $public = $private->getPublicKey();
  15   *
  16   * $plaintext = 'terrafrost';
  17   *
  18   * $signature = $private->sign($plaintext);
  19   *
  20   * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
  21   * ?>
  22   * </code>
  23   *
  24   * @category  Crypt
  25   * @package   DSA
  26   * @author    Jim Wigginton <[email protected]>
  27   * @copyright 2016 Jim Wigginton
  28   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  29   * @link      http://phpseclib.sourceforge.net
  30   */
  31  
  32  namespace phpseclib3\Crypt;
  33  
  34  use phpseclib3\Crypt\Common\AsymmetricKey;
  35  use phpseclib3\Crypt\DSA\Parameters;
  36  use phpseclib3\Crypt\DSA\PrivateKey;
  37  use phpseclib3\Crypt\DSA\PublicKey;
  38  use phpseclib3\Exception\InsufficientSetupException;
  39  use phpseclib3\Math\BigInteger;
  40  
  41  /**
  42   * Pure-PHP FIPS 186-4 compliant implementation of DSA.
  43   *
  44   * @package DSA
  45   * @author  Jim Wigginton <[email protected]>
  46   * @access  public
  47   */
  48  abstract class DSA extends AsymmetricKey
  49  {
  50      /**
  51       * Algorithm Name
  52       *
  53       * @var string
  54       * @access private
  55       */
  56      const ALGORITHM = 'DSA';
  57  
  58      /**
  59       * DSA Prime P
  60       *
  61       * @var \phpseclib3\Math\BigInteger
  62       * @access private
  63       */
  64      protected $p;
  65  
  66      /**
  67       * DSA Group Order q
  68       *
  69       * Prime divisor of p-1
  70       *
  71       * @var \phpseclib3\Math\BigInteger
  72       * @access private
  73       */
  74      protected $q;
  75  
  76      /**
  77       * DSA Group Generator G
  78       *
  79       * @var \phpseclib3\Math\BigInteger
  80       * @access private
  81       */
  82      protected $g;
  83  
  84      /**
  85       * DSA public key value y
  86       *
  87       * @var \phpseclib3\Math\BigInteger
  88       * @access private
  89       */
  90      protected $y;
  91  
  92      /**
  93       * Signature Format
  94       *
  95       * @var string
  96       * @access private
  97       */
  98      protected $sigFormat;
  99  
 100      /**
 101       * Signature Format (Short)
 102       *
 103       * @var string
 104       * @access private
 105       */
 106      protected $shortFormat;
 107  
 108      /**
 109       * Create DSA parameters
 110       *
 111       * @access public
 112       * @param int $L
 113       * @param int $N
 114       * @return \phpseclib3\Crypt\DSA|bool
 115       */
 116      public static function createParameters($L = 2048, $N = 224)
 117      {
 118          self::initialize_static_variables();
 119  
 120          if (!isset(self::$engines['PHP'])) {
 121              self::useBestEngine();
 122          }
 123  
 124          switch (true) {
 125              case $N == 160:
 126              /*
 127                in FIPS 186-1 and 186-2 N was fixed at 160 whereas K had an upper bound of 1024.
 128                RFC 4253 (SSH Transport Layer Protocol) references FIPS 186-2 and as such most
 129                SSH DSA implementations only support keys with an N of 160.
 130                puttygen let's you set the size of L (but not the size of N) and uses 2048 as the
 131                default L value. that's not really compliant with any of the FIPS standards, however,
 132                for the purposes of maintaining compatibility with puttygen, we'll support it
 133              */
 134              //case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160:
 135              // FIPS 186-3 changed this as follows:
 136              //case $L == 1024 && $N == 160:
 137              case $L == 2048 && $N == 224:
 138              case $L == 2048 && $N == 256:
 139              case $L == 3072 && $N == 256:
 140                  break;
 141              default:
 142                  throw new \InvalidArgumentException('Invalid values for N and L');
 143          }
 144  
 145          $two = new BigInteger(2);
 146  
 147          $q = BigInteger::randomPrime($N);
 148          $divisor = $q->multiply($two);
 149  
 150          do {
 151              $x = BigInteger::random($L);
 152              list(, $c) = $x->divide($divisor);
 153              $p = $x->subtract($c->subtract(self::$one));
 154          } while ($p->getLength() != $L || !$p->isPrime());
 155  
 156          $p_1 = $p->subtract(self::$one);
 157          list($e) = $p_1->divide($q);
 158  
 159          // quoting http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=50 ,
 160          // "h could be obtained from a random number generator or from a counter that
 161          //  changes after each use". PuTTY (sshdssg.c) starts h off at 1 and increments
 162          // it on each loop. wikipedia says "commonly h = 2 is used" so we'll just do that
 163          $h = clone $two;
 164          while (true) {
 165              $g = $h->powMod($e, $p);
 166              if (!$g->equals(self::$one)) {
 167                  break;
 168              }
 169              $h = $h->add(self::$one);
 170          }
 171  
 172          $dsa = new Parameters();
 173          $dsa->p = $p;
 174          $dsa->q = $q;
 175          $dsa->g = $g;
 176  
 177          return $dsa;
 178      }
 179  
 180      /**
 181       * Create public / private key pair.
 182       *
 183       * This method is a bit polymorphic. It can take a DSA/Parameters object, L / N as two distinct parameters or
 184       * no parameters (at which point L and N will be generated with this method)
 185       *
 186       * Returns the private key, from which the publickey can be extracted
 187       *
 188       * @param int[] ...$args
 189       * @access public
 190       * @return DSA\PrivateKey
 191       */
 192      public static function createKey(...$args)
 193      {
 194          self::initialize_static_variables();
 195  
 196          if (!isset(self::$engines['PHP'])) {
 197              self::useBestEngine();
 198          }
 199  
 200          if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
 201              $params = self::createParameters($args[0], $args[1]);
 202          } elseif (count($args) == 1 && $args[0] instanceof Parameters) {
 203              $params = $args[0];
 204          } elseif (!count($args)) {
 205              $params = self::createParameters();
 206          } else {
 207              throw new InsufficientSetupException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.');
 208          }
 209  
 210          $private = new PrivateKey();
 211          $private->p = $params->p;
 212          $private->q = $params->q;
 213          $private->g = $params->g;
 214  
 215          $private->x = BigInteger::randomRange(self::$one, $private->q->subtract(self::$one));
 216          $private->y = $private->g->powMod($private->x, $private->p);
 217  
 218          //$public = clone $private;
 219          //unset($public->x);
 220  
 221          return $private
 222              ->withHash($params->hash->getHash())
 223              ->withSignatureFormat($params->shortFormat);
 224      }
 225  
 226      /**
 227       * OnLoad Handler
 228       *
 229       * @return bool
 230       * @access protected
 231       * @param array $components
 232       */
 233      protected static function onLoad($components)
 234      {
 235          if (!isset(self::$engines['PHP'])) {
 236              self::useBestEngine();
 237          }
 238  
 239          if (!isset($components['x']) && !isset($components['y'])) {
 240              $new = new Parameters();
 241          } elseif (isset($components['x'])) {
 242              $new = new PrivateKey();
 243              $new->x = $components['x'];
 244          } else {
 245              $new = new PublicKey();
 246          }
 247  
 248          $new->p = $components['p'];
 249          $new->q = $components['q'];
 250          $new->g = $components['g'];
 251  
 252          if (isset($components['y'])) {
 253              $new->y = $components['y'];
 254          }
 255  
 256          return $new;
 257      }
 258  
 259      /**
 260       * Constructor
 261       *
 262       * PublicKey and PrivateKey objects can only be created from abstract RSA class
 263       */
 264      protected function __construct()
 265      {
 266          $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
 267          $this->shortFormat = 'ASN1';
 268  
 269          parent::__construct();
 270      }
 271  
 272      /**
 273       * Returns the key size
 274       *
 275       * More specifically, this L (the length of DSA Prime P) and N (the length of DSA Group Order q)
 276       *
 277       * @access public
 278       * @return array
 279       */
 280      public function getLength()
 281      {
 282          return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()];
 283      }
 284  
 285      /**
 286       * Returns the current engine being used
 287       *
 288       * @see self::useInternalEngine()
 289       * @see self::useBestEngine()
 290       * @access public
 291       * @return string
 292       */
 293      public function getEngine()
 294      {
 295          if (!isset(self::$engines['PHP'])) {
 296              self::useBestEngine();
 297          }
 298          return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ?
 299              'OpenSSL' : 'PHP';
 300      }
 301  
 302      /**
 303       * Returns the parameters
 304       *
 305       * A public / private key is only returned if the currently loaded "key" contains an x or y
 306       * value.
 307       *
 308       * @see self::getPublicKey()
 309       * @access public
 310       * @return mixed
 311       */
 312      public function getParameters()
 313      {
 314          $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
 315  
 316          $key = $type::saveParameters($this->p, $this->q, $this->g);
 317          return DSA::load($key, 'PKCS1')
 318              ->withHash($this->hash->getHash())
 319              ->withSignatureFormat($this->shortFormat);
 320      }
 321  
 322      /**
 323       * Determines the signature padding mode
 324       *
 325       * Valid values are: ASN1, SSH2, Raw
 326       *
 327       * @access public
 328       * @param string $format
 329       */
 330      public function withSignatureFormat($format)
 331      {
 332          $new = clone $this;
 333          $new->shortFormat = $format;
 334          $new->sigFormat = self::validatePlugin('Signature', $format);
 335          return $new;
 336      }
 337  
 338      /**
 339       * Returns the signature format currently being used
 340       *
 341       * @access public
 342       */
 343      public function getSignatureFormat()
 344      {
 345          return $this->shortFormat;
 346      }
 347  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer