KeyPair.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. namespace Elliptic\EdDSA;
  3. use Elliptic\Utils;
  4. class KeyPair {
  5. public $eddsa;
  6. public $_pubBytes;
  7. /**
  8. * @param {\Elliptic\EdDSA} eddsa - instance
  9. * @param {Object} params - public/private key parameters
  10. *
  11. * @param {Array<Byte>} [params.secret] - secret seed bytes
  12. * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
  13. * @param {Array<Byte>} [params.pub] - public key point encoded as bytes
  14. *
  15. */
  16. function __construct($eddsa, $params) {
  17. $this->eddsa = $eddsa;
  18. $this->_secret = isset($params["secret"]) ? Utils::parseBytes($params["secret"]) : null;
  19. if (!isset($params["pub"])) {
  20. $this->_pub = null;
  21. $this->_pubBytes = null;
  22. return;
  23. }
  24. if ($eddsa->isPoint($params["pub"]))
  25. $this->_pub = $params["pub"];
  26. else
  27. $this->_pubBytes = Utils::parseBytes($params["pub"]);
  28. }
  29. public static function fromPublic($eddsa, $pub) {
  30. if ($pub instanceof KeyPair)
  31. return $pub;
  32. return new KeyPair($eddsa, [ "pub" => $pub ]);
  33. }
  34. public static function fromSecret($eddsa, $secret) {
  35. if ($secret instanceof KeyPair)
  36. return $secret;
  37. return new KeyPair($eddsa, [ "secret" => $secret ]);
  38. }
  39. private $_secret;
  40. public function secret() {
  41. return $this->_secret;
  42. }
  43. public function pubBytes() {
  44. if (!$this->_pubBytes)
  45. $this->_pubBytes = $this->eddsa->encodePoint($this->pub());
  46. return $this->_pubBytes;
  47. }
  48. private $_pub;
  49. public function pub() {
  50. if (!$this->_pub) {
  51. if ($this->_pubBytes)
  52. $this->_pub = $this->eddsa->decodePoint($this->_pubBytes);
  53. else
  54. $this->_pub = $this->eddsa->g->mul($this->priv());
  55. }
  56. return $this->_pub;
  57. }
  58. private $_privBytes;
  59. public function privBytes() {
  60. if (!$this->_privBytes) {
  61. $eddsa = $this->eddsa;
  62. $hash = $this->hash();
  63. $lastIx = $eddsa->encodingLength - 1;
  64. $a = array_slice($hash, 0, $eddsa->encodingLength);
  65. $a[0] &= 248;
  66. $a[$lastIx] &= 127;
  67. $a[$lastIx] |= 64;
  68. $this->_privBytes = $a;
  69. }
  70. return $this->_privBytes;
  71. }
  72. private $_priv;
  73. public function priv() {
  74. if (!$this->_priv) {
  75. $this->_priv = $this->eddsa->decodeInt($this->privBytes());
  76. }
  77. return $this->_priv;
  78. }
  79. private $_hash;
  80. public function hash() {
  81. if (!$this->_hash) {
  82. // TODO: !!!
  83. $hash = hash_init('sha512');
  84. hash_update($hash, Utils::toBin($this->secret()));
  85. $this->_hash = Utils::toArray( hash_final($hash), 'hex' );
  86. }
  87. return $this->_hash;
  88. }
  89. private $_messagePrefix;
  90. public function messagePrefix() {
  91. if (!$this->_messagePrefix) {
  92. $this->_messagePrefix = array_slice($this->hash(), $this->eddsa->encodingLength);
  93. }
  94. return $this->_messagePrefix;
  95. }
  96. public function sign($message) {
  97. assert($this->_secret); //, 'KeyPair can only verify');
  98. return $this->eddsa->sign($message, $this);
  99. }
  100. public function verify($message, $sig) {
  101. return $this->eddsa->verify($message, $sig, $this);
  102. }
  103. public function getSecret($enc = false) {
  104. assert($this->_secret); //, 'KeyPair is public only');
  105. return Utils::encode($this->secret(), $enc);
  106. }
  107. public function getPublic($enc = false) {
  108. return Utils::encode($this->pubBytes(), $enc);
  109. }
  110. }