index.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. import { EC } from "./elliptic";
  3. import { arrayify, hexlify, hexZeroPad, splitSignature } from "@ethersproject/bytes";
  4. import { defineReadOnly } from "@ethersproject/properties";
  5. import { Logger } from "@ethersproject/logger";
  6. import { version } from "./_version";
  7. const logger = new Logger(version);
  8. let _curve = null;
  9. function getCurve() {
  10. if (!_curve) {
  11. _curve = new EC("secp256k1");
  12. }
  13. return _curve;
  14. }
  15. export class SigningKey {
  16. constructor(privateKey) {
  17. defineReadOnly(this, "curve", "secp256k1");
  18. defineReadOnly(this, "privateKey", hexlify(privateKey));
  19. const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
  20. defineReadOnly(this, "publicKey", "0x" + keyPair.getPublic(false, "hex"));
  21. defineReadOnly(this, "compressedPublicKey", "0x" + keyPair.getPublic(true, "hex"));
  22. defineReadOnly(this, "_isSigningKey", true);
  23. }
  24. _addPoint(other) {
  25. const p0 = getCurve().keyFromPublic(arrayify(this.publicKey));
  26. const p1 = getCurve().keyFromPublic(arrayify(other));
  27. return "0x" + p0.pub.add(p1.pub).encodeCompressed("hex");
  28. }
  29. signDigest(digest) {
  30. const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
  31. const digestBytes = arrayify(digest);
  32. if (digestBytes.length !== 32) {
  33. logger.throwArgumentError("bad digest length", "digest", digest);
  34. }
  35. const signature = keyPair.sign(digestBytes, { canonical: true });
  36. return splitSignature({
  37. recoveryParam: signature.recoveryParam,
  38. r: hexZeroPad("0x" + signature.r.toString(16), 32),
  39. s: hexZeroPad("0x" + signature.s.toString(16), 32),
  40. });
  41. }
  42. computeSharedSecret(otherKey) {
  43. const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
  44. const otherKeyPair = getCurve().keyFromPublic(arrayify(computePublicKey(otherKey)));
  45. return hexZeroPad("0x" + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
  46. }
  47. static isSigningKey(value) {
  48. return !!(value && value._isSigningKey);
  49. }
  50. }
  51. export function recoverPublicKey(digest, signature) {
  52. const sig = splitSignature(signature);
  53. const rs = { r: arrayify(sig.r), s: arrayify(sig.s) };
  54. return "0x" + getCurve().recoverPubKey(arrayify(digest), rs, sig.recoveryParam).encode("hex", false);
  55. }
  56. export function computePublicKey(key, compressed) {
  57. const bytes = arrayify(key);
  58. if (bytes.length === 32) {
  59. const signingKey = new SigningKey(bytes);
  60. if (compressed) {
  61. return "0x" + getCurve().keyFromPrivate(bytes).getPublic(true, "hex");
  62. }
  63. return signingKey.publicKey;
  64. }
  65. else if (bytes.length === 33) {
  66. if (compressed) {
  67. return hexlify(bytes);
  68. }
  69. return "0x" + getCurve().keyFromPublic(bytes).getPublic(false, "hex");
  70. }
  71. else if (bytes.length === 65) {
  72. if (!compressed) {
  73. return hexlify(bytes);
  74. }
  75. return "0x" + getCurve().keyFromPublic(bytes).getPublic(true, "hex");
  76. }
  77. return logger.throwArgumentError("invalid public or private key", "key", "[REDACTED]");
  78. }
  79. //# sourceMappingURL=index.js.map