Subversion Repositories oidplus

Rev

Rev 846 | 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
 * PuTTY Formatted EC Key Handler
5
 *
6
 * PHP version 5
7
 *
874 daniel-mar 8
 * @category  Crypt
9
 * @package   EC
827 daniel-mar 10
 * @author    Jim Wigginton <terrafrost@php.net>
11
 * @copyright 2015 Jim Wigginton
12
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
13
 * @link      http://phpseclib.sourceforge.net
14
 */
15
 
16
namespace phpseclib3\Crypt\EC\Formats\Keys;
17
 
18
use ParagonIE\ConstantTime\Base64;
19
use phpseclib3\Common\Functions\Strings;
20
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
21
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
22
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
23
use phpseclib3\Math\BigInteger;
24
 
25
/**
26
 * PuTTY Formatted EC Key Handler
27
 *
874 daniel-mar 28
 * @package EC
827 daniel-mar 29
 * @author  Jim Wigginton <terrafrost@php.net>
874 daniel-mar 30
 * @access  public
827 daniel-mar 31
 */
32
abstract class PuTTY extends Progenitor
33
{
34
    use Common;
35
 
36
    /**
37
     * Public Handler
38
     *
39
     * @var string
874 daniel-mar 40
     * @access private
827 daniel-mar 41
     */
42
    const PUBLIC_HANDLER = 'phpseclib3\Crypt\EC\Formats\Keys\OpenSSH';
43
 
44
    /**
45
     * Supported Key Types
46
     *
47
     * @var array
874 daniel-mar 48
     * @access private
827 daniel-mar 49
     */
50
    protected static $types = [
51
        'ecdsa-sha2-nistp256',
52
        'ecdsa-sha2-nistp384',
53
        'ecdsa-sha2-nistp521',
54
        'ssh-ed25519'
55
    ];
56
 
57
    /**
58
     * Break a public or private key down into its constituent components
59
     *
874 daniel-mar 60
     * @access public
827 daniel-mar 61
     * @param string $key
62
     * @param string $password optional
63
     * @return array
64
     */
65
    public static function load($key, $password = '')
66
    {
67
        $components = parent::load($key, $password);
68
        if (!isset($components['private'])) {
69
            return $components;
70
        }
71
 
72
        $private = $components['private'];
73
 
74
        $temp = Base64::encode(Strings::packSSH2('s', $components['type']) . $components['public']);
75
        $components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']);
76
 
77
        if ($components['curve'] instanceof TwistedEdwardsCurve) {
78
            if (Strings::shift($private, 4) != "\0\0\0\x20") {
79
                throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
80
            }
81
            $components['dA'] = $components['curve']->extractSecret($private);
82
        } else {
83
            list($components['dA']) = Strings::unpackSSH2('i', $private);
84
            $components['curve']->rangeCheck($components['dA']);
85
        }
86
 
87
        return $components;
88
    }
89
 
90
    /**
91
     * Convert a private key to the appropriate format.
92
     *
874 daniel-mar 93
     * @access public
827 daniel-mar 94
     * @param \phpseclib3\Math\BigInteger $privateKey
95
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
96
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
97
     * @param string $password optional
98
     * @param array $options optional
99
     * @return string
100
     */
101
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = false, array $options = [])
102
    {
103
        self::initialize_static_variables();
104
 
105
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
106
        $name = $public[0];
107
        $public = Base64::decode($public[1]);
108
        list(, $length) = unpack('N', Strings::shift($public, 4));
109
        Strings::shift($public, $length);
110
 
111
        // PuTTY pads private keys with a null byte per the following:
112
        // https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926
113
        if (!$curve instanceof TwistedEdwardsCurve) {
114
            $private = $privateKey->toBytes();
115
            if (!(strlen($privateKey->toBits()) & 7)) {
116
                $private = "\0$private";
117
            }
118
        }
119
 
120
        $private = $curve instanceof TwistedEdwardsCurve ?
121
            Strings::packSSH2('s', $privateKey->secret) :
122
            Strings::packSSH2('s', $private);
123
 
124
        return self::wrapPrivateKey($public, $private, $name, $password, $options);
125
    }
126
 
127
    /**
128
     * Convert an EC public key to the appropriate format
129
     *
874 daniel-mar 130
     * @access public
827 daniel-mar 131
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
132
     * @param \phpseclib3\Math\Common\FiniteField[] $publicKey
133
     * @return string
134
     */
135
    public static function savePublicKey(BaseCurve $curve, array $publicKey)
136
    {
137
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
138
        $type = $public[0];
139
        $public = Base64::decode($public[1]);
140
        list(, $length) = unpack('N', Strings::shift($public, 4));
141
        Strings::shift($public, $length);
142
 
143
        return self::wrapPublicKey($public, $type);
144
    }
145
}