[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4   * PuTTY Formatted EC Key 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\PuTTY as Progenitor;
  18  use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
  19  use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
  20  use phpseclib3\Math\BigInteger;
  21  
  22  /**
  23   * PuTTY Formatted EC Key Handler
  24   *
  25   * @author  Jim Wigginton <terrafrost@php.net>
  26   */
  27  abstract class PuTTY extends Progenitor
  28  {
  29      use Common;
  30  
  31      /**
  32       * Public Handler
  33       *
  34       * @var string
  35       */
  36      const PUBLIC_HANDLER = 'phpseclib3\Crypt\EC\Formats\Keys\OpenSSH';
  37  
  38      /**
  39       * Supported Key Types
  40       *
  41       * @var array
  42       */
  43      protected static $types = [
  44          'ecdsa-sha2-nistp256',
  45          'ecdsa-sha2-nistp384',
  46          'ecdsa-sha2-nistp521',
  47          'ssh-ed25519'
  48      ];
  49  
  50      /**
  51       * Break a public or private key down into its constituent components
  52       *
  53       * @param string $key
  54       * @param string $password optional
  55       * @return array
  56       */
  57      public static function load($key, $password = '')
  58      {
  59          $components = parent::load($key, $password);
  60          if (!isset($components['private'])) {
  61              return $components;
  62          }
  63  
  64          $private = $components['private'];
  65  
  66          $temp = Strings::base64_encode(Strings::packSSH2('s', $components['type']) . $components['public']);
  67          $components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']);
  68  
  69          if ($components['curve'] instanceof TwistedEdwardsCurve) {
  70              if (Strings::shift($private, 4) != "\0\0\0\x20") {
  71                  throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
  72              }
  73              $arr = $components['curve']->extractSecret($private);
  74              $components['dA'] = $arr['dA'];
  75              $components['secret'] = $arr['secret'];
  76          } else {
  77              list($components['dA']) = Strings::unpackSSH2('i', $private);
  78              $components['curve']->rangeCheck($components['dA']);
  79          }
  80  
  81          return $components;
  82      }
  83  
  84      /**
  85       * Convert a private key to the appropriate format.
  86       *
  87       * @param \phpseclib3\Math\BigInteger $privateKey
  88       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
  89       * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
  90       * @param string $secret optional
  91       * @param string $password optional
  92       * @param array $options optional
  93       * @return string
  94       */
  95      public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = false, array $options = [])
  96      {
  97          self::initialize_static_variables();
  98  
  99          $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
 100          $name = $public[0];
 101          $public = Strings::base64_decode($public[1]);
 102          list(, $length) = unpack('N', Strings::shift($public, 4));
 103          Strings::shift($public, $length);
 104  
 105          // PuTTY pads private keys with a null byte per the following:
 106          // https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926
 107          if (!$curve instanceof TwistedEdwardsCurve) {
 108              $private = $privateKey->toBytes();
 109              if (!(strlen($privateKey->toBits()) & 7)) {
 110                  $private = "\0$private";
 111              }
 112          }
 113  
 114          $private = $curve instanceof TwistedEdwardsCurve ?
 115              Strings::packSSH2('s', $secret) :
 116              Strings::packSSH2('s', $private);
 117  
 118          return self::wrapPrivateKey($public, $private, $name, $password, $options);
 119      }
 120  
 121      /**
 122       * Convert an EC public key to the appropriate format
 123       *
 124       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 125       * @param \phpseclib3\Math\Common\FiniteField[] $publicKey
 126       * @return string
 127       */
 128      public static function savePublicKey(BaseCurve $curve, array $publicKey)
 129      {
 130          $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
 131          $type = $public[0];
 132          $public = Strings::base64_decode($public[1]);
 133          list(, $length) = unpack('N', Strings::shift($public, 4));
 134          Strings::shift($public, $length);
 135  
 136          return self::wrapPublicKey($public, $type);
 137      }
 138  }