From: Chris Duncan Date: Fri, 1 May 2026 06:26:49 +0000 (-0700) Subject: Update signing of arbitrary data to accept it as a single string instead of a rest... X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=841e197b228569ffe8bebef5c746925c9fdb40fc;p=libnemo.git Update signing of arbitrary data to accept it as a single string instead of a rest parameter. --- diff --git a/src/lib/ledger.ts b/src/lib/ledger.ts index 2e51d7c..72fd3b6 100644 --- a/src/lib/ledger.ts +++ b/src/lib/ledger.ts @@ -284,7 +284,7 @@ export class Ledger { throw new Error('Signing with ledger failed', { cause: status }) } if (data instanceof Block && hash !== data.hash) { - throw new Error('Hash from ledger does not match hash from block', { cause: `${hash} | ${data.hash}` }) + throw new Error('Hash from Ledger does not match hash from block', { cause: `${hash} | ${data.hash}` }) } if (signature == null) { throw new Error('Ledger silently failed to return signature') diff --git a/src/lib/rolodex.ts b/src/lib/rolodex.ts index 1b8d00a..147f630 100644 --- a/src/lib/rolodex.ts +++ b/src/lib/rolodex.ts @@ -175,18 +175,18 @@ export class Rolodex { /** * Verifies whether the public key of any Nano address saved under a specific - * name in the rolodex was used to sign a specific set of data. + * name in the rolodex was used to sign a specific string. * * @param {string} name - Alias to look up * @param {string} signature - Signature to use for verification - * @param {...string} data - Signed data to verify + * @param {string} data - Signed data to verify * @returns {Promise} True if the signature was used to sign the data, else false */ - static async verify (name: string, signature: string, ...data: string[]): Promise { + static async verify (name: string, signature: string, data: string): Promise { const addresses = await this.getAddresses(name) for (const address of addresses) { const { publicKey } = new Account(address) - const verified = await Tools.verify(publicKey, signature, ...data) + const verified = await Tools.verify(publicKey, signature, data) if (verified) { return true } diff --git a/src/lib/tools.ts b/src/lib/tools.ts index dc55b3b..e95f0c5 100644 --- a/src/lib/tools.ts +++ b/src/lib/tools.ts @@ -138,14 +138,14 @@ export class Tools { } /** - * Concatenates and signs an arbitrary set of strings with a secret key using - * nano25519. The input data can be up to 32 KiB in total. + * Signs an arbitrary string with a secret key using nano25519. The input data + * is encoded as UTF-8 and can be up to 32 KiB in total. * * @param {(string | ArrayBuffer | Uint8Array)} secretKey - 64-byte secret key - * @param {...string[]} input - Data to be concatenated and then signed + * @param {string} input - Data to be signed * @returns {string} 64-byte hexadecimal signature */ - static sign (secretKey: string | ArrayBuffer | Uint8Array, ...input: string[]): string { + static sign (secretKey: string | ArrayBuffer | Uint8Array, input: string): string { if (navigator.userActivation?.isActive === false) { throw new DOMException( 'Signing request was blocked due to lack of user activation', @@ -154,7 +154,7 @@ export class Tools { } const k = this.#normalize(secretKey) try { - const signature = nano25519_sign(utf8.toBytes(input.join('')), k) + const signature = nano25519_sign(utf8.toBytes(input), k) return bytes.toHex(signature) } catch (err) { throw new Error(`Failed to sign message`, { cause: err }) @@ -222,18 +222,18 @@ export class Tools { } /** - * Verifies the signature of arbitrary strings using a public key. + * Verifies the signature of an arbitrary string using a public key. * * @param {(string | ArrayBuffer | Uint8Array)} publicKey - 32-byte hexadecimal public key * @param {(string | ArrayBuffer | Uint8Array)} signature - 128-character hexadcimal signature - * @param {...string} input - Data to be verified + * @param {string} input - Data to be verified * @returns {boolean} True if the data was signed by the public key's matching private key */ - static verify (publicKey: string | ArrayBuffer | Uint8Array, signature: string | ArrayBuffer | Uint8Array, ...input: string[]): boolean { + static verify (publicKey: string | ArrayBuffer | Uint8Array, signature: string | ArrayBuffer | Uint8Array, input: string): boolean { const k = this.#normalize(publicKey) const s = this.#normalize(signature) try { - return nano25519_verify(s, utf8.toBytes(input.join('')), k) + return nano25519_verify(s, utf8.toBytes(input), k) } catch (err) { throw new Error('Failed to verify signature', { cause: err }) } diff --git a/src/lib/wallet/index.ts b/src/lib/wallet/index.ts index ebb999e..ab4e015 100644 --- a/src/lib/wallet/index.ts +++ b/src/lib/wallet/index.ts @@ -348,10 +348,10 @@ export class Wallet { * Plan for this eventuality if you implement this method to sign nonces. * * @param {number} index - Account to use for signing - * @param {(string|string[])} data - Arbitrary data to be signed + * @param {string} data - Arbitrary data to be signed * @returns {Promise} 128-character hexadecimal detached signature */ - async sign (index: number, data: string | string[]): Promise + async sign (index: number, data: string): Promise /** * Signs a block using the private key of the account at the wallet index * specified. The signature is appended to the signature field of the block, @@ -369,13 +369,15 @@ export class Wallet { * is returned to allow chaining with other Block functions. The wallet must be * unlocked prior to signing. * + * See documentation on the class method `Ledger.sign()` for more information. + * * @param {number} index - Account to use for signing * @param {Block} block - Block data to be hashed and signed * @param {Block} [frontier] - Previous block data to be cached by Ledger wallet * @returns {Promise} Block with signature */ async sign (index: number, block: Block, frontier?: Block): Promise - async sign (index: number, data: string | string[] | Block, frontier?: Block): Promise { + async sign (index: number, data: string | Block, frontier?: Block): Promise { const { address } = await this.account(index) return data instanceof Block ? _signBlock(this, this.#vault, index, address, data, frontier) diff --git a/src/lib/wallet/sign.ts b/src/lib/wallet/sign.ts index cf5ee23..9a69cb0 100644 --- a/src/lib/wallet/sign.ts +++ b/src/lib/wallet/sign.ts @@ -51,7 +51,7 @@ export async function _signBlock (wallet: Wallet, vault: Vault, index: unknown, } } -export async function _signData (wallet: Wallet, vault: Vault, index: number, address: string, data: string | string[]): Promise +export async function _signData (wallet: Wallet, vault: Vault, index: number, address: string, data: string): Promise export async function _signData (wallet: Wallet, vault: Vault, index: unknown, address: unknown, data: unknown): Promise { try { if (typeof index !== 'number') { @@ -60,12 +60,11 @@ export async function _signData (wallet: Wallet, vault: Vault, index: unknown, a if (typeof address !== 'string') { throw new TypeError('Address must be a string', { cause: address }) } - const message = Array.isArray(data) ? data : [data] - if (message.some(s => typeof s !== 'string')) { - throw new TypeError('Data to sign must be strings', { cause: data }) + if (typeof data !== 'string') { + throw new TypeError('Data to sign must be a string', { cause: data }) } if (wallet.type === 'Ledger') { - return await Ledger.sign(index, message[0]) + return Ledger.sign(index, data) } if (navigator.userActivation?.isActive === false) { throw new DOMException( @@ -76,7 +75,7 @@ export async function _signData (wallet: Wallet, vault: Vault, index: unknown, a const { signature } = await vault.request({ action: 'sign', index, - message: utf8.toBuffer(message.join('')) + message: utf8.toBuffer(data) }) return bytes.toHex(new Uint8Array(signature)) } catch (err) {