1<?php 2 3/** 4 * PuTTY Formatted DSA Key Handler 5 * 6 * puttygen does not generate DSA keys with an N of anything other than 160, however, 7 * it can still load them and convert them. PuTTY will load them, too, but SSH servers 8 * won't accept them. Since PuTTY formatted keys are primarily used with SSH this makes 9 * keys with N > 160 kinda useless, hence this handlers not supporting such keys. 10 * 11 * PHP version 5 12 * 13 * @category Crypt 14 * @package DSA 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 21namespace phpseclib3\Crypt\DSA\Formats\Keys; 22 23use phpseclib3\Common\Functions\Strings; 24use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor; 25use phpseclib3\Math\BigInteger; 26 27/** 28 * PuTTY Formatted DSA Key Handler 29 * 30 * @package DSA 31 * @author Jim Wigginton <terrafrost@php.net> 32 * @access public 33 */ 34abstract class PuTTY extends Progenitor 35{ 36 /** 37 * Public Handler 38 * 39 * @var string 40 * @access private 41 */ 42 const PUBLIC_HANDLER = 'phpseclib3\Crypt\DSA\Formats\Keys\OpenSSH'; 43 44 /** 45 * Algorithm Identifier 46 * 47 * @var array 48 * @access private 49 */ 50 protected static $types = ['ssh-dss']; 51 52 /** 53 * Break a public or private key down into its constituent components 54 * 55 * @access public 56 * @param string $key 57 * @param string $password optional 58 * @return array 59 */ 60 public static function load($key, $password = '') 61 { 62 $components = parent::load($key, $password); 63 if (!isset($components['private'])) { 64 return $components; 65 } 66 extract($components); 67 unset($components['public'], $components['private']); 68 69 list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public); 70 list($x) = Strings::unpackSSH2('i', $private); 71 72 return compact('p', 'q', 'g', 'y', 'x', 'comment'); 73 } 74 75 /** 76 * Convert a private key to the appropriate format. 77 * 78 * @access public 79 * @param \phpseclib3\Math\BigInteger $p 80 * @param \phpseclib3\Math\BigInteger $q 81 * @param \phpseclib3\Math\BigInteger $g 82 * @param \phpseclib3\Math\BigInteger $y 83 * @param \phpseclib3\Math\BigInteger $x 84 * @param string $password optional 85 * @param array $options optional 86 * @return string 87 */ 88 public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = false, array $options = []) 89 { 90 if ($q->getLength() != 160) { 91 throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); 92 } 93 94 $public = Strings::packSSH2('iiii', $p, $q, $g, $y); 95 $private = Strings::packSSH2('i', $x); 96 97 return self::wrapPrivateKey($public, $private, 'ssh-dsa', $password, $options); 98 } 99 100 /** 101 * Convert a public key to the appropriate format 102 * 103 * @access public 104 * @param \phpseclib3\Math\BigInteger $p 105 * @param \phpseclib3\Math\BigInteger $q 106 * @param \phpseclib3\Math\BigInteger $g 107 * @param \phpseclib3\Math\BigInteger $y 108 * @return string 109 */ 110 public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) 111 { 112 if ($q->getLength() != 160) { 113 throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); 114 } 115 116 return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y), 'ssh-dsa'); 117 } 118} 119