+++ /dev/null
-//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>\r
-//! SPDX-License-Identifier: GPL-3.0-or-later\r
-\r
-import { Blake2b } from '.'\r
-\r
-/**\r
-* Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.\r
-* Public domain.\r
-*\r
-* Implementation derived from TweetNaCl version 20140427: http://tweetnacl.cr.yp.to/\r
-*\r
-* Modified to hash secret key to public key using BLAKE2b instead of SHA-512 per\r
-* Nano cryptocurrency specifications: https://docs.nano.org/integration-guides/the-basics/\r
-*\r
-* Original source commit: https://github.com/dchest/tweetnacl-js/blob/71df1d6a1d78236ca3e9f6c788786e21f5a651a6/nacl-fast.js\r
-*/\r
-export class NanoNaCl {\r
- static crypto_sign_BYTES: 64 = 64\r
- static crypto_sign_PUBLICKEYBYTES: 32 = 32\r
- static crypto_sign_PRIVATEKEYBYTES: 32 = 32\r
- static crypto_sign_SEEDBYTES: 32 = 32\r
- static D: Float64Array = new Float64Array([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203])\r
- static D2: Float64Array = new Float64Array([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406])\r
- static X: Float64Array = new Float64Array([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169])\r
- static Y: Float64Array = new Float64Array([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666])\r
- static I: Float64Array = new Float64Array([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83])\r
- static XY: Float64Array = new Float64Array([0xdd90, 0xa5b7, 0x8ab3, 0x6dde, 0x52f5, 0x7751, 0x9f80, 0x20f0, 0xe37d, 0x64ab, 0x4e8e, 0x66ea, 0x7665, 0xd78b, 0x5f0f, 0xe787])\r
-\r
- /**\r
- * Checks first 32 bytes of two byte arrays to see if they are equivalent.\r
- *\r
- * @returns 0 if first 32 bytes are equal, else 1 if there is at least one bit difference\r
- */\r
- static vn (x: Uint8Array, y: Uint8Array): number {\r
- let d: number = 0\r
- for (let i = 0; i < 32; i++) {\r
- d |= x[i] ^ y[i]\r
- }\r
- return ((1 & ((d - 1) >>> 8)) - 1) & 1\r
- }\r
-\r
- static pow2523 (out: Float64Array, i: Float64Array): void {\r
- const c: Float64Array = new Float64Array(16)\r
- c.set(i.subarray(0, 16), 0)\r
- for (let a = 0; a < 249; a++) {\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- }\r
- this.Square(c, c)\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- out.set(c, 0)\r
- }\r
-\r
- static car25519 (out: Float64Array): void {\r
- let v, c\r
- const s = 1 << 16\r
- c = 1\r
- for (let i = 0; i < 16; i++) {\r
- v = out[i] + c + s - 1\r
- out[i] = v % s\r
- c = (v / s) | 0\r
- }\r
- out[0] += 38 * (c - 1)\r
- }\r
-\r
- static inv25519 (out: Float64Array, i: Float64Array): void {\r
- const c: Float64Array = new Float64Array(16)\r
- c.set(i.subarray(0, 16), 0)\r
- for (let a = 0; a < 249; a++) {\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- }\r
- this.Square(c, c)\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- this.Square(c, c)\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- this.Square(c, c)\r
- this.Multiply(c, c, i)\r
- out.set(c, 0)\r
- }\r
-\r
- static neq25519 (a: Float64Array, b: Float64Array): number {\r
- const c: Uint8Array = new Uint8Array(32)\r
- const d: Uint8Array = new Uint8Array(32)\r
- this.pack25519(c, a)\r
- this.pack25519(d, b)\r
- return this.vn(c, d)\r
- }\r
-\r
- static pack25519 (out: Uint8Array, n: Float64Array): void {\r
- let b: number\r
- const m: Float64Array = new Float64Array(16)\r
- const t: Float64Array = new Float64Array(16)\r
- t.set(n, 0)\r
- this.car25519(t)\r
- this.car25519(t)\r
- this.car25519(t)\r
- for (let j = 0; j < 2; j++) {\r
- m[0] = t[0] - 0xffed\r
- for (let i = 1; i < 15; i++) {\r
- m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1)\r
- m[i - 1] &= 0xffff\r
- }\r
- m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1)\r
- b = (m[15] >> 16) & 1\r
- m[14] &= 0xffff\r
- this.sel25519(t, m, 1 - b)\r
- }\r
- for (let i = 0; i < 16; i++) {\r
- out[2 * i] = t[i] & 0xff\r
- out[2 * i + 1] = t[i] >> 8\r
- }\r
- }\r
-\r
- static par25519 (a: Float64Array): 0 | 1 {\r
- const d: Uint8Array = new Uint8Array(32)\r
- this.pack25519(d, a)\r
- return (d[0] & 1) as 0 | 1\r
- }\r
-\r
- static sel25519 (p: Float64Array, q: Float64Array, b: number): void {\r
- let t\r
- const c = ~(b - 1)\r
- for (let i = 0; i < 16; i++) {\r
- t = c & (p[i] ^ q[i])\r
- p[i] ^= t\r
- q[i] ^= t\r
- }\r
- }\r
-\r
- static unpack25519 (out: Float64Array, n: Uint8Array): void {\r
- for (let i = 0; i < 16; i++) {\r
- out[i] = n[2 * i] + (n[2 * i + 1] << 8)\r
- }\r
- out[15] &= (1 << 15) - 1\r
- }\r
-\r
- static Add (out: Float64Array, a: Float64Array, b: Float64Array): void {\r
- for (let i = 0; i < 16; i++) {\r
- out[i] = a[i] + b[i]\r
- }\r
- }\r
-\r
- static Subtract (out: Float64Array, a: Float64Array, b: Float64Array): void {\r
- for (let i = 0; i < 16; i++) {\r
- out[i] = a[i] - b[i]\r
- }\r
- }\r
-\r
- static Multiply (out: Float64Array, a: Float64Array, b: Float64Array): void {\r
- let v, c\r
- const s = 1 << 16\r
- const t = new Float64Array(31)\r
- t.fill(0)\r
-\r
- // init t values\r
- for (let i = 0; i < 16; i++) {\r
- for (let j = 0; j < 16; j++) {\r
- t[i + j] += a[i] * b[j]\r
- }\r
- }\r
-\r
- for (let i = 0; i < 15; i++) {\r
- t[i] += 38 * t[i + 16]\r
- }\r
- // t15 left as is\r
-\r
- // first carry\r
- c = 0\r
- for (let i = 0; i < 16; i++) {\r
- v = t[i] + c\r
- t[i] = v % s\r
- c = (v / s) | 0\r
- }\r
- t[0] += 38 * c\r
-\r
- // second carry\r
- c = 0\r
- for (let i = 0; i < 16; i++) {\r
- v = t[i] + c\r
- t[i] = v % s\r
- c = (v / s) | 0\r
- }\r
- t[0] += 38 * c\r
-\r
- // assign result to output\r
- out.set(t.slice(0, 16), 0)\r
- }\r
-\r
- static Square (out: Float64Array, a: Float64Array): void {\r
- let v, c\r
- const s = 1 << 16\r
- const t = new Float64Array(31)\r
- t.fill(0)\r
-\r
- // init t values, same as Multiply except we can skip some iterations of\r
- // the inner loop since a[x]*a[y] + a[y]*a[x] = 2*a[x]*a[y]\r
- for (let i = 0; i < 16; i++) {\r
- for (let j = i; j < 16; j++) {\r
- //@ts-expect-error\r
- t[i + j] += a[i] * a[j] * ((i < j) + 1)\r
- }\r
- }\r
-\r
- for (let i = 0; i < 15; i++) {\r
- t[i] += 38 * t[i + 16]\r
- }\r
- // t15 left as is\r
-\r
- // first carry\r
- c = 0\r
- for (let i = 0; i < 16; i++) {\r
- v = t[i] + c\r
- t[i] = v % s\r
- c = (v / s) | 0\r
- }\r
- t[0] += 38 * c\r
-\r
- // second carry\r
- c = 0\r
- for (let i = 0; i < 16; i++) {\r
- v = t[i] + c\r
- t[i] = v % s\r
- c = (v / s) | 0\r
- }\r
- t[0] += 38 * c\r
-\r
- // assign result to output\r
- out.set(t.slice(0, 16), 0)\r
- }\r
-\r
- static add (p: Float64Array[], q: Float64Array[]): void {\r
- const a: Float64Array = new Float64Array(16)\r
- const b: Float64Array = new Float64Array(16)\r
- const c: Float64Array = new Float64Array(16)\r
- const d: Float64Array = new Float64Array(16)\r
- const e: Float64Array = new Float64Array(16)\r
- const f: Float64Array = new Float64Array(16)\r
- const g: Float64Array = new Float64Array(16)\r
- const h: Float64Array = new Float64Array(16)\r
- const t: Float64Array = new Float64Array(16)\r
-\r
- this.Subtract(a, p[1], p[0])\r
- this.Subtract(t, q[1], q[0])\r
- this.Multiply(a, a, t)\r
- this.Add(b, p[0], p[1])\r
- this.Add(t, q[0], q[1])\r
- this.Multiply(b, b, t)\r
- this.Multiply(c, p[3], q[3])\r
- this.Multiply(c, c, this.D2)\r
- this.Multiply(d, p[2], q[2])\r
- this.Add(d, d, d)\r
- this.Subtract(e, b, a)\r
- this.Subtract(f, d, c)\r
- this.Add(g, d, c)\r
- this.Add(h, b, a)\r
-\r
- this.Multiply(p[0], e, f)\r
- this.Multiply(p[1], h, g)\r
- this.Multiply(p[2], g, f)\r
- this.Multiply(p[3], e, h)\r
- }\r
-\r
- static cswap (p: Float64Array[], q: Float64Array[], b: number): void {\r
- for (let i = 0; i < 4; i++) {\r
- this.sel25519(p[i], q[i], b)\r
- }\r
- }\r
-\r
- static pack (r: Uint8Array, p: Float64Array[]): void {\r
- const tx: Float64Array = new Float64Array(16)\r
- const ty: Float64Array = new Float64Array(16)\r
- const zi: Float64Array = new Float64Array(16)\r
- this.inv25519(zi, p[2])\r
- this.Multiply(tx, p[0], zi)\r
- this.Multiply(ty, p[1], zi)\r
- this.pack25519(r, ty)\r
- r[31] ^= this.par25519(tx) << 7\r
- }\r
-\r
- static scalarmult (p: Float64Array[], q: Float64Array[], s: Uint8Array): void {\r
- p[0].fill(0)\r
- p[1].fill(0).set([1], 0)\r
- p[2].fill(0).set([1], 0)\r
- p[3].fill(0)\r
- for (let i = 255; i >= 0; --i) {\r
- const b = (s[(i / 8) | 0] >> (i & 7)) & 1\r
- this.cswap(p, q, b)\r
- this.add(q, p)\r
- this.add(p, p)\r
- this.cswap(p, q, b)\r
- }\r
- }\r
-\r
- static scalarbase (p: Float64Array[], s: Uint8Array): void {\r
- const q: Float64Array[] = [new Float64Array(16), new Float64Array(16), new Float64Array(16), new Float64Array(16)]\r
- q[0].set(this.X, 0)\r
- q[1].set(this.Y, 0)\r
- q[2].set([1], 0)\r
- q[3].set(this.XY, 0)\r
- this.scalarmult(p, q, s)\r
- }\r
-\r
- static L = new Float64Array([\r
- 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,\r
- 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10\r
- ])\r
-\r
- static modL (r: Uint8Array, x: Float64Array): void {\r
- let c, t, v\r
- for (let i = 63; i >= 32; --i) {\r
- c = 0\r
- for (let j = i - 32, k = i - 12; j < k; j++) {\r
- t = 16 * x[i] * this.L[j - (i - 32)]\r
- v = x[j] + c - t\r
- c = ((v + 128) / 256) | 0\r
- x[j] = v - (c * 256)\r
- }\r
- x[i - 12] += c\r
- x[i] = 0\r
- }\r
- c = 0\r
- for (let j = 0; j < 32; j++) {\r
- x[j] += c - (x[31] >> 4) * this.L[j]\r
- c = x[j] >> 8\r
- x[j] &= 255\r
- }\r
- for (let j = 0; j < 32; j++) {\r
- x[j] -= c * this.L[j]\r
- }\r
- for (let i = 0; i < 32; i++) {\r
- x[i + 1] += x[i] >> 8\r
- r[i] = x[i] & 255\r
- }\r
- }\r
-\r
- static reduce (r: Uint8Array): void {\r
- let x = new Float64Array(64)\r
- x.set(r, 0)\r
- r.fill(0)\r
- this.modL(r, x)\r
- }\r
-\r
- static unpackneg (r: Float64Array[], p: Uint8Array): number {\r
- const t: Float64Array = new Float64Array(16)\r
- const chk: Float64Array = new Float64Array(16)\r
- const num: Float64Array = new Float64Array(16)\r
- const den: Float64Array = new Float64Array(16)\r
- const den2: Float64Array = new Float64Array(16)\r
- const den4: Float64Array = new Float64Array(16)\r
- const den6: Float64Array = new Float64Array(16)\r
-\r
- r[2].fill(0).set([1], 0)\r
- this.unpack25519(r[1], p)\r
- this.Square(num, r[1])\r
- this.Multiply(den, num, this.D)\r
- this.Subtract(num, num, r[2])\r
- this.Add(den, r[2], den)\r
-\r
- this.Square(den2, den)\r
- this.Square(den4, den2)\r
- this.Multiply(den6, den4, den2)\r
- this.Multiply(t, den6, num)\r
- this.Multiply(t, t, den)\r
-\r
- this.pow2523(t, t)\r
- this.Multiply(t, t, num)\r
- this.Multiply(t, t, den)\r
- this.Multiply(t, t, den)\r
- this.Multiply(r[0], t, den)\r
-\r
- this.Square(chk, r[0])\r
- this.Multiply(chk, chk, den)\r
-\r
- // if neq is true, multiply r[0] by I, else multiply by 1 for a no-op\r
- let neq = this.neq25519(chk, num)\r
- const I = new Float64Array(this.I)\r
- for (let i = 0; i < 16; i++) {\r
- I[i] *= neq\r
- }\r
- I[0] += neq ^ 1\r
- this.Multiply(r[0], r[0], I)\r
-\r
- this.Square(chk, r[0])\r
- this.Multiply(chk, chk, den)\r
-\r
- neq = 0 - this.neq25519(chk, num)\r
-\r
- // if par25519, subtract r[0] from 0 to swap sign, else keep current values\r
- //@ts-expect-error\r
- const par = (this.par25519(r[0]) === p[31] >> 7) ^ 1\r
- for (let i = 0; i < 16; i++) {\r
- r[0][i] = (2 * par * r[0][i]) - r[0][i]\r
- }\r
- this.Multiply(r[3], r[0], r[1])\r
- return neq\r
- }\r
-\r
- static crypto_sign (sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array, pk: Uint8Array): void {\r
- const p: Float64Array[] = [new Float64Array(16), new Float64Array(16), new Float64Array(16), new Float64Array(16)]\r
-\r
- const d = new Blake2b(64).update(sk).digest()\r
- d[0] &= 248\r
- d[31] &= 127\r
- d[31] |= 64\r
-\r
- sm.set(m.subarray(0, n), 64)\r
- sm.set(d.subarray(32, 64), 32)\r
-\r
- const r = new Blake2b(64).update(sm.subarray(32)).digest()\r
- this.reduce(r)\r
- this.scalarbase(p, r)\r
- this.pack(sm, p)\r
-\r
- sm.set(pk, 32)\r
- const h = new Blake2b(64).update(sm).digest()\r
- this.reduce(h)\r
-\r
- const x = new Float64Array(64)\r
- x.set(r.subarray(0, 32))\r
- for (let i = 0; i < 32; i++) {\r
- for (let j = 0; j < 32; j++) {\r
- x[i + j] += h[i] * d[j]\r
- }\r
- }\r
-\r
- this.modL(sm.subarray(32), x)\r
- }\r
-\r
- static crypto_sign_open (m: Uint8Array, sm: Uint8Array, n: number, pk: Uint8Array): number {\r
- const t = new Uint8Array(32)\r
- const p: Float64Array[] = [new Float64Array(16), new Float64Array(16), new Float64Array(16), new Float64Array(16)]\r
- const q: Float64Array[] = [new Float64Array(16), new Float64Array(16), new Float64Array(16), new Float64Array(16)]\r
-\r
- // eventually used in returned result but allow processing to continue\r
- const neg = this.unpackneg(q, pk) & 1\r
-\r
- m.set(sm.subarray(0, n), 0)\r
- m.set(pk.subarray(0, 32), 32)\r
- const h = new Blake2b(64).update(m).digest()\r
- this.reduce(h)\r
- this.scalarmult(p, q, h)\r
-\r
- this.scalarbase(q, sm.subarray(32))\r
- this.add(p, q)\r
- this.pack(t, p)\r
-\r
- n -= 64\r
-\r
- // if any bits unequal, zero out and return -1\r
- const vn = this.vn(sm, t) ^ 1\r
- for (let i = 0; i < n; i++) {\r
- m[i] = sm[i + 64] * vn\r
- }\r
- n = (n * vn) - (vn ^ 1)\r
- return (n * (neg ^ 1)) - neg\r
- }\r
-\r
- /**\r
- * Derives a public key from a private key "seed".\r
- *\r
- * @param {Uint8Array<ArrayBuffer>} seed - 32-byte private key\r
- * @returns {Uint8Array<ArrayBuffer>} 32-byte public key\r
- */\r
- static convert (seed: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>\r
- static convert (seed: unknown): Uint8Array<ArrayBuffer> {\r
- try {\r
- if (!(seed instanceof Uint8Array)) {\r
- throw new TypeError('Seed must be Uint8Array')\r
- }\r
- if (seed.byteLength !== this.crypto_sign_SEEDBYTES) {\r
- throw new Error(`Seed must be ${this.crypto_sign_SEEDBYTES} bytes`)\r
- }\r
- const s = new Uint8Array(seed)\r
- seed = undefined\r
- const pk = new Uint8Array(this.crypto_sign_PUBLICKEYBYTES)\r
- const p: Float64Array[] = [new Float64Array(16), new Float64Array(16), new Float64Array(16), new Float64Array(16)]\r
-\r
- const hash = new Blake2b(64).update(s).digest()\r
- hash[0] &= 248\r
- hash[31] &= 127\r
- hash[31] |= 64\r
-\r
- this.scalarbase(p, hash)\r
- this.pack(pk, p)\r
-\r
- return pk\r
- } catch (err) {\r
- throw new Error('Failed to convert seed to public key', { cause: err })\r
- }\r
- }\r
-\r
- /**\r
- * Signs the message using the secret key and returns a signature.\r
- *\r
- * @param {Uint8Array<ArrayBuffer>} message - Message to sign\r
- * @param {Uint8Array<ArrayBuffer>} privateKey - 32-byte key to use for signing\r
- * @returns {Uint8Array<ArrayBuffer>} 64-byte signature\r
- */\r
- static detached (message: Uint8Array<ArrayBuffer>, privateKey: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>\r
- static detached (message: unknown, privateKey: unknown): Uint8Array<ArrayBuffer> {\r
- try {\r
- const sm = this.sign(message as Uint8Array<ArrayBuffer>, privateKey as Uint8Array<ArrayBuffer>)\r
- return new Uint8Array(sm.buffer.slice(0, this.crypto_sign_BYTES))\r
- } catch (err) {\r
- throw new Error('Failed to sign and return signature', { cause: err })\r
- }\r
- }\r
-\r
- /**\r
- * Verifies the signed message and returns the message without signature.\r
- *\r
- * @param {Uint8Array<ArrayBuffer>} signedMessage - Signed message\r
- * @param {Uint8Array<ArrayBuffer>} publicKey - 32-byte key used to sign message\r
- * @returns {Uint8Array<ArrayBuffer>} Message without signature\r
- */\r
- static open (signedMessage: Uint8Array<ArrayBuffer>, publicKey: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>\r
- static open (signedMessage: unknown, publicKey: unknown): Uint8Array<ArrayBuffer> {\r
- try {\r
- if (!(signedMessage instanceof Uint8Array) || signedMessage.byteLength < this.crypto_sign_BYTES) {\r
- throw new TypeError('Signed message must be Uint8Array')\r
- }\r
- if (!(publicKey instanceof Uint8Array) || publicKey.byteLength !== this.crypto_sign_PUBLICKEYBYTES) {\r
- throw new Error(`Public key must be ${this.crypto_sign_PUBLICKEYBYTES}-byte Uint8Array`)\r
- }\r
- const sm = new Uint8Array(signedMessage)\r
- const smLen = sm.byteLength\r
- const pub = new Uint8Array(publicKey)\r
- const tmp = new Uint8Array(smLen)\r
- const mLen = this.crypto_sign_open(tmp, sm, smLen, pub)\r
- if (mLen < 0) {\r
- throw new Error('Signature verification failed')\r
- }\r
- const m = new Uint8Array(mLen)\r
- m.set(tmp.subarray(0, mLen), 0)\r
- return m\r
- } catch (err) {\r
- throw new Error('Failed to open message', { cause: err })\r
- }\r
- }\r
-\r
- /**\r
- * Signs the message using the secret key and returns a signed message.\r
- *\r
- * @param {Uint8Array<ArrayBuffer>} message - Message to be signed\r
- * @param {Uint8Array<ArrayBuffer>} privateKey - 32-byte key to use for signing\r
- * @returns {Uint8Array<ArrayBuffer>} Signed message\r
- */\r
- static sign (message: Uint8Array<ArrayBuffer>, privateKey: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>\r
- static sign (message: unknown, privateKey: unknown): Uint8Array<ArrayBuffer> {\r
- try {\r
- if (!(message instanceof Uint8Array)) {\r
- throw new TypeError('Message must be Uint8Array')\r
- }\r
- if (!(privateKey instanceof Uint8Array) || privateKey.byteLength !== this.crypto_sign_SEEDBYTES) {\r
- throw new Error(`Private key must be ${this.crypto_sign_PRIVATEKEYBYTES}-byte Uint8Array`)\r
- }\r
- const prv = new Uint8Array(privateKey)\r
- privateKey = undefined\r
- const mLen = message.byteLength\r
- const msg = new Uint8Array(message)\r
- const signed = new Uint8Array(this.crypto_sign_BYTES + mLen)\r
- const pub = this.convert(prv)\r
- this.crypto_sign(signed, msg, mLen, prv, pub)\r
- return signed\r
- } catch (err) {\r
- throw new Error('Failed to sign and return message', { cause: err })\r
- }\r
- }\r
-\r
- /**\r
- * Verifies a detached signature for a message.\r
- *\r
- * @param {Uint8Array<ArrayBuffer>} signedMessage - Signed message\r
- * @param {Uint8Array<ArrayBuffer>} signature - 64-byte signature\r
- * @param {Uint8Array<ArrayBuffer>} publicKey - 32-byte key used for signing\r
- * @returns {boolean} - True if `publicKey` was used to sign `msg` and generate `sig`, else false\r
- */\r
- static verify (signedMessage: Uint8Array<ArrayBuffer>, signature: Uint8Array<ArrayBuffer>, publicKey: Uint8Array<ArrayBuffer>): boolean\r
- static verify (signedMessage: unknown, signature: unknown, publicKey: unknown): boolean {\r
- try {\r
- if (!(signedMessage instanceof Uint8Array)) {\r
- throw new TypeError('Signed message must be Uint8Array')\r
- }\r
- if (!(signature instanceof Uint8Array) || signature.byteLength !== this.crypto_sign_BYTES) {\r
- throw new Error(`Signature must be ${this.crypto_sign_BYTES}-byte Uint8Array`)\r
- }\r
- if (!(publicKey instanceof Uint8Array) || publicKey.byteLength !== this.crypto_sign_PUBLICKEYBYTES) {\r
- throw new Error(`Public key must be ${this.crypto_sign_PUBLICKEYBYTES}-byte Uint8Array`)\r
- }\r
- const msg = new Uint8Array(signedMessage)\r
- const sig = new Uint8Array(signature)\r
- const pub = new Uint8Array(publicKey)\r
- const smLen = this.crypto_sign_BYTES + msg.byteLength\r
- const sm = new Uint8Array(smLen)\r
- const m = new Uint8Array(smLen)\r
- sm.set(sig, 0)\r
- sm.set(msg, this.crypto_sign_BYTES)\r
- return (this.crypto_sign_open(m, sm, smLen, pub) >= 0)\r
- } catch (err) {\r
- throw new Error('Failed to verify signature on message with the given public key', { cause: err })\r
- }\r
- }\r
-}\r