goldrat/vendor/simplito/elliptic-php/lib/EdDSA/KeyPair.php
2025-10-09 17:41:57 +00:00

129 lines
3.6 KiB
PHP

<?php
namespace Elliptic\EdDSA;
use Elliptic\Utils;
class KeyPair {
public $eddsa;
public $_pubBytes;
/**
* @param {\Elliptic\EdDSA} eddsa - instance
* @param {Object} params - public/private key parameters
*
* @param {Array<Byte>} [params.secret] - secret seed bytes
* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
* @param {Array<Byte>} [params.pub] - public key point encoded as bytes
*
*/
function __construct($eddsa, #[\SensitiveParameter]
$params) {
$this->eddsa = $eddsa;
$this->_secret = isset($params["secret"]) ? Utils::parseBytes($params["secret"]) : null;
if (!isset($params["pub"])) {
$this->_pub = null;
$this->_pubBytes = null;
return;
}
if ($eddsa->isPoint($params["pub"]))
$this->_pub = $params["pub"];
else
$this->_pubBytes = Utils::parseBytes($params["pub"]);
}
public static function fromPublic($eddsa, $pub) {
if ($pub instanceof KeyPair)
return $pub;
return new KeyPair($eddsa, [ "pub" => $pub ]);
}
public static function fromSecret($eddsa, #[\SensitiveParameter]
$secret) {
if ($secret instanceof KeyPair)
return $secret;
return new KeyPair($eddsa, [ "secret" => $secret ]);
}
private $_secret;
public function secret() {
return $this->_secret;
}
public function pubBytes() {
if (!$this->_pubBytes)
$this->_pubBytes = $this->eddsa->encodePoint($this->pub());
return $this->_pubBytes;
}
private $_pub;
public function pub() {
if (!$this->_pub) {
if ($this->_pubBytes)
$this->_pub = $this->eddsa->decodePoint($this->_pubBytes);
else
$this->_pub = $this->eddsa->g->mul($this->priv());
}
return $this->_pub;
}
private $_privBytes;
public function privBytes() {
if (!$this->_privBytes) {
$eddsa = $this->eddsa;
$hash = $this->hash();
$lastIx = $eddsa->encodingLength - 1;
$a = array_slice($hash, 0, $eddsa->encodingLength);
$a[0] &= 248;
$a[$lastIx] &= 127;
$a[$lastIx] |= 64;
$this->_privBytes = $a;
}
return $this->_privBytes;
}
private $_priv;
public function priv() {
if (!$this->_priv) {
$this->_priv = $this->eddsa->decodeInt($this->privBytes());
}
return $this->_priv;
}
private $_hash;
public function hash() {
if (!$this->_hash) {
// TODO: !!!
$hash = hash_init('sha512');
hash_update($hash, Utils::toBin($this->secret()));
$this->_hash = Utils::toArray( hash_final($hash), 'hex' );
}
return $this->_hash;
}
private $_messagePrefix;
public function messagePrefix() {
if (!$this->_messagePrefix) {
$this->_messagePrefix = array_slice($this->hash(), $this->eddsa->encodingLength);
}
return $this->_messagePrefix;
}
public function sign($message) {
assert($this->_secret); //, 'KeyPair can only verify');
return $this->eddsa->sign($message, $this);
}
public function verify($message, $sig) {
return $this->eddsa->verify($message, $sig, $this);
}
public function getSecret($enc = false) {
assert($this->_secret); //, 'KeyPair is public only');
return Utils::encode($this->secret(), $enc);
}
public function getPublic($enc = false) {
return Utils::encode($this->pubBytes(), $enc);
}
}