[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/ -> JWK.php (source)

   1  <?php
   2  
   3  /**
   4   * JSON Web Key (RFC7517 / RFC8037) Formatted EC Handler
   5   *
   6   * PHP version 5
   7   *
   8   * @author    Jim Wigginton <terrafrost@php.net>
   9   * @copyright 2015 Jim Wigginton
  10   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  11   * @link      http://phpseclib.sourceforge.net
  12   */
  13  
  14  namespace phpseclib3\Crypt\EC\Formats\Keys;
  15  
  16  use phpseclib3\Common\Functions\Strings;
  17  use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor;
  18  use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
  19  use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
  20  use phpseclib3\Crypt\EC\Curves\Ed25519;
  21  use phpseclib3\Crypt\EC\Curves\secp256k1;
  22  use phpseclib3\Crypt\EC\Curves\secp256r1;
  23  use phpseclib3\Crypt\EC\Curves\secp384r1;
  24  use phpseclib3\Crypt\EC\Curves\secp521r1;
  25  use phpseclib3\Exception\UnsupportedCurveException;
  26  use phpseclib3\Math\BigInteger;
  27  
  28  /**
  29   * JWK Formatted EC Handler
  30   *
  31   * @author  Jim Wigginton <terrafrost@php.net>
  32   */
  33  abstract class JWK extends Progenitor
  34  {
  35      use Common;
  36  
  37      /**
  38       * Break a public or private key down into its constituent components
  39       *
  40       * @param string $key
  41       * @param string $password optional
  42       * @return array
  43       */
  44      public static function load($key, $password = '')
  45      {
  46          $key = parent::load($key, $password);
  47  
  48          switch ($key->kty) {
  49              case 'EC':
  50                  switch ($key->crv) {
  51                      case 'P-256':
  52                      case 'P-384':
  53                      case 'P-521':
  54                      case 'secp256k1':
  55                          break;
  56                      default:
  57                          throw new UnsupportedCurveException('Only P-256, P-384, P-521 and secp256k1 curves are accepted (' . $key->crv . ' provided)');
  58                  }
  59                  break;
  60              case 'OKP':
  61                  switch ($key->crv) {
  62                      case 'Ed25519':
  63                      case 'Ed448':
  64                          break;
  65                      default:
  66                          throw new UnsupportedCurveException('Only Ed25519 and Ed448 curves are accepted (' . $key->crv . ' provided)');
  67                  }
  68                  break;
  69              default:
  70                  throw new \Exception('Only EC and OKP JWK keys are supported');
  71          }
  72  
  73          $curve = '\phpseclib3\Crypt\EC\Curves\\' . str_replace('P-', 'nistp', $key->crv);
  74          $curve = new $curve();
  75  
  76          if ($curve instanceof TwistedEdwardsCurve) {
  77              $QA = self::extractPoint(Strings::base64url_decode($key->x), $curve);
  78              if (!isset($key->d)) {
  79                  return compact('curve', 'QA');
  80              }
  81              $arr = $curve->extractSecret(Strings::base64url_decode($key->d));
  82              return compact('curve', 'QA') + $arr;
  83          }
  84  
  85          $QA = [
  86              $curve->convertInteger(new BigInteger(Strings::base64url_decode($key->x), 256)),
  87              $curve->convertInteger(new BigInteger(Strings::base64url_decode($key->y), 256))
  88          ];
  89  
  90          if (!$curve->verifyPoint($QA)) {
  91              throw new \RuntimeException('Unable to verify that point exists on curve');
  92          }
  93  
  94          if (!isset($key->d)) {
  95              return compact('curve', 'QA');
  96          }
  97  
  98          $dA = new BigInteger(Strings::base64url_decode($key->d), 256);
  99  
 100          $curve->rangeCheck($dA);
 101  
 102          return compact('curve', 'dA', 'QA');
 103      }
 104  
 105      /**
 106       * Returns the alias that corresponds to a curve
 107       *
 108       * @return string
 109       */
 110      private static function getAlias(BaseCurve $curve)
 111      {
 112          switch (true) {
 113              case $curve instanceof secp256r1:
 114                  return 'P-256';
 115              case $curve instanceof secp384r1:
 116                  return 'P-384';
 117              case $curve instanceof secp521r1:
 118                  return 'P-521';
 119              case $curve instanceof secp256k1:
 120                  return 'secp256k1';
 121          }
 122  
 123          $reflect = new \ReflectionClass($curve);
 124          $curveName = $reflect->isFinal() ?
 125              $reflect->getParentClass()->getShortName() :
 126              $reflect->getShortName();
 127          throw new UnsupportedCurveException("$curveName is not a supported curve");
 128      }
 129  
 130      /**
 131       * Return the array superstructure for an EC public key
 132       *
 133       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 134       * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
 135       * @return array
 136       */
 137      private static function savePublicKeyHelper(BaseCurve $curve, array $publicKey)
 138      {
 139          if ($curve instanceof TwistedEdwardsCurve) {
 140              return [
 141                  'kty' => 'OKP',
 142                  'crv' => $curve instanceof Ed25519 ? 'Ed25519' : 'Ed448',
 143                  'x' => Strings::base64url_encode($curve->encodePoint($publicKey))
 144              ];
 145          }
 146  
 147          return [
 148              'kty' => 'EC',
 149              'crv' => self::getAlias($curve),
 150              'x' => Strings::base64url_encode($publicKey[0]->toBytes()),
 151              'y' => Strings::base64url_encode($publicKey[1]->toBytes())
 152          ];
 153      }
 154  
 155      /**
 156       * Convert an EC public key to the appropriate format
 157       *
 158       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 159       * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
 160       * @param array $options optional
 161       * @return string
 162       */
 163      public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
 164      {
 165          $key = self::savePublicKeyHelper($curve, $publicKey);
 166  
 167          return self::wrapKey($key, $options);
 168      }
 169  
 170      /**
 171       * Convert a private key to the appropriate format.
 172       *
 173       * @param \phpseclib3\Math\BigInteger $privateKey
 174       * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
 175       * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
 176       * @param string $secret optional
 177       * @param string $password optional
 178       * @param array $options optional
 179       * @return string
 180       */
 181      public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = '', array $options = [])
 182      {
 183          $key = self::savePublicKeyHelper($curve, $publicKey);
 184          $key['d'] = $curve instanceof TwistedEdwardsCurve ? $secret : $privateKey->toBytes();
 185          $key['d'] = Strings::base64url_encode($key['d']);
 186  
 187          return self::wrapKey($key, $options);
 188      }
 189  }