Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class HdKeyring extends SimpleKeyring {
}


_getWalletForAccount (account, opts = {}) {
_getWalletForAccount (account) {
const targetAddress = sigUtil.normalize(account)

let wallet = this.wallets.find((w) => {
Expand All @@ -94,22 +94,14 @@ class HdKeyring extends SimpleKeyring {
(sigUtil.normalize(address) === targetAddress))
})

if (opts.withAppKeyOrigin) {
const privKey = wallet.getPrivateKey()
const appKeyOriginBuffer = Buffer.from(opts.withAppKeyOrigin, 'utf8')
const appKeyBuffer = Buffer.concat([privKey, appKeyOriginBuffer])
const appKeyPrivKey = ethUtil.keccak(appKeyBuffer, 256)
wallet = Wallet.fromPrivateKey(appKeyPrivKey)
}

return wallet
}

getPrivateKeyFor (address, opts = {}) {
getPrivateKeyFor (address) {
if (!address) {
throw new Error('Must specify address.');
}
const wallet = this._getWalletForAccount(address, opts)
const wallet = this._getWalletForAccount(address)
const privKey = ethUtil.toBuffer(wallet.getPrivateKey())
return privKey;
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"dependencies": {
"bip39": "^2.2.0",
"eth-sig-util": "^2.4.4",
"eth-simple-keyring": "^3.4.0",
"eth-simple-keyring": "^4.0.0",
"ethereumjs-abi": "^0.6.5",
"ethereumjs-util": "^5.1.1",
"ethereumjs-wallet": "^0.6.0",
Expand Down
110 changes: 67 additions & 43 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,63 +385,87 @@ describe('hd-keyring', function() {
})
})

describe('signing methods withAppKeyOrigin option', function () {
it('should signPersonalMessage with the expected key when passed a withAppKeyOrigin', function (done) {
describe('getAppKey', function () {
it('should return a private key custom to the provided app origin', async function () {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
})
const address = firstAcct
const message = '0x68656c6c6f20776f726c64'
const hexKey = await keyring.exportAccount(address)

const privateKeyBuffer = Buffer.from('8e82d2d74c50e5c8460f771d38a560ebe1151a9134c65a7e92b28ad0cfae7151', 'hex')
const expectedSig = sigUtil.personalSign(privateKeyBuffer, { data: message })
const appKey = await keyring.getAppKey(address, 'someapp.origin.io')

keyring.deserialize({
assert.notEqual(hexKey, appKey.toString('hex'))
assert(ethUtil.isValidPrivate(appKey))
})

it('should return different keyrings when provided different app origins', async function () {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
})
.then(() => {
return keyring.signPersonalMessage(address, message, {
withAppKeyOrigin: 'someapp.origin.io',
})
})
.then((sig) => {
assert.equal(sig, expectedSig, 'signed with app key')
done()
})
.catch((reason) => {
assert(!reason, reason.message)
done()
})
const address = firstAcct

const appKey1 = await keyring.getAppKey(address, 'someapp.origin.io')

assert(ethUtil.isValidPrivate(appKey1))

const appKey2 = await keyring.getAppKey(address, 'anotherapp.origin.io')

assert(ethUtil.isValidPrivate(appKey2))

assert.notEqual(appKey1.toString('hex'), appKey2.toString('hex'))
})

it('should signTypedData with the expected key when passed a withAppKeyOrigin', function (done) {
it('should return the same keyring when called multiple times with the same params', async function () {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
})
const address = firstAcct
const typedData = {
types: {
EIP712Domain: []
},
domain: {},
primaryType: 'EIP712Domain',
message: {}
}

const privateKeyBuffer = Buffer.from('8e82d2d74c50e5c8460f771d38a560ebe1151a9134c65a7e92b28ad0cfae7151', 'hex')
const expectedSig = sigUtil.signTypedData(privateKeyBuffer, { data: typedData })
const appKey1 = await keyring.getAppKey(address, 'someapp.origin.io')

keyring.deserialize({
assert(ethUtil.isValidPrivate(appKey1))

const appKey2 = await keyring.getAppKey(address, 'someapp.origin.io')

assert(ethUtil.isValidPrivate(appKey2))

assert.equal(appKey1.toString('hex'), appKey2.toString('hex'))
})

it('should throw error if the provided origin is not a string', async function () {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1
}).then(() => {
return keyring.signTypedData_v3(address, typedData, {
withAppKeyOrigin: 'someapp.origin.io',
})
})
.then((sig) => {
assert.equal(sig, expectedSig, 'signed with app key')
done()
numberOfAccounts: 1,
})
.catch((reason) => {
assert(!reason, reason.message)
done()
const address = firstAcct

try {
await keyring.getAppKey(address, [])
} catch (error) {
assert(error instanceof Error, 'Value thrown is not an error')
return
}
assert.fail('Should have thrown error')
})

it('should throw error if the provided origin is an empty string', async function () {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
})
const address = firstAcct

try {
await keyring.getAppKey(address, '')
} catch (error) {
assert(error instanceof Error, 'Value thrown is not an error')
return
}
assert.fail('Should have thrown error')
})
})
})