1<?php 2 3/** 4 * PKCS#8 Formatted RSA Key Handler 5 * 6 * PHP version 5 7 * 8 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set) 9 * 10 * Processes keys with the following headers: 11 * 12 * -----BEGIN ENCRYPTED PRIVATE KEY----- 13 * -----BEGIN PRIVATE KEY----- 14 * -----BEGIN PUBLIC KEY----- 15 * 16 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8 17 * is specific to private keys it's basically creating a DER-encoded wrapper 18 * for keys. This just extends that same concept to public keys (much like ssh-keygen) 19 * 20 * @category Crypt 21 * @package RSA 22 * @author Jim Wigginton <terrafrost@php.net> 23 * @copyright 2015 Jim Wigginton 24 * @license http://www.opensource.org/licenses/mit-license.html MIT License 25 * @link http://phpseclib.sourceforge.net 26 */ 27 28namespace phpseclib3\Crypt\RSA\Formats\Keys; 29 30use phpseclib3\Common\Functions\Strings; 31use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; 32use phpseclib3\File\ASN1; 33use phpseclib3\Math\BigInteger; 34 35/** 36 * PKCS#8 Formatted RSA Key Handler 37 * 38 * @package RSA 39 * @author Jim Wigginton <terrafrost@php.net> 40 * @access public 41 */ 42abstract class PKCS8 extends Progenitor 43{ 44 /** 45 * OID Name 46 * 47 * @var string 48 * @access private 49 */ 50 const OID_NAME = 'rsaEncryption'; 51 52 /** 53 * OID Value 54 * 55 * @var string 56 * @access private 57 */ 58 const OID_VALUE = '1.2.840.113549.1.1.1'; 59 60 /** 61 * Child OIDs loaded 62 * 63 * @var bool 64 * @access private 65 */ 66 protected static $childOIDsLoaded = false; 67 68 /** 69 * Break a public or private key down into its constituent components 70 * 71 * @access public 72 * @param string $key 73 * @param string $password optional 74 * @return array 75 */ 76 public static function load($key, $password = '') 77 { 78 if (!Strings::is_stringable($key)) { 79 throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); 80 } 81 82 if (strpos($key, 'PUBLIC') !== false) { 83 $components = ['isPublicKey' => true]; 84 } elseif (strpos($key, 'PRIVATE') !== false) { 85 $components = ['isPublicKey' => false]; 86 } else { 87 $components = []; 88 } 89 90 $key = parent::load($key, $password); 91 92 if (isset($key['privateKey'])) { 93 if (!isset($components['isPublicKey'])) { 94 $components['isPublicKey'] = false; 95 } 96 $type = 'private'; 97 } else { 98 if (!isset($components['isPublicKey'])) { 99 $components['isPublicKey'] = true; 100 } 101 $type = 'public'; 102 } 103 104 $result = $components + PKCS1::load($key[$type . 'Key']); 105 106 if (isset($key['meta'])) { 107 $result['meta'] = $key['meta']; 108 } 109 110 return $result; 111 } 112 113 /** 114 * Convert a private key to the appropriate format. 115 * 116 * @access public 117 * @param \phpseclib3\Math\BigInteger $n 118 * @param \phpseclib3\Math\BigInteger $e 119 * @param \phpseclib3\Math\BigInteger $d 120 * @param array $primes 121 * @param array $exponents 122 * @param array $coefficients 123 * @param string $password optional 124 * @param array $options optional 125 * @return string 126 */ 127 public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) 128 { 129 $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients); 130 $key = ASN1::extractBER($key); 131 return self::wrapPrivateKey($key, [], null, $password, null, '', $options); 132 } 133 134 /** 135 * Convert a public key to the appropriate format 136 * 137 * @access public 138 * @param \phpseclib3\Math\BigInteger $n 139 * @param \phpseclib3\Math\BigInteger $e 140 * @param array $options optional 141 * @return string 142 */ 143 public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) 144 { 145 $key = PKCS1::savePublicKey($n, $e); 146 $key = ASN1::extractBER($key); 147 return self::wrapPublicKey($key, null); 148 } 149} 150