From: Chris Duncan Date: Fri, 24 Apr 2026 06:51:05 +0000 (-0700) Subject: Fix wallet signing to work with arbitrary strings like Tools. Update test vectors... X-Git-Tag: v0.12.0~3^2~1 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=9ce995e9504b0310b3064081137d75da3929f694;p=libnemo.git Fix wallet signing to work with arbitrary strings like Tools. Update test vectors and documentation accordingly. --- diff --git a/src/lib/wallet/index.ts b/src/lib/wallet/index.ts index 0f716f2..4df8ff6 100644 --- a/src/lib/wallet/index.ts +++ b/src/lib/wallet/index.ts @@ -330,8 +330,8 @@ export class Wallet { /** * Signs arbitrary strings using the private key of the account at the wallet * index specified and returns a detached signature as a hexadecimal string. - * For compatibility with other Nano tools, the data is first hashed to a - * 32-byte value using BLAKE2b. The wallet must be unlocked prior to signing. + * The data is treated as UTF-8 strings and is internally encoded as bytes + * accordingly. The wallet must be unlocked prior to signing. * * Special note: This method can be used to sign a 16-byte nonce with a Ledger * device. The actual message signed is a string which can be expressed as the @@ -346,7 +346,7 @@ 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 hashed and signed + * @param {(string|string[])} data - Arbitrary data to be signed */ async sign (index: number, data: string | string[]): Promise /** diff --git a/src/lib/wallet/sign.ts b/src/lib/wallet/sign.ts index 5254605..35f6609 100644 --- a/src/lib/wallet/sign.ts +++ b/src/lib/wallet/sign.ts @@ -3,7 +3,6 @@ import { Block } from '../block' import { bytes, hex, utf8 } from '../convert' -import { Blake2b } from '../crypto' import { Ledger } from '../ledger' import { Vault } from '../vault' import { Wallet } from '../wallet' @@ -21,12 +20,10 @@ export async function _signData (wallet: Wallet, vault: Vault, index: unknown, d if (wallet.type === 'Ledger') { return await Ledger.sign(index, message[0]) } - const hash = new Blake2b(32) - message.forEach(s => hash.update(utf8.toBytes(s))) const { signature } = await vault.request({ action: 'sign', index, - message: hash.digest().buffer + message: utf8.toBuffer(message.join('')) }) return bytes.toHex(new Uint8Array(signature)) } catch (err) { diff --git a/test/test.tools.mjs b/test/test.tools.mjs index efef90f..eb04b12 100644 --- a/test/test.tools.mjs +++ b/test/test.tools.mjs @@ -99,26 +99,31 @@ await Promise.all([ }), suite('signature tests', async () => { + const m = 'bug-libnemo@' + const n = 'codecow.com' await test('should sign data with a single parameter', async () => { - const result = Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, 'miro@metsanheimo.fi') - assert.equal(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C') + const result = Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, n) + assert.equal(result.toLowerCase(), '176469a6bea176bc060889225e2d35c484bee7bcfbe32658645de446236121fa2d2dd90e4c895c5fc3e7e9328752fb1e15195cea54964ef5cfe81a6a56dadb02') }) await test('should sign data with multiple parameters', async () => { - const result = Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, 'miro@metsanheimo.fi', 'somePassword') - assert.equal(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804') + const result = Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, m, n) + assert.equal(result.toLowerCase(), '0ceebbc0b9b3a270a30bad1eef4eddc0931effd8d5c0b7cab007fcc61f30d3ee9760cd93d7eeb5b654ecc0d9d17bc7a6d53bee54aa163a8272f425fb1184e30e') }) await test('should verify a signature using the public key', async () => { - const result = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') + const result = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, '176469a6bea176bc060889225e2d35c484bee7bcfbe32658645de446236121fa2d2dd90e4c895c5fc3e7e9328752fb1e15195cea54964ef5cfe81a6a56dadb02', n) assert.equal(result, true) - const result2 = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi') + const result2 = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, '176469a6bea176bc060889225e2d35c484bee7bcfbe32658645de446236121fa2d2dd90e4c895c5fc3e7e9328752fb1e15195cea54964ef5cfe81a6a56dadb02', m) assert.equal(result2, false) - const result3 = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') + const result3 = Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, '076469a6bea176bc060889225e2d35c484bee7bcfbe32658645de446236121fa2d2dd90e4c895c5fc3e7e9328752fb1e15195cea54964ef5cfe81a6a56dadb02', n) assert.equal(result3, false) + + const result4 = Tools.verify(NANO_TEST_VECTORS.PUBLIC_1, '176469a6bea176bc060889225e2d35c484bee7bcfbe32658645de446236121fa2d2dd90e4c895c5fc3e7e9328752fb1e15195cea54964ef5cfe81a6a56dadb02', n) + assert.equal(result4, false) }) await test('sweeper throws without required parameters', async () => {