Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit f2ac320

Browse files
authored
Merge pull request #2929 from chirag-parmar/2.x
Length check and formatting private key in accounts.privateKeyToAccount method
2 parents 9136975 + 183fd68 commit f2ac320

File tree

3 files changed

+43
-19
lines changed

3 files changed

+43
-19
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6363

6464
## [2.0.0-alpha.1]
6565

66+
### Added
67+
68+
- Length check of the PK added to the ``fromPrivateKey`` method of the ``Account`` model (#2928)
69+
6670
### Fixed
6771

6872
- miner.startMining fixed (#2877)

packages/web3-eth-accounts/src/models/Account.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ export default class Account {
123123
* @returns {Account}
124124
*/
125125
static fromPrivateKey(privateKey, accounts = {}) {
126+
if (!privateKey.startsWith('0x')) {
127+
privateKey = '0x' + privateKey;
128+
}
129+
130+
// 64 hex characters + hex-prefix
131+
if (privateKey.length !== 66) {
132+
throw new Error("Private key must be 32 bytes long");
133+
}
134+
126135
return new Account(EthLibAccount.fromPrivate(privateKey), accounts);
127136
}
128137

packages/web3-eth-accounts/tests/src/models/AccountTest.js

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ jest.mock('../../../src/Accounts');
2525
* AccountTest test
2626
*/
2727
describe('AccountTest', () => {
28-
let account, accountsMock, transactionSignerMock;
28+
let account, accountsMock, transactionSignerMock, mockKey;
2929

3030
beforeEach(() => {
31+
mockKey = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
3132
transactionSignerMock = new TransactionSigner();
3233

3334
new Accounts();
@@ -55,6 +56,20 @@ describe('AccountTest', () => {
5556
expect(accountsMock.signTransaction).toHaveBeenCalledWith({}, 'pk', callback);
5657
});
5758

59+
it('calls fromPrivateKey with incorrect private key length and throws error', () => {
60+
expect(() => {
61+
Account.fromPrivateKey('asdfasdf')
62+
}).toThrow('Private key must be 32 bytes long');
63+
});
64+
65+
it('calls fromPrivateKey with incorrect private key prefix and throws error', () => {
66+
mockKey = '0z0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
67+
68+
expect(() => {
69+
Account.fromPrivateKey(mockKey)
70+
}).toThrow('Private key must be 32 bytes long');
71+
});
72+
5873
it('calls sign with non-strict hex and returns the expected string', () => {
5974
isHexStrict.mockReturnValue(false);
6075

@@ -152,17 +167,15 @@ describe('AccountTest', () => {
152167
final: jest.fn()
153168
};
154169

155-
decipher.update.mockReturnValueOnce(Buffer.from('0'));
170+
decipher.update.mockReturnValueOnce(Buffer.from(mockKey.slice(2,34), 'hex'));
156171

157-
decipher.final.mockReturnValueOnce(Buffer.from('0'));
172+
decipher.final.mockReturnValueOnce(Buffer.from(mockKey.slice(34,66), 'hex'));
158173

159174
createDecipheriv.mockReturnValueOnce(decipher);
160175

161176
expect(Account.fromV3Keystore(json, 'password', false)).toBeInstanceOf(Account);
162177

163-
expect(fromPrivate).toHaveBeenLastCalledWith(
164-
`0x${Buffer.concat([Buffer.from('0'), Buffer.from('0')]).toString('hex')}`
165-
);
178+
expect(fromPrivate).toHaveBeenLastCalledWith(mockKey);
166179

167180
expect(scrypt).toHaveBeenCalledWith(
168181
Buffer.from('password'),
@@ -220,19 +233,17 @@ describe('AccountTest', () => {
220233
final: jest.fn()
221234
};
222235

223-
decipher.update.mockReturnValueOnce(Buffer.from('0'));
236+
decipher.update.mockReturnValueOnce(Buffer.from(mockKey.slice(2,34), 'hex'));
224237

225-
decipher.final.mockReturnValueOnce(Buffer.from('0'));
238+
decipher.final.mockReturnValueOnce(Buffer.from(mockKey.slice(34,66), 'hex'));
226239

227240
createDecipheriv.mockReturnValueOnce(decipher);
228241

229242
pbkdf2Sync.mockReturnValueOnce(Buffer.from('00000000000000000000000000000000'));
230243

231244
expect(Account.fromV3Keystore(json, 'password', false)).toBeInstanceOf(Account);
232245

233-
expect(fromPrivate).toHaveBeenCalledWith(
234-
`0x${Buffer.concat([Buffer.from('0'), Buffer.from('0')]).toString('hex')}`
235-
);
246+
expect(fromPrivate).toHaveBeenCalledWith(mockKey);
236247

237248
expect(pbkdf2Sync).toHaveBeenCalledWith(
238249
Buffer.from('password'),
@@ -349,7 +360,7 @@ describe('AccountTest', () => {
349360

350361
uuid.v4.mockReturnValueOnce(0);
351362

352-
expect(Account.fromPrivateKey('pk').toV3Keystore('password', options)).toEqual({
363+
expect(Account.fromPrivateKey(mockKey).toV3Keystore('password', options)).toEqual({
353364
version: 3,
354365
id: 0,
355366
address: 'a',
@@ -369,7 +380,7 @@ describe('AccountTest', () => {
369380
}
370381
});
371382

372-
expect(fromPrivate).toHaveBeenCalledWith('pk');
383+
expect(fromPrivate).toHaveBeenCalledWith(mockKey);
373384

374385
expect(randomBytes).toHaveBeenNthCalledWith(1, 32);
375386

@@ -426,7 +437,7 @@ describe('AccountTest', () => {
426437

427438
uuid.v4.mockReturnValueOnce(0);
428439

429-
expect(Account.fromPrivateKey('pk').toV3Keystore('password', options)).toEqual({
440+
expect(Account.fromPrivateKey(mockKey).toV3Keystore('password', options)).toEqual({
430441
version: 3,
431442
id: 0,
432443
address: 'a',
@@ -445,7 +456,7 @@ describe('AccountTest', () => {
445456
}
446457
});
447458

448-
expect(fromPrivate).toHaveBeenCalledWith('pk');
459+
expect(fromPrivate).toHaveBeenCalledWith(mockKey);
449460

450461
expect(randomBytes).toHaveBeenNthCalledWith(1, 32);
451462

@@ -484,10 +495,10 @@ describe('AccountTest', () => {
484495
randomBytes.mockReturnValue(Buffer.from('random'));
485496

486497
expect(() => {
487-
Account.fromPrivateKey('pk').toV3Keystore('password', {kdf: 'nope'});
498+
Account.fromPrivateKey(mockKey).toV3Keystore('password', {kdf: 'nope'});
488499
}).toThrow('Unsupported kdf');
489500

490-
expect(fromPrivate).toHaveBeenCalledWith('pk');
501+
expect(fromPrivate).toHaveBeenCalledWith(mockKey);
491502

492503
expect(randomBytes).toHaveBeenNthCalledWith(1, 32);
493504

@@ -511,10 +522,10 @@ describe('AccountTest', () => {
511522
keccak256.mockReturnValueOnce('0xmac');
512523

513524
expect(() => {
514-
Account.fromPrivateKey('pk').toV3Keystore('password', options);
525+
Account.fromPrivateKey(mockKey).toV3Keystore('password', options);
515526
}).toThrow('Unsupported cipher');
516527

517-
expect(fromPrivate).toHaveBeenCalledWith('pk');
528+
expect(fromPrivate).toHaveBeenCalledWith(mockKey);
518529

519530
expect(randomBytes).toHaveBeenNthCalledWith(1, 32);
520531

0 commit comments

Comments
 (0)