PuTTY.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. /**
  3. * PuTTY Formatted RSA Key Handler
  4. *
  5. * PHP version 5
  6. *
  7. * @category Crypt
  8. * @package RSA
  9. * @author Jim Wigginton <terrafrost@php.net>
  10. * @copyright 2015 Jim Wigginton
  11. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  12. * @link http://phpseclib.sourceforge.net
  13. */
  14. namespace phpseclib\Crypt\RSA\Keys;
  15. use phpseclib\Math\BigInteger;
  16. use phpseclib\Common\Functions\Strings;
  17. use phpseclib\Crypt\Common\Keys\PuTTY as Progenitor;
  18. /**
  19. * PuTTY Formatted RSA Key Handler
  20. *
  21. * @package RSA
  22. * @author Jim Wigginton <terrafrost@php.net>
  23. * @access public
  24. */
  25. abstract class PuTTY extends Progenitor
  26. {
  27. /**
  28. * Public Handler
  29. *
  30. * @var string
  31. * @access private
  32. */
  33. const PUBLIC_HANDLER = 'phpseclib\Crypt\RSA\Keys\OpenSSH';
  34. /**
  35. * Algorithm Identifier
  36. *
  37. * @var string
  38. * @access private
  39. */
  40. const TYPE = 'ssh-rsa';
  41. /**
  42. * Break a public or private key down into its constituent components
  43. *
  44. * @access public
  45. * @param string $key
  46. * @param string $password optional
  47. * @return array
  48. */
  49. public static function load($key, $password = '')
  50. {
  51. static $one;
  52. if (!isset($one)) {
  53. $one = new BigInteger(1);
  54. }
  55. $components = parent::load($key, $password);
  56. if ($components === false || !isset($components['private'])) {
  57. return $components;
  58. }
  59. extract($components);
  60. unset($components['public'], $components['private']);
  61. $isPublicKey = false;
  62. $result = Strings::unpackSSH2('ii', $public);
  63. if ($result === false) {
  64. return false;
  65. }
  66. list($publicExponent, $modulus) = $result;
  67. $result = Strings::unpackSSH2('iiii', $private);
  68. if ($result === false) {
  69. return false;
  70. }
  71. $primes = $coefficients = [];
  72. list($privateExponent, $primes[1], $primes[2], $coefficients[2]) = $result;
  73. $temp = $primes[1]->subtract($one);
  74. $exponents = [1 => $publicExponent->modInverse($temp)];
  75. $temp = $primes[2]->subtract($one);
  76. $exponents[] = $publicExponent->modInverse($temp);
  77. return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
  78. }
  79. /**
  80. * Convert a private key to the appropriate format.
  81. *
  82. * @access public
  83. * @param \phpseclib\Math\BigInteger $n
  84. * @param \phpseclib\Math\BigInteger $e
  85. * @param \phpseclib\Math\BigInteger $d
  86. * @param array $primes
  87. * @param array $exponents
  88. * @param array $coefficients
  89. * @param string $password optional
  90. * @return string
  91. */
  92. public static function savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients, $password = '')
  93. {
  94. if (count($primes) != 2) {
  95. throw new \InvalidArgumentException('PuTTY does not support multi-prime RSA keys');
  96. }
  97. $public = Strings::packSSH2('ii', $e, $n);
  98. $private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]);
  99. return self::wrapPrivateKey($public, $private, $password);
  100. }
  101. /**
  102. * Convert a public key to the appropriate format
  103. *
  104. * @access public
  105. * @param \phpseclib\Math\BigInteger $n
  106. * @param \phpseclib\Math\BigInteger $e
  107. * @return string
  108. */
  109. public static function savePublicKey($n, $e)
  110. {
  111. return self::wrapPublicKey(Strings::packSSH2($e, $n));
  112. }
  113. }