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 | } |