1<?php 2 3/** 4 * PKCS#1 Formatted DSA Key Handler 5 * 6 * PHP version 5 7 * 8 * Used by File/X509.php 9 * 10 * Processes keys with the following headers: 11 * 12 * -----BEGIN DSA PRIVATE KEY----- 13 * -----BEGIN DSA PUBLIC KEY----- 14 * -----BEGIN DSA PARAMETERS----- 15 * 16 * Analogous to ssh-keygen's pem format (as specified by -m) 17 * 18 * Also, technically, PKCS1 decribes RSA but I am not aware of a formal specification for DSA. 19 * The DSA private key format seems to have been adapted from the RSA private key format so 20 * we're just re-using that as the name. 21 * 22 * @category Crypt 23 * @package DSA 24 * @author Jim Wigginton <terrafrost@php.net> 25 * @copyright 2015 Jim Wigginton 26 * @license http://www.opensource.org/licenses/mit-license.html MIT License 27 * @link http://phpseclib.sourceforge.net 28 */ 29 30namespace phpseclib3\Crypt\DSA\Formats\Keys; 31 32use ParagonIE\ConstantTime\Base64; 33use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor; 34use phpseclib3\File\ASN1; 35use phpseclib3\File\ASN1\Maps; 36use phpseclib3\Math\BigInteger; 37 38/** 39 * PKCS#1 Formatted DSA Key Handler 40 * 41 * @package RSA 42 * @author Jim Wigginton <terrafrost@php.net> 43 * @access public 44 */ 45abstract class PKCS1 extends Progenitor 46{ 47 /** 48 * Break a public or private key down into its constituent components 49 * 50 * @access public 51 * @param string $key 52 * @param string $password optional 53 * @return array 54 */ 55 public static function load($key, $password = '') 56 { 57 $key = parent::load($key, $password); 58 59 $decoded = ASN1::decodeBER($key); 60 if (empty($decoded)) { 61 throw new \RuntimeException('Unable to decode BER'); 62 } 63 64 $key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); 65 if (is_array($key)) { 66 return $key; 67 } 68 69 $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP); 70 if (is_array($key)) { 71 return $key; 72 } 73 74 $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); 75 if (is_array($key)) { 76 return $key; 77 } 78 79 throw new \RuntimeException('Unable to perform ASN1 mapping'); 80 } 81 82 /** 83 * Convert DSA parameters to the appropriate format 84 * 85 * @access public 86 * @param \phpseclib3\Math\BigInteger $p 87 * @param \phpseclib3\Math\BigInteger $q 88 * @param \phpseclib3\Math\BigInteger $g 89 * @return string 90 */ 91 public static function saveParameters(BigInteger $p, BigInteger $q, BigInteger $g) 92 { 93 $key = [ 94 'p' => $p, 95 'q' => $q, 96 'g' => $g 97 ]; 98 99 $key = ASN1::encodeDER($key, Maps\DSAParams::MAP); 100 101 return "-----BEGIN DSA PARAMETERS-----\r\n" . 102 chunk_split(Base64::encode($key), 64) . 103 "-----END DSA PARAMETERS-----\r\n"; 104 } 105 106 /** 107 * Convert a private key to the appropriate format. 108 * 109 * @access public 110 * @param \phpseclib3\Math\BigInteger $p 111 * @param \phpseclib3\Math\BigInteger $q 112 * @param \phpseclib3\Math\BigInteger $g 113 * @param \phpseclib3\Math\BigInteger $y 114 * @param \phpseclib3\Math\BigInteger $x 115 * @param string $password optional 116 * @param array $options optional 117 * @return string 118 */ 119 public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = []) 120 { 121 $key = [ 122 'version' => 0, 123 'p' => $p, 124 'q' => $q, 125 'g' => $g, 126 'y' => $y, 127 'x' => $x 128 ]; 129 130 $key = ASN1::encodeDER($key, Maps\DSAPrivateKey::MAP); 131 132 return self::wrapPrivateKey($key, 'DSA', $password, $options); 133 } 134 135 /** 136 * Convert a public key to the appropriate format 137 * 138 * @access public 139 * @param \phpseclib3\Math\BigInteger $p 140 * @param \phpseclib3\Math\BigInteger $q 141 * @param \phpseclib3\Math\BigInteger $g 142 * @param \phpseclib3\Math\BigInteger $y 143 * @return string 144 */ 145 public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) 146 { 147 $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP); 148 149 return self::wrapPublicKey($key, 'DSA'); 150 } 151} 152