PKCS8.php 4.4 KB

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