From 20907bede67ba2155d47dbc691a617e46d50caff Mon Sep 17 00:00:00 2001 From: Thomas Mathews Date: Wed, 22 Mar 2023 13:12:10 -0700 Subject: [PATCH] Use only nos2x. This removes all code that depends on our own implementation of key signing. Thus you must now use a browser extension to use any functionality. --- TODO | 17 - index.html | 4 +- js/bech32.js | 169 ------ js/core.js | 49 +- js/main.js | 12 +- js/noble-secp256k1.js | 1203 ----------------------------------------- js/ui/util.js | 40 +- 7 files changed, 24 insertions(+), 1470 deletions(-) delete mode 100644 TODO delete mode 100644 js/bech32.js delete mode 100644 js/noble-secp256k1.js diff --git a/TODO b/TODO deleted file mode 100644 index 272ae62..0000000 --- a/TODO +++ /dev/null @@ -1,17 +0,0 @@ -Here lie goals: - [ ] Autocomplete for usernames in composition - [ ] Display followers - [ ] Display following list - [ ] Export/import contacts list - [ ] Redesign embeds - [ ] Render lighting invoices (BOLT11) Do this without a library - [ ] Replace local storage usage - [ ] Show "Show More" button at end of timeline to display next 200 - [ ] Show likes on profile page under a tab - [ ] Store profiles of friends, friends of friends, & the user - [x] Direct messaging - [x] Fix UI/X issues on mobile (modal, reply, etc.) - [x] Mark all mail as read button. - [x] Render tagged users e.g. #[0] - [x] Toggle replys only in home view - [x] Update profile fields: name, banner, website, lightning address diff --git a/index.html b/index.html index 6f71004..87c3b19 100644 --- a/index.html +++ b/index.html @@ -14,8 +14,8 @@ - + @@ -23,8 +23,6 @@ - - diff --git a/js/bech32.js b/js/bech32.js deleted file mode 100644 index e76aadf..0000000 --- a/js/bech32.js +++ /dev/null @@ -1,169 +0,0 @@ -var ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; -var ALPHABET_MAP = {}; -for (var z = 0; z < ALPHABET.length; z++) { - var x = ALPHABET.charAt(z); - ALPHABET_MAP[x] = z; -} -function polymodStep(pre) { - var b = pre >> 25; - return (((pre & 0x1ffffff) << 5) ^ - (-((b >> 0) & 1) & 0x3b6a57b2) ^ - (-((b >> 1) & 1) & 0x26508e6d) ^ - (-((b >> 2) & 1) & 0x1ea119fa) ^ - (-((b >> 3) & 1) & 0x3d4233dd) ^ - (-((b >> 4) & 1) & 0x2a1462b3)); -} -function prefixChk(prefix) { - var chk = 1; - for (var i = 0; i < prefix.length; ++i) { - var c = prefix.charCodeAt(i); - if (c < 33 || c > 126) - return 'Invalid prefix (' + prefix + ')'; - chk = polymodStep(chk) ^ (c >> 5); - } - chk = polymodStep(chk); - for (var i = 0; i < prefix.length; ++i) { - var v = prefix.charCodeAt(i); - chk = polymodStep(chk) ^ (v & 0x1f); - } - return chk; -} -function convertbits(data, inBits, outBits, pad) { - var value = 0; - var bits = 0; - var maxV = (1 << outBits) - 1; - var result = []; - for (var i = 0; i < data.length; ++i) { - value = (value << inBits) | data[i]; - bits += inBits; - while (bits >= outBits) { - bits -= outBits; - result.push((value >> bits) & maxV); - } - } - if (pad) { - if (bits > 0) { - result.push((value << (outBits - bits)) & maxV); - } - } - else { - if (bits >= inBits) - return 'Excess padding'; - if ((value << (outBits - bits)) & maxV) - return 'Non-zero padding'; - } - return result; -} -function toWords(bytes) { - return convertbits(bytes, 8, 5, true); -} -function fromWordsUnsafe(words) { - var res = convertbits(words, 5, 8, false); - if (Array.isArray(res)) - return res; -} -function fromWords(words) { - var res = convertbits(words, 5, 8, false); - if (Array.isArray(res)) - return res; - throw new Error(res); -} -function getLibraryFromEncoding(encoding) { - var ENCODING_CONST; - if (encoding === 'bech32') { - ENCODING_CONST = 1; - } - else { - ENCODING_CONST = 0x2bc830a3; - } - function encode(prefix, words, LIMIT) { - LIMIT = LIMIT || 90; - if (prefix.length + 7 + words.length > LIMIT) - throw new TypeError('Exceeds length limit'); - prefix = prefix.toLowerCase(); - // determine chk mod - var chk = prefixChk(prefix); - if (typeof chk === 'string') - throw new Error(chk); - var result = prefix + '1'; - for (var i = 0; i < words.length; ++i) { - var x = words[i]; - if (x >> 5 !== 0) - throw new Error('Non 5-bit word'); - chk = polymodStep(chk) ^ x; - result += ALPHABET.charAt(x); - } - for (var i = 0; i < 6; ++i) { - chk = polymodStep(chk); - } - chk ^= ENCODING_CONST; - for (var i = 0; i < 6; ++i) { - var v = (chk >> ((5 - i) * 5)) & 0x1f; - result += ALPHABET.charAt(v); - } - return result; - } - function __decode(str, LIMIT) { - LIMIT = LIMIT || 90; - if (str.length < 8) - return str + ' too short'; - if (str.length > LIMIT) - return 'Exceeds length limit'; - // don't allow mixed case - var lowered = str.toLowerCase(); - var uppered = str.toUpperCase(); - if (str !== lowered && str !== uppered) - return 'Mixed-case string ' + str; - str = lowered; - var split = str.lastIndexOf('1'); - if (split === -1) - return 'No separator character for ' + str; - if (split === 0) - return 'Missing prefix for ' + str; - var prefix = str.slice(0, split); - var wordChars = str.slice(split + 1); - if (wordChars.length < 6) - return 'Data too short'; - var chk = prefixChk(prefix); - if (typeof chk === 'string') - return chk; - var words = []; - for (var i = 0; i < wordChars.length; ++i) { - var c = wordChars.charAt(i); - var v = ALPHABET_MAP[c]; - if (v === undefined) - return 'Unknown character ' + c; - chk = polymodStep(chk) ^ v; - // not in the checksum? - if (i + 6 >= wordChars.length) - continue; - words.push(v); - } - if (chk !== ENCODING_CONST) - return 'Invalid checksum for ' + str; - return { prefix: prefix, words: words }; - } - function decodeUnsafe(str, LIMIT) { - var res = __decode(str, LIMIT); - if (typeof res === 'object') - return res; - } - function decode(str, LIMIT) { - var res = __decode(str, LIMIT); - if (typeof res === 'object') - return res; - throw new Error(res); - } - return { - decodeUnsafe: decodeUnsafe, - decode: decode, - encode: encode, - toWords: toWords, - fromWordsUnsafe: fromWordsUnsafe, - fromWords: fromWords - }; -} - -const bech32 = getLibraryFromEncoding('bech32'); -const bech32m = getLibraryFromEncoding('bech32m'); - diff --git a/js/core.js b/js/core.js index 47bcef8..89f6c56 100644 --- a/js/core.js +++ b/js/core.js @@ -28,23 +28,6 @@ const PUBLIC_KINDS = [ KIND_SHARE, ]; -function get_local_state(key) { - if (DAMUS[key] != null) - return DAMUS[key] - return localStorage.getItem(key) -} - -function set_local_state(key, val) { - DAMUS[key] = val - localStorage.setItem(key, val) -} - -async function sign_id(privkey, id) { - //const digest = nostrjs.hex_decode(id) - const sig = await nobleSecp256k1.schnorr.sign(id, privkey) - return nostrjs.hex_encode(sig) -} - async function broadcast_related_events(ev) { ev.tags.reduce((evs, tag) => { // cap it at something sane @@ -120,18 +103,16 @@ async function update_contacts() { } async function sign_event(ev) { - if (window.nostr && window.nostr.signEvent) { - const signed = await window.nostr.signEvent(ev) - if (typeof signed === 'string') { - ev.sig = signed - return ev - } - return signed + if (!(window.nostr && window.nostr.signEvent)) { + console.error("window.nostr.signEvent is unsupported"); + return; } - - const privkey = get_privkey() - ev.sig = await sign_id(privkey, ev.id) - return ev + const signed = await window.nostr.signEvent(ev) + if (typeof signed === 'string') { + ev.sig = signed + return ev + } + return signed } function new_reply_tags(ev) { @@ -301,7 +282,6 @@ function get_content_warning(tags) { async function get_nip05_pubkey(email) { const [user, host] = email.split("@") const url = `https://${host}/.well-known/nostr.json?name=${user}` - try { const res = await fetch(url) const json = await res.json() @@ -312,14 +292,3 @@ async function get_nip05_pubkey(email) { throw e } } - -// TODO rename handle_pubkey to fetch_pubkey -async function handle_pubkey(pubkey) { - if (pubkey[0] === "n") - pubkey = bech32_decode(pubkey) - if (pubkey.includes("@")) - pubkey = await get_nip05_pubkey(pubkey) - set_local_state('pubkey', pubkey) - return pubkey -} - diff --git a/js/main.js b/js/main.js index 1ac48c8..56ee41d 100644 --- a/js/main.js +++ b/js/main.js @@ -23,18 +23,18 @@ addEventListener('DOMContentLoaded', (ev) => { async function damus_web_init() { let tries = 0; - const max_wait = 500; const interval = 20; - async function init() { - if (window.nostr || tries >= (max_wait/interval)) { + function init() { + if (window.nostr) { log_info("init after", tries); - await damus_web_init_ready(); + damus_web_init_ready(); return; } + // TODO if tries is too many say window.nostr not found. tries++; - await init(); + setTimeout(init, interval); } - setTimeout(init, interval); + init(); } async function damus_web_init_ready() { diff --git a/js/noble-secp256k1.js b/js/noble-secp256k1.js deleted file mode 100644 index 5f19504..0000000 --- a/js/noble-secp256k1.js +++ /dev/null @@ -1,1203 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.nobleSecp256k1 = {})); -})(this, (function (exports) { 'use strict'; - - const _nodeResolve_empty = {}; - - const nodeCrypto = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _nodeResolve_empty - }); - - /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ - const _0n = BigInt(0); - const _1n = BigInt(1); - const _2n = BigInt(2); - const _3n = BigInt(3); - const _8n = BigInt(8); - const CURVE = Object.freeze({ - a: _0n, - b: BigInt(7), - P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'), - n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), - h: _1n, - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - }); - function weistrass(x) { - const { a, b } = CURVE; - const x2 = mod(x * x); - const x3 = mod(x2 * x); - return mod(x3 + a * x + b); - } - const USE_ENDOMORPHISM = CURVE.a === _0n; - class ShaError extends Error { - constructor(message) { - super(message); - } - } - class JacobianPoint { - constructor(x, y, z) { - this.x = x; - this.y = y; - this.z = z; - } - static fromAffine(p) { - if (!(p instanceof Point)) { - throw new TypeError('JacobianPoint#fromAffine: expected Point'); - } - return new JacobianPoint(p.x, p.y, _1n); - } - static toAffineBatch(points) { - const toInv = invertBatch(points.map((p) => p.z)); - return points.map((p, i) => p.toAffine(toInv[i])); - } - static normalizeZ(points) { - return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine); - } - equals(other) { - if (!(other instanceof JacobianPoint)) - throw new TypeError('JacobianPoint expected'); - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; - const Z1Z1 = mod(Z1 * Z1); - const Z2Z2 = mod(Z2 * Z2); - const U1 = mod(X1 * Z2Z2); - const U2 = mod(X2 * Z1Z1); - const S1 = mod(mod(Y1 * Z2) * Z2Z2); - const S2 = mod(mod(Y2 * Z1) * Z1Z1); - return U1 === U2 && S1 === S2; - } - negate() { - return new JacobianPoint(this.x, mod(-this.y), this.z); - } - double() { - const { x: X1, y: Y1, z: Z1 } = this; - const A = mod(X1 * X1); - const B = mod(Y1 * Y1); - const C = mod(B * B); - const x1b = X1 + B; - const D = mod(_2n * (mod(x1b * x1b) - A - C)); - const E = mod(_3n * A); - const F = mod(E * E); - const X3 = mod(F - _2n * D); - const Y3 = mod(E * (D - X3) - _8n * C); - const Z3 = mod(_2n * Y1 * Z1); - return new JacobianPoint(X3, Y3, Z3); - } - add(other) { - if (!(other instanceof JacobianPoint)) - throw new TypeError('JacobianPoint expected'); - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; - if (X2 === _0n || Y2 === _0n) - return this; - if (X1 === _0n || Y1 === _0n) - return other; - const Z1Z1 = mod(Z1 * Z1); - const Z2Z2 = mod(Z2 * Z2); - const U1 = mod(X1 * Z2Z2); - const U2 = mod(X2 * Z1Z1); - const S1 = mod(mod(Y1 * Z2) * Z2Z2); - const S2 = mod(mod(Y2 * Z1) * Z1Z1); - const H = mod(U2 - U1); - const r = mod(S2 - S1); - if (H === _0n) { - if (r === _0n) { - return this.double(); - } - else { - return JacobianPoint.ZERO; - } - } - const HH = mod(H * H); - const HHH = mod(H * HH); - const V = mod(U1 * HH); - const X3 = mod(r * r - HHH - _2n * V); - const Y3 = mod(r * (V - X3) - S1 * HHH); - const Z3 = mod(Z1 * Z2 * H); - return new JacobianPoint(X3, Y3, Z3); - } - subtract(other) { - return this.add(other.negate()); - } - multiplyUnsafe(scalar) { - const P0 = JacobianPoint.ZERO; - if (typeof scalar === 'bigint' && scalar === _0n) - return P0; - let n = normalizeScalar(scalar); - if (n === _1n) - return this; - if (!USE_ENDOMORPHISM) { - let p = P0; - let d = this; - while (n > _0n) { - if (n & _1n) - p = p.add(d); - d = d.double(); - n >>= _1n; - } - return p; - } - let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); - let k1p = P0; - let k2p = P0; - let d = this; - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) - k1p = k1p.add(d); - if (k2 & _1n) - k2p = k2p.add(d); - d = d.double(); - k1 >>= _1n; - k2 >>= _1n; - } - if (k1neg) - k1p = k1p.negate(); - if (k2neg) - k2p = k2p.negate(); - k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); - return k1p.add(k2p); - } - precomputeWindow(W) { - const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1; - const points = []; - let p = this; - let base = p; - for (let window = 0; window < windows; window++) { - base = p; - points.push(base); - for (let i = 1; i < 2 ** (W - 1); i++) { - base = base.add(p); - points.push(base); - } - p = base.double(); - } - return points; - } - wNAF(n, affinePoint) { - if (!affinePoint && this.equals(JacobianPoint.BASE)) - affinePoint = Point.BASE; - const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1; - if (256 % W) { - throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2'); - } - let precomputes = affinePoint && pointPrecomputes.get(affinePoint); - if (!precomputes) { - precomputes = this.precomputeWindow(W); - if (affinePoint && W !== 1) { - precomputes = JacobianPoint.normalizeZ(precomputes); - pointPrecomputes.set(affinePoint, precomputes); - } - } - let p = JacobianPoint.ZERO; - let f = JacobianPoint.ZERO; - const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W); - const windowSize = 2 ** (W - 1); - const mask = BigInt(2 ** W - 1); - const maxNumber = 2 ** W; - const shiftBy = BigInt(W); - for (let window = 0; window < windows; window++) { - const offset = window * windowSize; - let wbits = Number(n & mask); - n >>= shiftBy; - if (wbits > windowSize) { - wbits -= maxNumber; - n += _1n; - } - if (wbits === 0) { - let pr = precomputes[offset]; - if (window % 2) - pr = pr.negate(); - f = f.add(pr); - } - else { - let cached = precomputes[offset + Math.abs(wbits) - 1]; - if (wbits < 0) - cached = cached.negate(); - p = p.add(cached); - } - } - return { p, f }; - } - multiply(scalar, affinePoint) { - let n = normalizeScalar(scalar); - let point; - let fake; - if (USE_ENDOMORPHISM) { - const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); - let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint); - let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint); - if (k1neg) - k1p = k1p.negate(); - if (k2neg) - k2p = k2p.negate(); - k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); - point = k1p.add(k2p); - fake = f1p.add(f2p); - } - else { - const { p, f } = this.wNAF(n, affinePoint); - point = p; - fake = f; - } - return JacobianPoint.normalizeZ([point, fake])[0]; - } - toAffine(invZ = invert(this.z)) { - const { x, y, z } = this; - const iz1 = invZ; - const iz2 = mod(iz1 * iz1); - const iz3 = mod(iz2 * iz1); - const ax = mod(x * iz2); - const ay = mod(y * iz3); - const zz = mod(z * iz1); - if (zz !== _1n) - throw new Error('invZ was invalid'); - return new Point(ax, ay); - } - } - JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n); - JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n); - const pointPrecomputes = new WeakMap(); - class Point { - constructor(x, y) { - this.x = x; - this.y = y; - } - _setWindowSize(windowSize) { - this._WINDOW_SIZE = windowSize; - pointPrecomputes.delete(this); - } - hasEvenY() { - return this.y % _2n === _0n; - } - static fromCompressedHex(bytes) { - const isShort = bytes.length === 32; - const x = bytesToNumber(isShort ? bytes : bytes.subarray(1)); - if (!isValidFieldElement(x)) - throw new Error('Point is not on curve'); - const y2 = weistrass(x); - let y = sqrtMod(y2); - const isYOdd = (y & _1n) === _1n; - if (isShort) { - if (isYOdd) - y = mod(-y); - } - else { - const isFirstByteOdd = (bytes[0] & 1) === 1; - if (isFirstByteOdd !== isYOdd) - y = mod(-y); - } - const point = new Point(x, y); - point.assertValidity(); - return point; - } - static fromUncompressedHex(bytes) { - const x = bytesToNumber(bytes.subarray(1, 33)); - const y = bytesToNumber(bytes.subarray(33, 65)); - const point = new Point(x, y); - point.assertValidity(); - return point; - } - static fromHex(hex) { - const bytes = ensureBytes(hex); - const len = bytes.length; - const header = bytes[0]; - if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) { - return this.fromCompressedHex(bytes); - } - if (len === 65 && header === 0x04) - return this.fromUncompressedHex(bytes); - throw new Error(`Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}`); - } - static fromPrivateKey(privateKey) { - return Point.BASE.multiply(normalizePrivateKey(privateKey)); - } - static fromSignature(msgHash, signature, recovery) { - msgHash = ensureBytes(msgHash); - const h = truncateHash(msgHash); - const { r, s } = normalizeSignature(signature); - if (recovery !== 0 && recovery !== 1) { - throw new Error('Cannot recover signature: invalid recovery bit'); - } - const prefix = recovery & 1 ? '03' : '02'; - const R = Point.fromHex(prefix + numTo32bStr(r)); - const { n } = CURVE; - const rinv = invert(r, n); - const u1 = mod(-h * rinv, n); - const u2 = mod(s * rinv, n); - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); - if (!Q) - throw new Error('Cannot recover signature: point at infinify'); - Q.assertValidity(); - return Q; - } - toRawBytes(isCompressed = false) { - return hexToBytes(this.toHex(isCompressed)); - } - toHex(isCompressed = false) { - const x = numTo32bStr(this.x); - if (isCompressed) { - const prefix = this.hasEvenY() ? '02' : '03'; - return `${prefix}${x}`; - } - else { - return `04${x}${numTo32bStr(this.y)}`; - } - } - toHexX() { - return this.toHex(true).slice(2); - } - toRawX() { - return this.toRawBytes(true).slice(1); - } - assertValidity() { - const msg = 'Point is not on elliptic curve'; - const { x, y } = this; - if (!isValidFieldElement(x) || !isValidFieldElement(y)) - throw new Error(msg); - const left = mod(y * y); - const right = weistrass(x); - if (mod(left - right) !== _0n) - throw new Error(msg); - } - equals(other) { - return this.x === other.x && this.y === other.y; - } - negate() { - return new Point(this.x, mod(-this.y)); - } - double() { - return JacobianPoint.fromAffine(this).double().toAffine(); - } - add(other) { - return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine(); - } - subtract(other) { - return this.add(other.negate()); - } - multiply(scalar) { - return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine(); - } - multiplyAndAddUnsafe(Q, a, b) { - const P = JacobianPoint.fromAffine(this); - const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a); - const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b); - const sum = aP.add(bQ); - return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine(); - } - } - Point.BASE = new Point(CURVE.Gx, CURVE.Gy); - Point.ZERO = new Point(_0n, _0n); - function sliceDER(s) { - return Number.parseInt(s[0], 16) >= 8 ? '00' + s : s; - } - function parseDERInt(data) { - if (data.length < 2 || data[0] !== 0x02) { - throw new Error(`Invalid signature integer tag: ${bytesToHex(data)}`); - } - const len = data[1]; - const res = data.subarray(2, len + 2); - if (!len || res.length !== len) { - throw new Error(`Invalid signature integer: wrong length`); - } - if (res[0] === 0x00 && res[1] <= 0x7f) { - throw new Error('Invalid signature integer: trailing length'); - } - return { data: bytesToNumber(res), left: data.subarray(len + 2) }; - } - function parseDERSignature(data) { - if (data.length < 2 || data[0] != 0x30) { - throw new Error(`Invalid signature tag: ${bytesToHex(data)}`); - } - if (data[1] !== data.length - 2) { - throw new Error('Invalid signature: incorrect length'); - } - const { data: r, left: sBytes } = parseDERInt(data.subarray(2)); - const { data: s, left: rBytesLeft } = parseDERInt(sBytes); - if (rBytesLeft.length) { - throw new Error(`Invalid signature: left bytes after parsing: ${bytesToHex(rBytesLeft)}`); - } - return { r, s }; - } - class Signature { - constructor(r, s) { - this.r = r; - this.s = s; - this.assertValidity(); - } - static fromCompact(hex) { - const arr = hex instanceof Uint8Array; - const name = 'Signature.fromCompact'; - if (typeof hex !== 'string' && !arr) - throw new TypeError(`${name}: Expected string or Uint8Array`); - const str = arr ? bytesToHex(hex) : hex; - if (str.length !== 128) - throw new Error(`${name}: Expected 64-byte hex`); - return new Signature(hexToNumber(str.slice(0, 64)), hexToNumber(str.slice(64, 128))); - } - static fromDER(hex) { - const arr = hex instanceof Uint8Array; - if (typeof hex !== 'string' && !arr) - throw new TypeError(`Signature.fromDER: Expected string or Uint8Array`); - const { r, s } = parseDERSignature(arr ? hex : hexToBytes(hex)); - return new Signature(r, s); - } - static fromHex(hex) { - return this.fromDER(hex); - } - assertValidity() { - const { r, s } = this; - if (!isWithinCurveOrder(r)) - throw new Error('Invalid Signature: r must be 0 < r < n'); - if (!isWithinCurveOrder(s)) - throw new Error('Invalid Signature: s must be 0 < s < n'); - } - hasHighS() { - const HALF = CURVE.n >> _1n; - return this.s > HALF; - } - normalizeS() { - return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this; - } - toDERRawBytes(isCompressed = false) { - return hexToBytes(this.toDERHex(isCompressed)); - } - toDERHex(isCompressed = false) { - const sHex = sliceDER(numberToHexUnpadded(this.s)); - if (isCompressed) - return sHex; - const rHex = sliceDER(numberToHexUnpadded(this.r)); - const rLen = numberToHexUnpadded(rHex.length / 2); - const sLen = numberToHexUnpadded(sHex.length / 2); - const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4); - return `30${length}02${rLen}${rHex}02${sLen}${sHex}`; - } - toRawBytes() { - return this.toDERRawBytes(); - } - toHex() { - return this.toDERHex(); - } - toCompactRawBytes() { - return hexToBytes(this.toCompactHex()); - } - toCompactHex() { - return numTo32bStr(this.r) + numTo32bStr(this.s); - } - } - function concatBytes(...arrays) { - if (!arrays.every((b) => b instanceof Uint8Array)) - throw new Error('Uint8Array list expected'); - if (arrays.length === 1) - return arrays[0]; - const length = arrays.reduce((a, arr) => a + arr.length, 0); - const result = new Uint8Array(length); - for (let i = 0, pad = 0; i < arrays.length; i++) { - const arr = arrays[i]; - result.set(arr, pad); - pad += arr.length; - } - return result; - } - const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); - function bytesToHex(uint8a) { - if (!(uint8a instanceof Uint8Array)) - throw new Error('Expected Uint8Array'); - let hex = ''; - for (let i = 0; i < uint8a.length; i++) { - hex += hexes[uint8a[i]]; - } - return hex; - } - const POW_2_256 = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000'); - function numTo32bStr(num) { - if (typeof num !== 'bigint') - throw new Error('Expected bigint'); - if (!(_0n <= num && num < POW_2_256)) - throw new Error('Expected number < 2^256'); - return num.toString(16).padStart(64, '0'); - } - function numTo32b(num) { - const b = hexToBytes(numTo32bStr(num)); - if (b.length !== 32) - throw new Error('Error: expected 32 bytes'); - return b; - } - function numberToHexUnpadded(num) { - const hex = num.toString(16); - return hex.length & 1 ? `0${hex}` : hex; - } - function hexToNumber(hex) { - if (typeof hex !== 'string') { - throw new TypeError('hexToNumber: expected string, got ' + typeof hex); - } - return BigInt(`0x${hex}`); - } - function hexToBytes(hex) { - if (typeof hex !== 'string') { - throw new TypeError('hexToBytes: expected string, got ' + typeof hex); - } - if (hex.length % 2) - throw new Error('hexToBytes: received invalid unpadded hex' + hex.length); - const array = new Uint8Array(hex.length / 2); - for (let i = 0; i < array.length; i++) { - const j = i * 2; - const hexByte = hex.slice(j, j + 2); - const byte = Number.parseInt(hexByte, 16); - if (Number.isNaN(byte) || byte < 0) - throw new Error('Invalid byte sequence'); - array[i] = byte; - } - return array; - } - function bytesToNumber(bytes) { - return hexToNumber(bytesToHex(bytes)); - } - function ensureBytes(hex) { - return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex); - } - function normalizeScalar(num) { - if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0) - return BigInt(num); - if (typeof num === 'bigint' && isWithinCurveOrder(num)) - return num; - throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n'); - } - function mod(a, b = CURVE.P) { - const result = a % b; - return result >= _0n ? result : b + result; - } - function pow2(x, power) { - const { P } = CURVE; - let res = x; - while (power-- > _0n) { - res *= res; - res %= P; - } - return res; - } - function sqrtMod(x) { - const { P } = CURVE; - const _6n = BigInt(6); - const _11n = BigInt(11); - const _22n = BigInt(22); - const _23n = BigInt(23); - const _44n = BigInt(44); - const _88n = BigInt(88); - const b2 = (x * x * x) % P; - const b3 = (b2 * b2 * x) % P; - const b6 = (pow2(b3, _3n) * b3) % P; - const b9 = (pow2(b6, _3n) * b3) % P; - const b11 = (pow2(b9, _2n) * b2) % P; - const b22 = (pow2(b11, _11n) * b11) % P; - const b44 = (pow2(b22, _22n) * b22) % P; - const b88 = (pow2(b44, _44n) * b44) % P; - const b176 = (pow2(b88, _88n) * b88) % P; - const b220 = (pow2(b176, _44n) * b44) % P; - const b223 = (pow2(b220, _3n) * b3) % P; - const t1 = (pow2(b223, _23n) * b22) % P; - const t2 = (pow2(t1, _6n) * b2) % P; - return pow2(t2, _2n); - } - function invert(number, modulo = CURVE.P) { - if (number === _0n || modulo <= _0n) { - throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); - } - let a = mod(number, modulo); - let b = modulo; - let x = _0n, u = _1n; - while (a !== _0n) { - const q = b / a; - const r = b % a; - const m = x - u * q; - b = a, a = r, x = u, u = m; - } - const gcd = b; - if (gcd !== _1n) - throw new Error('invert: does not exist'); - return mod(x, modulo); - } - function invertBatch(nums, p = CURVE.P) { - const scratch = new Array(nums.length); - const lastMultiplied = nums.reduce((acc, num, i) => { - if (num === _0n) - return acc; - scratch[i] = acc; - return mod(acc * num, p); - }, _1n); - const inverted = invert(lastMultiplied, p); - nums.reduceRight((acc, num, i) => { - if (num === _0n) - return acc; - scratch[i] = mod(acc * scratch[i], p); - return mod(acc * num, p); - }, inverted); - return scratch; - } - const divNearest = (a, b) => (a + b / _2n) / b; - const ENDO = { - a1: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), - b1: -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'), - a2: BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), - b2: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), - POW_2_128: BigInt('0x100000000000000000000000000000000'), - }; - function splitScalarEndo(k) { - const { n } = CURVE; - const { a1, b1, a2, b2, POW_2_128 } = ENDO; - const c1 = divNearest(b2 * k, n); - const c2 = divNearest(-b1 * k, n); - let k1 = mod(k - c1 * a1 - c2 * a2, n); - let k2 = mod(-c1 * b1 - c2 * b2, n); - const k1neg = k1 > POW_2_128; - const k2neg = k2 > POW_2_128; - if (k1neg) - k1 = n - k1; - if (k2neg) - k2 = n - k2; - if (k1 > POW_2_128 || k2 > POW_2_128) { - throw new Error('splitScalarEndo: Endomorphism failed, k=' + k); - } - return { k1neg, k1, k2neg, k2 }; - } - function truncateHash(hash) { - const { n } = CURVE; - const byteLength = hash.length; - const delta = byteLength * 8 - 256; - let h = bytesToNumber(hash); - if (delta > 0) - h = h >> BigInt(delta); - if (h >= n) - h -= n; - return h; - } - let _sha256Sync; - let _hmacSha256Sync; - class HmacDrbg { - constructor() { - this.v = new Uint8Array(32).fill(1); - this.k = new Uint8Array(32).fill(0); - this.counter = 0; - } - hmac(...values) { - return utils.hmacSha256(this.k, ...values); - } - hmacSync(...values) { - return _hmacSha256Sync(this.k, ...values); - } - checkSync() { - if (typeof _hmacSha256Sync !== 'function') - throw new ShaError('hmacSha256Sync needs to be set'); - } - incr() { - if (this.counter >= 1000) - throw new Error('Tried 1,000 k values for sign(), all were invalid'); - this.counter += 1; - } - async reseed(seed = new Uint8Array()) { - this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed); - this.v = await this.hmac(this.v); - if (seed.length === 0) - return; - this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed); - this.v = await this.hmac(this.v); - } - reseedSync(seed = new Uint8Array()) { - this.checkSync(); - this.k = this.hmacSync(this.v, Uint8Array.from([0x00]), seed); - this.v = this.hmacSync(this.v); - if (seed.length === 0) - return; - this.k = this.hmacSync(this.v, Uint8Array.from([0x01]), seed); - this.v = this.hmacSync(this.v); - } - async generate() { - this.incr(); - this.v = await this.hmac(this.v); - return this.v; - } - generateSync() { - this.checkSync(); - this.incr(); - this.v = this.hmacSync(this.v); - return this.v; - } - } - function isWithinCurveOrder(num) { - return _0n < num && num < CURVE.n; - } - function isValidFieldElement(num) { - return _0n < num && num < CURVE.P; - } - function kmdToSig(kBytes, m, d) { - const k = bytesToNumber(kBytes); - if (!isWithinCurveOrder(k)) - return; - const { n } = CURVE; - const q = Point.BASE.multiply(k); - const r = mod(q.x, n); - if (r === _0n) - return; - const s = mod(invert(k, n) * mod(m + d * r, n), n); - if (s === _0n) - return; - const sig = new Signature(r, s); - const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); - return { sig, recovery }; - } - function normalizePrivateKey(key) { - let num; - if (typeof key === 'bigint') { - num = key; - } - else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) { - num = BigInt(key); - } - else if (typeof key === 'string') { - if (key.length !== 64) - throw new Error('Expected 32 bytes of private key'); - num = hexToNumber(key); - } - else if (key instanceof Uint8Array) { - if (key.length !== 32) - throw new Error('Expected 32 bytes of private key'); - num = bytesToNumber(key); - } - else { - throw new TypeError('Expected valid private key'); - } - if (!isWithinCurveOrder(num)) - throw new Error('Expected private key: 0 < key < n'); - return num; - } - function normalizePublicKey(publicKey) { - if (publicKey instanceof Point) { - publicKey.assertValidity(); - return publicKey; - } - else { - return Point.fromHex(publicKey); - } - } - function normalizeSignature(signature) { - if (signature instanceof Signature) { - signature.assertValidity(); - return signature; - } - try { - return Signature.fromDER(signature); - } - catch (error) { - return Signature.fromCompact(signature); - } - } - function getPublicKey(privateKey, isCompressed = false) { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed); - } - function recoverPublicKey(msgHash, signature, recovery, isCompressed = false) { - return Point.fromSignature(msgHash, signature, recovery).toRawBytes(isCompressed); - } - function isProbPub(item) { - const arr = item instanceof Uint8Array; - const str = typeof item === 'string'; - const len = (arr || str) && item.length; - if (arr) - return len === 33 || len === 65; - if (str) - return len === 66 || len === 130; - if (item instanceof Point) - return true; - return false; - } - function getSharedSecret(privateA, publicB, isCompressed = false) { - if (isProbPub(privateA)) - throw new TypeError('getSharedSecret: first arg must be private key'); - if (!isProbPub(publicB)) - throw new TypeError('getSharedSecret: second arg must be public key'); - const b = normalizePublicKey(publicB); - b.assertValidity(); - return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed); - } - function bits2int(bytes) { - const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes; - return bytesToNumber(slice); - } - function bits2octets(bytes) { - const z1 = bits2int(bytes); - const z2 = mod(z1, CURVE.n); - return int2octets(z2 < _0n ? z1 : z2); - } - function int2octets(num) { - return numTo32b(num); - } - function initSigArgs(msgHash, privateKey, extraEntropy) { - if (msgHash == null) - throw new Error(`sign: expected valid message hash, not "${msgHash}"`); - const h1 = ensureBytes(msgHash); - const d = normalizePrivateKey(privateKey); - const seedArgs = [int2octets(d), bits2octets(h1)]; - if (extraEntropy != null) { - if (extraEntropy === true) - extraEntropy = utils.randomBytes(32); - const e = ensureBytes(extraEntropy); - if (e.length !== 32) - throw new Error('sign: Expected 32 bytes of extra data'); - seedArgs.push(e); - } - const seed = concatBytes(...seedArgs); - const m = bits2int(h1); - return { seed, m, d }; - } - function finalizeSig(recSig, opts) { - let { sig, recovery } = recSig; - const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts); - if (canonical && sig.hasHighS()) { - sig = sig.normalizeS(); - recovery ^= 1; - } - const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes(); - return recovered ? [hashed, recovery] : hashed; - } - async function sign(msgHash, privKey, opts = {}) { - const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - let sig; - const drbg = new HmacDrbg(); - await drbg.reseed(seed); - while (!(sig = kmdToSig(await drbg.generate(), m, d))) - await drbg.reseed(); - return finalizeSig(sig, opts); - } - function signSync(msgHash, privKey, opts = {}) { - const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - let sig; - const drbg = new HmacDrbg(); - drbg.reseedSync(seed); - while (!(sig = kmdToSig(drbg.generateSync(), m, d))) - drbg.reseedSync(); - return finalizeSig(sig, opts); - } - const vopts = { strict: true }; - function verify(signature, msgHash, publicKey, opts = vopts) { - let sig; - try { - sig = normalizeSignature(signature); - msgHash = ensureBytes(msgHash); - } - catch (error) { - return false; - } - const { r, s } = sig; - if (opts.strict && sig.hasHighS()) - return false; - const h = truncateHash(msgHash); - let P; - try { - P = normalizePublicKey(publicKey); - } - catch (error) { - return false; - } - const { n } = CURVE; - const sinv = invert(s, n); - const u1 = mod(h * sinv, n); - const u2 = mod(r * sinv, n); - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2); - if (!R) - return false; - const v = mod(R.x, n); - return v === r; - } - function schnorrChallengeFinalize(ch) { - return mod(bytesToNumber(ch), CURVE.n); - } - class SchnorrSignature { - constructor(r, s) { - this.r = r; - this.s = s; - this.assertValidity(); - } - static fromHex(hex) { - const bytes = ensureBytes(hex); - if (bytes.length !== 64) - throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`); - const r = bytesToNumber(bytes.subarray(0, 32)); - const s = bytesToNumber(bytes.subarray(32, 64)); - return new SchnorrSignature(r, s); - } - assertValidity() { - const { r, s } = this; - if (!isValidFieldElement(r) || !isWithinCurveOrder(s)) - throw new Error('Invalid signature'); - } - toHex() { - return numTo32bStr(this.r) + numTo32bStr(this.s); - } - toRawBytes() { - return hexToBytes(this.toHex()); - } - } - function schnorrGetPublicKey(privateKey) { - return Point.fromPrivateKey(privateKey).toRawX(); - } - class InternalSchnorrSignature { - constructor(message, privateKey, auxRand = utils.randomBytes()) { - if (message == null) - throw new TypeError(`sign: Expected valid message, not "${message}"`); - this.m = ensureBytes(message); - const { x, scalar } = this.getScalar(normalizePrivateKey(privateKey)); - this.px = x; - this.d = scalar; - this.rand = ensureBytes(auxRand); - if (this.rand.length !== 32) - throw new TypeError('sign: Expected 32 bytes of aux randomness'); - } - getScalar(priv) { - const point = Point.fromPrivateKey(priv); - const scalar = point.hasEvenY() ? priv : CURVE.n - priv; - return { point, scalar, x: point.toRawX() }; - } - initNonce(d, t0h) { - return numTo32b(d ^ bytesToNumber(t0h)); - } - finalizeNonce(k0h) { - const k0 = mod(bytesToNumber(k0h), CURVE.n); - if (k0 === _0n) - throw new Error('sign: Creation of signature failed. k is zero'); - const { point: R, x: rx, scalar: k } = this.getScalar(k0); - return { R, rx, k }; - } - finalizeSig(R, k, e, d) { - return new SchnorrSignature(R.x, mod(k + e * d, CURVE.n)).toRawBytes(); - } - error() { - throw new Error('sign: Invalid signature produced'); - } - async calc() { - const { m, d, px, rand } = this; - const tag = utils.taggedHash; - const t = this.initNonce(d, await tag(TAGS.aux, rand)); - const { R, rx, k } = this.finalizeNonce(await tag(TAGS.nonce, t, px, m)); - const e = schnorrChallengeFinalize(await tag(TAGS.challenge, rx, px, m)); - const sig = this.finalizeSig(R, k, e, d); - if (!(await schnorrVerify(sig, m, px))) - this.error(); - return sig; - } - calcSync() { - const { m, d, px, rand } = this; - const tag = utils.taggedHashSync; - const t = this.initNonce(d, tag(TAGS.aux, rand)); - const { R, rx, k } = this.finalizeNonce(tag(TAGS.nonce, t, px, m)); - const e = schnorrChallengeFinalize(tag(TAGS.challenge, rx, px, m)); - const sig = this.finalizeSig(R, k, e, d); - if (!schnorrVerifySync(sig, m, px)) - this.error(); - return sig; - } - } - async function schnorrSign(msg, privKey, auxRand) { - return new InternalSchnorrSignature(msg, privKey, auxRand).calc(); - } - function schnorrSignSync(msg, privKey, auxRand) { - return new InternalSchnorrSignature(msg, privKey, auxRand).calcSync(); - } - function initSchnorrVerify(signature, message, publicKey) { - const raw = signature instanceof SchnorrSignature; - const sig = raw ? signature : SchnorrSignature.fromHex(signature); - if (raw) - sig.assertValidity(); - return { - ...sig, - m: ensureBytes(message), - P: normalizePublicKey(publicKey), - }; - } - function finalizeSchnorrVerify(r, P, s, e) { - const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n)); - if (!R || !R.hasEvenY() || R.x !== r) - return false; - return true; - } - async function schnorrVerify(signature, message, publicKey) { - try { - const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); - const e = schnorrChallengeFinalize(await utils.taggedHash(TAGS.challenge, numTo32b(r), P.toRawX(), m)); - return finalizeSchnorrVerify(r, P, s, e); - } - catch (error) { - return false; - } - } - function schnorrVerifySync(signature, message, publicKey) { - try { - const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); - const e = schnorrChallengeFinalize(utils.taggedHashSync(TAGS.challenge, numTo32b(r), P.toRawX(), m)); - return finalizeSchnorrVerify(r, P, s, e); - } - catch (error) { - if (error instanceof ShaError) - throw error; - return false; - } - } - const schnorr = { - Signature: SchnorrSignature, - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - signSync: schnorrSignSync, - verifySync: schnorrVerifySync, - }; - Point.BASE._setWindowSize(8); - const crypto = { - node: nodeCrypto, - web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, - }; - const TAGS = { - challenge: 'BIP0340/challenge', - aux: 'BIP0340/aux', - nonce: 'BIP0340/nonce', - }; - const TAGGED_HASH_PREFIXES = {}; - const utils = { - bytesToHex, - hexToBytes, - concatBytes, - mod, - invert, - isValidPrivateKey(privateKey) { - try { - normalizePrivateKey(privateKey); - return true; - } - catch (error) { - return false; - } - }, - _bigintTo32Bytes: numTo32b, - _normalizePrivateKey: normalizePrivateKey, - hashToPrivateKey: (hash) => { - hash = ensureBytes(hash); - if (hash.length < 40 || hash.length > 1024) - throw new Error('Expected 40-1024 bytes of private key as per FIPS 186'); - const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n; - return numTo32b(num); - }, - randomBytes: (bytesLength = 32) => { - if (crypto.web) { - return crypto.web.getRandomValues(new Uint8Array(bytesLength)); - } - else if (crypto.node) { - const { randomBytes } = crypto.node; - return Uint8Array.from(randomBytes(bytesLength)); - } - else { - throw new Error("The environment doesn't have randomBytes function"); - } - }, - randomPrivateKey: () => { - return utils.hashToPrivateKey(utils.randomBytes(40)); - }, - sha256: async (...messages) => { - if (crypto.web) { - const buffer = await crypto.web.subtle.digest('SHA-256', concatBytes(...messages)); - return new Uint8Array(buffer); - } - else if (crypto.node) { - const { createHash } = crypto.node; - const hash = createHash('sha256'); - messages.forEach((m) => hash.update(m)); - return Uint8Array.from(hash.digest()); - } - else { - throw new Error("The environment doesn't have sha256 function"); - } - }, - hmacSha256: async (key, ...messages) => { - if (crypto.web) { - const ckey = await crypto.web.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); - const message = concatBytes(...messages); - const buffer = await crypto.web.subtle.sign('HMAC', ckey, message); - return new Uint8Array(buffer); - } - else if (crypto.node) { - const { createHmac } = crypto.node; - const hash = createHmac('sha256', key); - messages.forEach((m) => hash.update(m)); - return Uint8Array.from(hash.digest()); - } - else { - throw new Error("The environment doesn't have hmac-sha256 function"); - } - }, - sha256Sync: undefined, - hmacSha256Sync: undefined, - taggedHash: async (tag, ...messages) => { - let tagP = TAGGED_HASH_PREFIXES[tag]; - if (tagP === undefined) { - const tagH = await utils.sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))); - tagP = concatBytes(tagH, tagH); - TAGGED_HASH_PREFIXES[tag] = tagP; - } - return utils.sha256(tagP, ...messages); - }, - taggedHashSync: (tag, ...messages) => { - if (typeof _sha256Sync !== 'function') - throw new ShaError('sha256Sync is undefined, you need to set it'); - let tagP = TAGGED_HASH_PREFIXES[tag]; - if (tagP === undefined) { - const tagH = _sha256Sync(Uint8Array.from(tag, (c) => c.charCodeAt(0))); - tagP = concatBytes(tagH, tagH); - TAGGED_HASH_PREFIXES[tag] = tagP; - } - return _sha256Sync(tagP, ...messages); - }, - precompute(windowSize = 8, point = Point.BASE) { - const cached = point === Point.BASE ? point : new Point(point.x, point.y); - cached._setWindowSize(windowSize); - cached.multiply(_3n); - return cached; - }, - }; - Object.defineProperties(utils, { - sha256Sync: { - configurable: false, - get() { - return _sha256Sync; - }, - set(val) { - if (!_sha256Sync) - _sha256Sync = val; - }, - }, - hmacSha256Sync: { - configurable: false, - get() { - return _hmacSha256Sync; - }, - set(val) { - if (!_hmacSha256Sync) - _hmacSha256Sync = val; - }, - }, - }); - - exports.CURVE = CURVE; - exports.Point = Point; - exports.Signature = Signature; - exports.getPublicKey = getPublicKey; - exports.getSharedSecret = getSharedSecret; - exports.recoverPublicKey = recoverPublicKey; - exports.schnorr = schnorr; - exports.sign = sign; - exports.signSync = signSync; - exports.utils = utils; - exports.verify = verify; - - Object.defineProperty(exports, '__esModule', { value: true }); - -})); diff --git a/js/ui/util.js b/js/ui/util.js index 1b2ba8c..66c88ea 100644 --- a/js/ui/util.js +++ b/js/ui/util.js @@ -168,40 +168,16 @@ function update_notifications(model) { } async function get_pubkey(use_prompt=true) { - let pubkey = get_local_state('pubkey') - if (pubkey) - return pubkey - if (window.nostr && window.nostr.getPublicKey) { - log_debug("calling window.nostr.getPublicKey()...") - try { - pubkey = await window.nostr.getPublicKey() - return await handle_pubkey(pubkey) - } catch (err) { - return; - } - log_debug("got %s pubkey from nos2x", pubkey) - } - if (!use_prompt) + if (!(window.nostr && window.nostr.getPublicKey)) { + console.error("window.nostr.getPublicKey is unsupported"); + return; + } + try { + return await window.nostr.getPublicKey() + } catch (err) { + console.error(err); return; - pubkey = prompt("Enter Nostr ID (eg: jb55@jb55.com) or public key (hex or npub).") - if (!pubkey.trim()) - return; - return await handle_pubkey(pubkey) -} - -function get_privkey() { - let privkey = get_local_state('privkey') - if (privkey) - return privkey - if (!privkey) - privkey = prompt("Enter private key") - if (!privkey) - throw new Error("can't get privkey") - if (privkey[0] === "n") { - privkey = bech32_decode(privkey) } - set_local_state('privkey', privkey) - return privkey } function open_thread(thread_id) {