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) {