From 3060994b7264998050145d2ae87f2f843262a776 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 28 Sep 2023 14:03:15 -0400 Subject: [PATCH] 6344 - normalize v on recover (#6462) * recover function accepts both v < 27 and v>= 27 * update changelog * update linter --- packages/web3-eth-accounts/CHANGELOG.md | 6 +++++- packages/web3-eth-accounts/src/account.ts | 7 +++++-- packages/web3-eth-accounts/test/fixtures/account.ts | 5 +++++ packages/web3-eth-accounts/test/unit/account.test.ts | 7 +++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 9c11ba18dd4..1c3a8291f2e 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -137,4 +137,8 @@ Documentation: - Fixed "The `r` and `s` returned by `sign` to does not always consist of 64 characters" (#6411) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- Fixed `recover` function, `v` will be normalized to value 0,1 (#6344) \ No newline at end of file diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index 4a3deec6dd5..bb07577cd52 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -341,10 +341,13 @@ export const recover = ( const V_INDEX = 130; // r = first 32 bytes, s = second 32 bytes, v = last byte of signature const hashedMessage = prefixedOrR ? data : hashMessage(data); - const v = signatureOrV.substring(V_INDEX); // 0x + r + s + v + let v = parseInt(signatureOrV.substring(V_INDEX),16); // 0x + r + s + v + if (v > 26) { + v -= 27; + } const ecPublicKey = secp256k1.Signature.fromCompact(signatureOrV.slice(2, V_INDEX)) - .addRecoveryBit(parseInt(v, 16) - 27) + .addRecoveryBit(v) .recoverPublicKey(hashedMessage.replace('0x', '')) .toRawBytes(false); diff --git a/packages/web3-eth-accounts/test/fixtures/account.ts b/packages/web3-eth-accounts/test/fixtures/account.ts index 4638b6e2717..6e64595c28b 100644 --- a/packages/web3-eth-accounts/test/fixtures/account.ts +++ b/packages/web3-eth-accounts/test/fixtures/account.ts @@ -381,6 +381,11 @@ export const invalidEncryptData: [ ], ]; +export const validRecover: [string, string][] = [ + [ "I hereby confirm that I am the sole beneficial owner of the assets involved in the business relationship with Fiat24. \nI hereby undertake to inform Fiat24 proactively of any changes to the information contained herein.", "0xec4f73260ac14882e65995a09359896a0ae8f16bd0d28b0d9171655b4e85271e07cda040be059fdcbf52709e3c993eb50a89ce33f41617dc090dc80a583e3c4f00",], // v < 27 + ["test", "0xefb42c22baa0143b322e93b24b0903a0ef47a64b716fbb77debbea55a93dec3e4417aff7dce845723240916c6e34cf17c674828b3addfb0afad966334df5b6311b"] // v >= 27 +] + export const invalidKeyStore: [[any, string]][] = [ [ // invalid keystore error, missing id field diff --git a/packages/web3-eth-accounts/test/unit/account.test.ts b/packages/web3-eth-accounts/test/unit/account.test.ts index b2614137a0d..1f61b74c5f7 100644 --- a/packages/web3-eth-accounts/test/unit/account.test.ts +++ b/packages/web3-eth-accounts/test/unit/account.test.ts @@ -42,6 +42,7 @@ import { validHashMessageData, validPrivateKeytoAccountData, validPrivateKeyToAddressData, + validRecover, } from '../fixtures/account'; import { TransactionFactory } from '../../src/tx/transactionFactory'; import { TxData } from '../../src/tx/types'; @@ -215,5 +216,11 @@ describe('accounts', () => { await expect(result).rejects.toThrow(Web3ValidatorError); }); }); + + describe('valid signatures for recover', () => { + it.each(validRecover)('&s', (data, signature) => { + recover(data, signature) + }) + }) }); });