1<?php 2 3/** 4 * OpenSSH Formatted RSA Key Handler 5 * 6 * PHP version 5 7 * 8 * Place in $HOME/.ssh/authorized_keys 9 * 10 * @category Crypt 11 * @package RSA 12 * @author Jim Wigginton <terrafrost@php.net> 13 * @copyright 2015 Jim Wigginton 14 * @license http://www.opensource.org/licenses/mit-license.html MIT License 15 * @link http://phpseclib.sourceforge.net 16 */ 17 18namespace phpseclib3\Crypt\RSA\Formats\Keys; 19 20use phpseclib3\Common\Functions\Strings; 21use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor; 22use phpseclib3\Math\BigInteger; 23 24/** 25 * OpenSSH Formatted RSA Key Handler 26 * 27 * @package RSA 28 * @author Jim Wigginton <terrafrost@php.net> 29 * @access public 30 */ 31abstract class OpenSSH extends Progenitor 32{ 33 /** 34 * Supported Key Types 35 * 36 * @var array 37 */ 38 protected static $types = ['ssh-rsa']; 39 40 /** 41 * Break a public or private key down into its constituent components 42 * 43 * @access public 44 * @param string $key 45 * @param string $password optional 46 * @return array 47 */ 48 public static function load($key, $password = '') 49 { 50 static $one; 51 if (!isset($one)) { 52 $one = new BigInteger(1); 53 } 54 55 $parsed = parent::load($key, $password); 56 57 if (isset($parsed['paddedKey'])) { 58 list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']); 59 if ($type != $parsed['type']) { 60 throw new \RuntimeException("The public and private keys are not of the same type ($type vs $parsed[type])"); 61 } 62 63 $primes = $coefficients = []; 64 65 list( 66 $modulus, 67 $publicExponent, 68 $privateExponent, 69 $coefficients[2], 70 $primes[1], 71 $primes[2], 72 $comment, 73 ) = Strings::unpackSSH2('i6s', $parsed['paddedKey']); 74 75 $temp = $primes[1]->subtract($one); 76 $exponents = [1 => $publicExponent->modInverse($temp)]; 77 $temp = $primes[2]->subtract($one); 78 $exponents[] = $publicExponent->modInverse($temp); 79 80 $isPublicKey = false; 81 82 return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey'); 83 } 84 85 list($publicExponent, $modulus) = Strings::unpackSSH2('ii', $parsed['publicKey']); 86 87 return [ 88 'isPublicKey' => true, 89 'modulus' => $modulus, 90 'publicExponent' => $publicExponent, 91 'comment' => $parsed['comment'] 92 ]; 93 } 94 95 /** 96 * Convert a public key to the appropriate format 97 * 98 * @access public 99 * @param \phpseclib3\Math\BigInteger $n 100 * @param \phpseclib3\Math\BigInteger $e 101 * @param array $options optional 102 * @return string 103 */ 104 public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) 105 { 106 $RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n); 107 108 if (isset($options['binary']) ? $options['binary'] : self::$binary) { 109 return $RSAPublicKey; 110 } 111 112 $comment = isset($options['comment']) ? $options['comment'] : self::$comment; 113 $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $comment; 114 115 return $RSAPublicKey; 116 } 117 118 /** 119 * Convert a private key to the appropriate format. 120 * 121 * @access public 122 * @param \phpseclib3\Math\BigInteger $n 123 * @param \phpseclib3\Math\BigInteger $e 124 * @param \phpseclib3\Math\BigInteger $d 125 * @param array $primes 126 * @param array $exponents 127 * @param array $coefficients 128 * @param string $password optional 129 * @param array $options optional 130 * @return string 131 */ 132 public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) 133 { 134 $publicKey = self::savePublicKey($n, $e, ['binary' => true]); 135 $privateKey = Strings::packSSH2('si6', 'ssh-rsa', $n, $e, $d, $coefficients[2], $primes[1], $primes[2]); 136 137 return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); 138 } 139} 140