Closed ivaylonikolov7 closed 1 day ago
After thorough investigation this issue happens due to incompatibility of Buffers in environment different than node.js.This is the code that causes this issue:
export async function derive(parentKey, chainCode, index) {
const isHardened = isHardenedIndex(index);
const data = new Uint8Array(37);
const publicKey = hex.decode(
secp256k1.keyFromPrivate(parentKey).getPublic(true, "hex"),
);
// Hardened child
if (isHardened) {
// data = 0x00 || ser256(kpar) || ser32(index)
data[0] = 0x00;
data.set(parentKey, 1);
// Normal child
} else {
// data = serP(point(kpar)) || ser32(index)
// = serP(Kpar) || ser32(index)
data.set(publicKey, 0);
}
new DataView(data.buffer, data.byteOffset, data.byteLength).setUint32(
33,
index,
false,
);
const I = await hmac.hash(hmac.HashAlgorithm.Sha512, chainCode, data);
const IL = I.subarray(0, 32);
const IR = I.subarray(32);
// if parse256(IL) >= n, proceed with the next value for i
try {
// ki = parse256(IL) + kpar (mod n)
const ki = secp256k1
.keyFromPrivate(parentKey)
.getPrivate()
.add(secp256k1.keyFromPrivate(IL).getPrivate())
.mod(N);
const hexZeroPadded = hex.hexZeroPadded(ki.toBuffer(), 32);
// const ki = Buffer.from(ecc.privateAdd(this.privateKey!, IL)!);
// In case ki == 0, proceed with the next value for i
if (ki.eqn(0)) {
return derive(parentKey, chainCode, index + 1);
}
return {
keyData: hex.decode(hexZeroPadded),
chainCode: IR,
};
} catch {
return derive(parentKey, chainCode, index + 1);
}
}
This code is found in cryptography/src/primitive/bip32.native.js
. Expo's environment not supporting Buffer
s causes const hexZeroPadded = hex.hexZeroPadded(ki.toBuffer(), 32);
to throw an error which invokes the catch
block in the try-catch
. The catch block invokes the same derive
function, therefore generating a recursive function that never gets resolved. Therefore causing the app to eat all the memory it's given. At some point we run out of memory which freezes the application. Which also makes my laptop turns into a huge heat emitting machine ergo makes me a huge contributor to the climate change.
Anyway... The .toBuffer
function code documentation recommends a.toArrayLike(Buffer, endian, length)
but this didn't solve the issue. I checked older versions and this happens in older versions too. In the Github history of this file I can't seem to find a version where this behaviour could be different. So I think this issue has been there for a long time. Currently trying to circumvent it using different conversions toString
, toArrayLike
,toBytes
etc but so far with no result.
Resolved in v.2.51.0
Description
This issue happens in Expo environment. When you try to get a private key(it doesn't matter if ECDSA or ED25519) from a mnemonic it enters an infinite loop that causes the application to freeze(both the browser or the simulator freeze/crash). Tested this both on Android and the web version of the expo project. Same outcome. So far I have noticed that the seed phrase doesn't matter and happens on every seed.
This issue isn't reproducible in node.js environment. Only in Expo environment!
Steps to reproduce
Run this code snippet in an Expo project:
Start the application via an Android or iOS simulator. Web freezes the browser tab too.
Additional context
No response
Hedera network
mainnet, testnet, previewnet, other
Version
2.48.1 but happens in others too
Operating system
macOS