[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/ -> XML.php (source)

   1  <?php
   2  
   3  /**
   4   * XML Formatted RSA Key Handler
   5   *
   6   * More info:
   7   *
   8   * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
   9   * http://www.w3.org/TR/xkms2/#XKMS_2_0_Paragraph_269
  10   * http://en.wikipedia.org/wiki/XML_Signature
  11   * http://en.wikipedia.org/wiki/XKMS
  12   *
  13   * PHP version 5
  14   *
  15   * @author    Jim Wigginton <terrafrost@php.net>
  16   * @copyright 2015 Jim Wigginton
  17   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  18   * @link      http://phpseclib.sourceforge.net
  19   */
  20  
  21  namespace phpseclib3\Crypt\RSA\Formats\Keys;
  22  
  23  use phpseclib3\Common\Functions\Strings;
  24  use phpseclib3\Exception\BadConfigurationException;
  25  use phpseclib3\Exception\UnsupportedFormatException;
  26  use phpseclib3\Math\BigInteger;
  27  
  28  /**
  29   * XML Formatted RSA Key Handler
  30   *
  31   * @author  Jim Wigginton <terrafrost@php.net>
  32   */
  33  abstract class XML
  34  {
  35      /**
  36       * Break a public or private key down into its constituent components
  37       *
  38       * @param string $key
  39       * @param string $password optional
  40       * @return array
  41       */
  42      public static function load($key, $password = '')
  43      {
  44          if (!Strings::is_stringable($key)) {
  45              throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
  46          }
  47  
  48          if (!class_exists('DOMDocument')) {
  49              throw new BadConfigurationException('The dom extension is not setup correctly on this system');
  50          }
  51  
  52          $components = [
  53              'isPublicKey' => false,
  54              'primes' => [],
  55              'exponents' => [],
  56              'coefficients' => []
  57          ];
  58  
  59          $use_errors = libxml_use_internal_errors(true);
  60  
  61          $dom = new \DOMDocument();
  62          if (substr($key, 0, 5) != '<?xml') {
  63              $key = '<xml>' . $key . '</xml>';
  64          }
  65          if (!$dom->loadXML($key)) {
  66              libxml_use_internal_errors($use_errors);
  67              throw new \UnexpectedValueException('Key does not appear to contain XML');
  68          }
  69          $xpath = new \DOMXPath($dom);
  70          $keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'];
  71          foreach ($keys as $key) {
  72              // $dom->getElementsByTagName($key) is case-sensitive
  73              $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']");
  74              if (!$temp->length) {
  75                  continue;
  76              }
  77              $value = new BigInteger(Strings::base64_decode($temp->item(0)->nodeValue), 256);
  78              switch ($key) {
  79                  case 'modulus':
  80                      $components['modulus'] = $value;
  81                      break;
  82                  case 'exponent':
  83                      $components['publicExponent'] = $value;
  84                      break;
  85                  case 'p':
  86                      $components['primes'][1] = $value;
  87                      break;
  88                  case 'q':
  89                      $components['primes'][2] = $value;
  90                      break;
  91                  case 'dp':
  92                      $components['exponents'][1] = $value;
  93                      break;
  94                  case 'dq':
  95                      $components['exponents'][2] = $value;
  96                      break;
  97                  case 'inverseq':
  98                      $components['coefficients'][2] = $value;
  99                      break;
 100                  case 'd':
 101                      $components['privateExponent'] = $value;
 102              }
 103          }
 104  
 105          libxml_use_internal_errors($use_errors);
 106  
 107          foreach ($components as $key => $value) {
 108              if (is_array($value) && !count($value)) {
 109                  unset($components[$key]);
 110              }
 111          }
 112  
 113          if (isset($components['modulus']) && isset($components['publicExponent'])) {
 114              if (count($components) == 3) {
 115                  $components['isPublicKey'] = true;
 116              }
 117              return $components;
 118          }
 119  
 120          throw new \UnexpectedValueException('Modulus / exponent not present');
 121      }
 122  
 123      /**
 124       * Convert a private key to the appropriate format.
 125       *
 126       * @param \phpseclib3\Math\BigInteger $n
 127       * @param \phpseclib3\Math\BigInteger $e
 128       * @param \phpseclib3\Math\BigInteger $d
 129       * @param array $primes
 130       * @param array $exponents
 131       * @param array $coefficients
 132       * @param string $password optional
 133       * @return string
 134       */
 135      public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '')
 136      {
 137          if (count($primes) != 2) {
 138              throw new \InvalidArgumentException('XML does not support multi-prime RSA keys');
 139          }
 140  
 141          if (!empty($password) && is_string($password)) {
 142              throw new UnsupportedFormatException('XML private keys do not support encryption');
 143          }
 144  
 145          return "<RSAKeyPair>\r\n" .
 146                 '  <Modulus>' . Strings::base64_encode($n->toBytes()) . "</Modulus>\r\n" .
 147                 '  <Exponent>' . Strings::base64_encode($e->toBytes()) . "</Exponent>\r\n" .
 148                 '  <P>' . Strings::base64_encode($primes[1]->toBytes()) . "</P>\r\n" .
 149                 '  <Q>' . Strings::base64_encode($primes[2]->toBytes()) . "</Q>\r\n" .
 150                 '  <DP>' . Strings::base64_encode($exponents[1]->toBytes()) . "</DP>\r\n" .
 151                 '  <DQ>' . Strings::base64_encode($exponents[2]->toBytes()) . "</DQ>\r\n" .
 152                 '  <InverseQ>' . Strings::base64_encode($coefficients[2]->toBytes()) . "</InverseQ>\r\n" .
 153                 '  <D>' . Strings::base64_encode($d->toBytes()) . "</D>\r\n" .
 154                 '</RSAKeyPair>';
 155      }
 156  
 157      /**
 158       * Convert a public key to the appropriate format
 159       *
 160       * @param \phpseclib3\Math\BigInteger $n
 161       * @param \phpseclib3\Math\BigInteger $e
 162       * @return string
 163       */
 164      public static function savePublicKey(BigInteger $n, BigInteger $e)
 165      {
 166          return "<RSAKeyValue>\r\n" .
 167                 '  <Modulus>' . Strings::base64_encode($n->toBytes()) . "</Modulus>\r\n" .
 168                 '  <Exponent>' . Strings::base64_encode($e->toBytes()) . "</Exponent>\r\n" .
 169                 '</RSAKeyValue>';
 170      }
 171  }