Subversion Repositories oidplus

Rev

Rev 846 | Rev 1042 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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