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
 * libsodium Key Handler
5
 *
6
 * Different NaCl implementations store the key differently.
7
 * https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ elaborates.
8
 * libsodium appears to use the same format as SUPERCOP.
9
 *
10
 * PHP version 5
11
 *
874 daniel-mar 12
 * @category  Crypt
13
 * @package   EC
827 daniel-mar 14
 * @author    Jim Wigginton <terrafrost@php.net>
15
 * @copyright 2015 Jim Wigginton
16
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
17
 * @link      http://phpseclib.sourceforge.net
18
 */
19
 
20
namespace phpseclib3\Crypt\EC\Formats\Keys;
21
 
22
use phpseclib3\Crypt\EC\Curves\Ed25519;
23
use phpseclib3\Exception\UnsupportedFormatException;
24
use phpseclib3\Math\BigInteger;
25
 
26
/**
27
 * libsodium Key Handler
28
 *
874 daniel-mar 29
 * @package EC
827 daniel-mar 30
 * @author  Jim Wigginton <terrafrost@php.net>
874 daniel-mar 31
 * @access  public
827 daniel-mar 32
 */
33
abstract class libsodium
34
{
35
    use Common;
36
 
37
    /**
38
     * Is invisible flag
39
     *
874 daniel-mar 40
     * @access private
827 daniel-mar 41
     */
42
    const IS_INVISIBLE = true;
43
 
44
    /**
45
     * Break a public or private key down into its constituent components
46
     *
874 daniel-mar 47
     * @access public
827 daniel-mar 48
     * @param string $key
49
     * @param string $password optional
50
     * @return array
51
     */
52
    public static function load($key, $password = '')
53
    {
54
        switch (strlen($key)) {
55
            case 32:
56
                $public = $key;
57
                break;
58
            case 64:
59
                $private = substr($key, 0, 32);
60
                $public = substr($key, -32);
61
                break;
62
            case 96:
63
                $public = substr($key, -32);
64
                if (substr($key, 32, 32) != $public) {
65
                    throw new \RuntimeException('Keys with 96 bytes should have the 2nd and 3rd set of 32 bytes match');
66
                }
67
                $private = substr($key, 0, 32);
68
                break;
69
            default:
70
                throw new \RuntimeException('libsodium keys need to either be 32 bytes long, 64 bytes long or 96 bytes long');
71
        }
72
 
73
        $curve = new Ed25519();
74
        $components = ['curve' => $curve];
75
        if (isset($private)) {
76
            $components['dA'] = $curve->extractSecret($private);
77
        }
78
        $components['QA'] = isset($public) ?
79
            self::extractPoint($public, $curve) :
80
            $curve->multiplyPoint($curve->getBasePoint(), $components['dA']);
81
 
82
        return $components;
83
    }
84
 
85
    /**
86
     * Convert an EC public key to the appropriate format
87
     *
874 daniel-mar 88
     * @access public
827 daniel-mar 89
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
90
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
91
     * @return string
92
     */
93
    public static function savePublicKey(Ed25519 $curve, array $publicKey)
94
    {
95
        return $curve->encodePoint($publicKey);
96
    }
97
 
98
    /**
99
     * Convert a private key to the appropriate format.
100
     *
874 daniel-mar 101
     * @access public
827 daniel-mar 102
     * @param \phpseclib3\Math\BigInteger $privateKey
103
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
104
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
105
     * @param string $password optional
106
     * @return string
107
     */
108
    public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, $password = '')
109
    {
110
        if (!isset($privateKey->secret)) {
111
            throw new \RuntimeException('Private Key does not have a secret set');
112
        }
113
        if (strlen($privateKey->secret) != 32) {
114
            throw new \RuntimeException('Private Key secret is not of the correct length');
115
        }
116
        if (!empty($password) && is_string($password)) {
117
            throw new UnsupportedFormatException('libsodium private keys do not support encryption');
118
        }
119
        return $privateKey->secret . $curve->encodePoint($publicKey);
120
    }
121
}