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 * 12 * @category Crypt 13 * @package EC 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 20namespace phpseclib3\Crypt\EC\Formats\Keys; 21 22use phpseclib3\Crypt\EC\Curves\Ed25519; 23use phpseclib3\Exception\UnsupportedFormatException; 24use phpseclib3\Math\BigInteger; 25 26/** 27 * libsodium Key Handler 28 * 29 * @package EC 30 * @author Jim Wigginton <terrafrost@php.net> 31 * @access public 32 */ 33abstract class libsodium 34{ 35 use Common; 36 37 /** 38 * Is invisible flag 39 * 40 * @access private 41 */ 42 const IS_INVISIBLE = true; 43 44 /** 45 * Break a public or private key down into its constituent components 46 * 47 * @access public 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 * 88 * @access public 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 * 101 * @access public 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} 122