ethers.js
ethers.js copied to clipboard
Fix for prepended empty bytes on KeystoreJson decrypt
In certain scenarios, decrypting a KeystoreJson can result in 00 being prepended to a private key in the getAccount function.
Here is an example with a random key
Json:
{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"2e9dc1c889a994f29f84501a88ee28df"},"ciphertext":"9b46c206388bc115b8ac811d288c68f7ae04a7501d5ae5a67dfb230525bbfb61","kdf":"scrypt","kdfparams":{"dklen":32,"n":512,"r":8,"p":1,"salt":"4e87b121893d3082cd70212cbb4c0114e0d858e7d91092c8af3f6d599a6d2072"},"mac":"46ec1e91ec891c0fd018ec4d098036e7f41d5871278631c590349f2c094161dd"},"id":"f04398b6-d60b-4d6b-88b2-6fb9aaa69487","version":3}
Password:
1edw8fROhOix-1QcaXQxXeoA2aCFvpHPeZxESqx-hKLHIxzVBhk8bLb8DMALuclUlbhq-arWJdMVuLM3l3uMsA==
The resulting private key should be:
0x54fc8d2c19216406f12e587253d4a52c20c6af9e1d98248381fb6133d732798f
But internally, the decrypt function returns:
0x0054fc8d2c19216406f12e587253d4a52c20c6af9e1d98248381fb6133d732798f
Additional Context
This KeystoreJson and private key was generated using web3dart
Can you include a demo of how you are using the decrypt functions that generated the invalid key? I use the following code and get the correct (non-prefixed) values:
const json = '{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"2e9dc1c889a994f29f84501a88ee28df"},"ciphertext":"9b46c206388bc115b8ac811d288c68f7ae04a7501d5ae5a67dfb230525bbfb61","kdf":"scrypt","kdfparams":{"dklen":32,"n":512,"r":8,"p":1,"salt":"4e87b121893d3082cd70212cbb4c0114e0d858e7d91092c8af3f6d599a6d2072"},"mac":"46ec1e91ec891c0fd018ec4d098036e7f41d5871278631c590349f2c094161dd"},"id":"f04398b6-d60b-4d6b-88b2-6fb9aaa69487","version":3}';
const password = "1edw8fROhOix-1QcaXQxXeoA2aCFvpHPeZxESqx-hKLHIxzVBhk8bLb8DMALuclUlbhq-arWJdMVuLM3l3uMsA==";
const pk = "0x54fc8d2c19216406f12e587253d4a52c20c6af9e1d98248381fb6133d732798f";
console.log(await ethers.decryptKeystoreJsonSync(json, password));
// {
// address: '0x18e38dA42233e0c4D6107d129A9C953800e590F3',
// privateKey: '0x54fc8d2c19216406f12e587253d4a52c20c6af9e1d98248381fb6133d732798f'
// }
(async function() {
console.log(await ethers.decryptKeystoreJson(json, password));
// {
// address: '0x18e38dA42233e0c4D6107d129A9C953800e590F3',
// privateKey: '0x54fc8d2c19216406f12e587253d4a52c20c6af9e1d98248381fb6133d732798f'
// }
})();
Sorry about that, web3dart seems to only sometimes generate a key that will fail.
web3dart can always decrypt, it's ethers that can't.
Here is one that will fail in ethers:
{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"71b1f67ddc295c9f2a46e34ebd8f5910"},"ciphertext":"e3a9b0d39e65c9a521b3b4326600c9d715c4c712536e47443c2be83b876d995629","kdf":"scrypt","kdfparams":{"dklen":32,"n":512,"r":8,"p":1,"salt":"bb0463b7407242a131c7c8d78239c315d85006e8801efcce2004525761e31bc2"},"mac":"30556000e56b1d17cc31d4b3f288b7e73a7ff4104b1c3e71ae8b9ffea8fbb971"},"id":"dea3ce15-75ef-48b8-b0d8-2eb5fbe324f0","version":3}
Password:
1edw8fROhOix-1QcaXQxXeoA2aCFvpHPeZxESqx-hKLHIxzVBhk8bLb8DMALuclUlbhq-arWJdMVuLM3l3uMsA==
Error:
Error: Point of length 33 was invalid. Expected 33 compressed bytes or 65 uncompressed bytes
at fromBytes (weierstrass.js:599:23)
at Point.fromHex (weierstrass.js:233:40)
at SigningKey.computePublicKey (signing-key.js:129:102)
at computeAddress (address.js:19:75)
at getAccount (json-keystore.js:70:90)
at decryptKeystoreJsonSync (json-keystore.js:146:12)
Decryption succeeds, but there's an extra 00 which makes address computation fail.