XML.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <?php
  2. /**
  3. * XML Formatted RSA Key Handler
  4. *
  5. * More info:
  6. *
  7. * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
  8. * http://en.wikipedia.org/wiki/XML_Signature
  9. *
  10. * PHP version 5
  11. *
  12. * @category Crypt
  13. * @package RSA
  14. * @author Jim Wigginton <terrafrost@php.net>
  15. * @copyright 2015 Jim Wigginton
  16. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  17. * @link http://phpseclib.sourceforge.net
  18. */
  19. namespace phpseclib\Crypt\RSA;
  20. use ParagonIE\ConstantTime\Base64;
  21. use phpseclib\Math\BigInteger;
  22. /**
  23. * XML Formatted RSA Key Handler
  24. *
  25. * @package RSA
  26. * @author Jim Wigginton <terrafrost@php.net>
  27. * @access public
  28. */
  29. class XML
  30. {
  31. /**
  32. * Break a public or private key down into its constituent components
  33. *
  34. * @access public
  35. * @param string $key
  36. * @param string $password optional
  37. * @return array
  38. */
  39. static function load($key, $password = '')
  40. {
  41. if (!is_string($key)) {
  42. return false;
  43. }
  44. $components = array(
  45. 'isPublicKey' => false,
  46. 'primes' => array(),
  47. 'exponents' => array(),
  48. 'coefficients' => array()
  49. );
  50. $use_errors = libxml_use_internal_errors(true);
  51. $dom = new \DOMDocument();
  52. if (!$dom->loadXML('<xml>' . $key . '</xml>')) {
  53. return false;
  54. }
  55. $xpath = new \DOMXPath($dom);
  56. $keys = array('modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd');
  57. foreach ($keys as $key) {
  58. // $dom->getElementsByTagName($key) is case-sensitive
  59. $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']");
  60. if (!$temp->length) {
  61. continue;
  62. }
  63. $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
  64. switch ($key) {
  65. case 'modulus':
  66. $components['modulus'] = $value;
  67. break;
  68. case 'exponent':
  69. $components['publicExponent'] = $value;
  70. break;
  71. case 'p':
  72. $components['primes'][1] = $value;
  73. break;
  74. case 'q':
  75. $components['primes'][2] = $value;
  76. break;
  77. case 'dp':
  78. $components['exponents'][1] = $value;
  79. break;
  80. case 'dq':
  81. $components['exponents'][2] = $value;
  82. break;
  83. case 'inverseq':
  84. $components['coefficients'][2] = $value;
  85. break;
  86. case 'd':
  87. $components['privateExponent'] = $value;
  88. }
  89. }
  90. libxml_use_internal_errors($use_errors);
  91. return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
  92. }
  93. /**
  94. * Convert a private key to the appropriate format.
  95. *
  96. * @access public
  97. * @param \phpseclib\Math\BigInteger $n
  98. * @param \phpseclib\Math\BigInteger $e
  99. * @param \phpseclib\Math\BigInteger $d
  100. * @param array $primes
  101. * @param array $exponents
  102. * @param array $coefficients
  103. * @param string $password optional
  104. * @return string
  105. */
  106. static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
  107. {
  108. if (count($primes) != 2) {
  109. return false;
  110. }
  111. return "<RSAKeyValue>\r\n" .
  112. ' <Modulus>' . Base64::encode($n->toBytes()) . "</Modulus>\r\n" .
  113. ' <Exponent>' . Base64::encode($e->toBytes()) . "</Exponent>\r\n" .
  114. ' <P>' . Base64::encode($primes[1]->toBytes()) . "</P>\r\n" .
  115. ' <Q>' . Base64::encode($primes[2]->toBytes()) . "</Q>\r\n" .
  116. ' <DP>' . Base64::encode($exponents[1]->toBytes()) . "</DP>\r\n" .
  117. ' <DQ>' . Base64::encode($exponents[2]->toBytes()) . "</DQ>\r\n" .
  118. ' <InverseQ>' . Base64::encode($coefficients[2]->toBytes()) . "</InverseQ>\r\n" .
  119. ' <D>' . Base64::encode($d->toBytes()) . "</D>\r\n" .
  120. '</RSAKeyValue>';
  121. }
  122. /**
  123. * Convert a public key to the appropriate format
  124. *
  125. * @access public
  126. * @param \phpseclib\Math\BigInteger $n
  127. * @param \phpseclib\Math\BigInteger $e
  128. * @return string
  129. */
  130. static function savePublicKey(BigInteger $n, BigInteger $e)
  131. {
  132. return "<RSAKeyValue>\r\n" .
  133. ' <Modulus>' . Base64::encode($n->toBytes()) . "</Modulus>\r\n" .
  134. ' <Exponent>' . Base64::encode($e->toBytes()) . "</Exponent>\r\n" .
  135. '</RSAKeyValue>';
  136. }
  137. }