KeyPair.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. namespace Elliptic\EC;
  3. use BN\BN;
  4. class KeyPair
  5. {
  6. public $ec;
  7. public $pub;
  8. public $priv;
  9. function __construct($ec, #[\SensitiveParameter]
  10. $options)
  11. {
  12. $this->ec = $ec;
  13. $this->priv = null;
  14. $this->pub = null;
  15. if( isset($options["priv"]) )
  16. $this->_importPrivate($options["priv"], $options["privEnc"]);
  17. if( isset($options["pub"]) )
  18. $this->_importPublic($options["pub"], $options["pubEnc"]);
  19. }
  20. public static function fromPublic($ec, $pub, $enc)
  21. {
  22. if( $pub instanceof KeyPair )
  23. return $pub;
  24. return new KeyPair($ec, array(
  25. "pub" => $pub,
  26. "pubEnc" => $enc
  27. ));
  28. }
  29. public static function fromPrivate($ec, #[\SensitiveParameter]
  30. $priv, $enc)
  31. {
  32. if( $priv instanceof KeyPair )
  33. return $priv;
  34. return new KeyPair($ec, array(
  35. "priv" => $priv,
  36. "privEnc" => $enc
  37. ));
  38. }
  39. public function validate()
  40. {
  41. $pub = $this->getPublic();
  42. if( $pub->isInfinity() )
  43. return array( "result" => false, "reason" => "Invalid public key" );
  44. if( !$pub->validate() )
  45. return array( "result" => false, "reason" => "Public key is not a point" );
  46. if( !$pub->mul($this->ec->curve->n)->isInfinity() )
  47. return array( "result" => false, "reason" => "Public key * N != O" );
  48. return array( "result" => true, "reason" => null );
  49. }
  50. public function getPublic($compact = false, $enc = "")
  51. {
  52. //compact is optional argument
  53. if( is_string($compact) )
  54. {
  55. $enc = $compact;
  56. $compact = false;
  57. }
  58. if( $this->pub === null )
  59. $this->pub = $this->ec->g->mul($this->priv);
  60. if( !$enc )
  61. return $this->pub;
  62. return $this->pub->encode($enc, $compact);
  63. }
  64. public function getPrivate($enc = false)
  65. {
  66. if( $enc === "hex" )
  67. return $this->priv->toString(16, 2);
  68. return $this->priv;
  69. }
  70. private function _importPrivate(#[\SensitiveParameter]
  71. $key, $enc)
  72. {
  73. $this->priv = new BN($key, (isset($enc) && $enc) ? $enc : 16);
  74. // Ensure that the priv won't be bigger than n, otherwise we may fail
  75. // in fixed multiplication method
  76. $this->priv = $this->priv->umod($this->ec->curve->n);
  77. }
  78. private function _importPublic($key, $enc)
  79. {
  80. $x = $y = null;
  81. if ( is_object($key) ) {
  82. $x = $key->x;
  83. $y = $key->y;
  84. } elseif ( is_array($key) ) {
  85. $x = isset($key["x"]) ? $key["x"] : null;
  86. $y = isset($key["y"]) ? $key["y"] : null;
  87. }
  88. if( $x != null || $y != null )
  89. $this->pub = $this->ec->curve->point($x, $y);
  90. else
  91. $this->pub = $this->ec->curve->decodePoint($key, $enc);
  92. }
  93. //ECDH
  94. public function derive($pub) {
  95. return $pub->mul($this->priv)->getX();
  96. }
  97. //ECDSA
  98. public function sign($msg, $enc = false, $options = false) {
  99. return $this->ec->sign($msg, $this, $enc, $options);
  100. }
  101. public function verify($msg, $signature) {
  102. return $this->ec->verify($msg, $signature, $this);
  103. }
  104. public function inspect() {
  105. return "<Key priv: " . (isset($this->priv) ? $this->priv->toString(16, 2) : "") .
  106. " pub: " . (isset($this->pub) ? $this->pub->inspect() : "") . ">";
  107. }
  108. public function __debugInfo() {
  109. return ["priv" => $this->priv, "pub" => $this->pub];
  110. }
  111. }
  112. ?>