Closed SCBuergel closed 4 years ago
After a quick skim of the code (way over my head here), is this line correct? https://github.com/brave/brave-core/blob/cd5a08090094fc1a67033e2760c3a067b27e001d/components/brave_sync/crypto/crypto.cc#L148
bool PassphraseToBytes32(const std::string& passphrase,
std::vector<uint8_t>* bytes) {
DCHECK(bytes);
size_t written;
bytes->resize(DEFAULT_SEED_SIZE);
if (bip39_mnemonic_to_bytes(nullptr, passphrase.c_str(), bytes->data(),
bytes->size(), &written) != WALLY_OK) {
LOG(ERROR) << "bip39_mnemonic_to_bytes failed";
return false;
}
return true;
}
bip39_mnemonic_to_bytes
only converts the mnemonic into a binary representation, but it does not actually derive the BIP39 seed. That is done by bip39_mnemonic_to_seed
, which doesn't seem to be used anywhere in the code. Maybe someone mistook the result of PassphraseToBytes32
as the actual seed to derive keys with?
@karalabe I don't get why that would work for 12 word mnemonics but not for 24 word mnemonics though. Since I haven't been digging into C for well over a decade I won't be able to comment much further.
@diracdeltas can you take a look? Is this also a problem with MetaMask?
I don't get why that would work for 12 word mnemonics but not for 24 word mnemonics though.
we use different code paths for 12 vs 24. 12-word does the same thing as metamask (needed for legacy compatibility with metamask imports) whereas 24 uses our own derivation method, described here: https://github.com/brave/brave-browser/wiki/Brave-Ethereum-Remote-Client-Wallet-Seed-Information
unfortunately when we designed this, we didn't have compatibility with other wallet providers as a goal, so it's not surprising to me that this is happening :(
@karalabe that code is used for sync, not crypto wallets. i think you want to look here: https://github.com/brave/eth-hd-keyring/blob/master/index.js#L188-L199
this is where it calls the metamask-compatible code for 12-word phrases btw: https://github.com/brave/eth-hd-keyring/blob/master/index.js#L180
so at a glance, i think this is because we are calling https://github.com/brave/eth-hd-keyring/blob/master/index.js#L176, which doesn't actually derive the bip39 seed (the same issue @karalabe found, but in js not c++). this can pretty easily be replaced by just calling bip39.mnemonicToSeed(mnemonic)
. however, the tricky part is migrating existing wallet users.
open to thoughts here
i did some digging; findings here
bip39.entropyToMnemonic
to encode it as a mnemonichdkey.fromMasterSeed
directly on the 32-byte seed (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#master-key-generation)bip39.mnemonicToEntropy
on the mnemonic to convert it back into the seedas far as i understand:
bip39.generateMnemonic()
to generate 16 bytes of entropy encoded as a mnemonic. this follows https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic.hdkey.fromMasterSeed
with the 64-byte seedbip39.mnemonicToSeed
unfortunately, i think this will make it difficult for us to encode the brave wallet codewords as other-wallet-compatible code words, because we would need to find the PBKDF2 preimage. if other wallets are willing to take the seed directly as input, that could work.
Why does this not have a P1 and bug label?
Have confirmed this issue. A short-term workaround would be for a user to export and save private keys for each active account in the wallet. However this results in a new problem as the exported private key does not work in the MyCrypto desktop app as the key has all uppercase letters. Indicates the exported private key format is also nonstandard. For a successful import, a user first needs to change the private key to all lowercase letters before importing into MyCrypto and I doubt many users would know this. FYI Metamask displays private key as uppercase but exports as lowercase. Suggest Brave change the exported private key to lowercase.
There appears to be a number of options.
I didn't realize you could import the private key directly into other wallets. In that case, seems like the easy one-line fix is to change the export to lowercase. Is everyone happy with that?
sounds good to me, are there any downsides to this?
dan finlay from metamask doesn't exactly remember why they chose uppercase; it's possible some other wallets expect uppercase as well? in which case i think it's safest to just offer a button in the private key export screen that converts between uppercase and lowercase so users can do either.
Please keep in mind that exporting/importing private keys is really only a last resort temporary solution.
Users expect mnemonics to work across wallets in a consistent fashion, i.e. the same addresses get generated from the same mnemonic. If the Brave wallet does not follow established standards then the number of issues you will get here with people claiming loss-of-fund situations will explode.
Users expect mnemonics to work across wallets in a consistent fashion, i.e. the same addresses get generated from the same mnemonic. If the Brave wallet does not follow established standards then the number of issues you will get here with people claiming loss-of-fund situations will explode.
AFAICT we've only had 2 complaints of this so far, probably because this bug only occurs if you are going from Brave to another wallet implementation. I agree it would be ideal to be standards-compatible because that's what users expect, but either way the funds are fully recoverable.
I think the 2 options are:
Add lowercase key export option. In the codewords screen, add a disclaimer that restoring wallets from the codewords requires using Brave; for exporting to other wallets, use the private key export. This is my preferred solution since it's easier.
Add lowercase key export option, but also change the wallet derivation process to be standard-compatible; then on wallet restoration in Brave, we ask whether their wallet codewords are v1 or v2 and derive accordingly. This might cause some user confusion if someone doesn't know whether they are using v1 or v2 codewords, which can also lead to perceived loss of funds.
update - metamask has an upstream PR to stop upper-casing the private key, which we should pull once it's merged. https://github.com/MetaMask/metamask-extension/pull/8850
Okay, this can be the 3rd complaint. I expect most users of Brave Crypto Wallet would not realise the issue exists. If they had known of the issue they probably wouldn't have choosen the Brave Crypto Wallet in the first place.
Is there a guide for deriving seed words that will restore the crypto wallet addresses to other wallets?
AFAICT we've only had 2 complaints of this so far, probably because this bug only occurs if you are going from Brave to another wallet implementation. I agree it would be ideal to be standards-compatible because that's what users expect, but either way the funds are fully recoverable.
I think the 2 options are:
- Add lowercase key export option. In the codewords screen, add a disclaimer that restoring wallets from the codewords requires using Brave; for exporting to other wallets, use the private key export. This is my preferred solution since it's easier.
- Add lowercase key export option, but also change the wallet derivation process to be standard-compatible; then on wallet restoration in Brave, we ask whether their wallet codewords are v1 or v2 and derive accordingly. This might cause some user confusion if someone doesn't know whether they are using v1 or v2 codewords, which can also lead to perceived loss of funds.
Is there a guide for deriving seed words that will restore the crypto wallet addresses to other wallets?
As I explained in https://github.com/brave/brave-browser/issues/9837#issuecomment-644477534, it is not computationally feasible to derive other-wallet seedwords from brave seedwords AFAICT. So given that this option isn't on the table, I'm leaning toward option 1.
So are you saving the Brave seed words won't even restore a Brave crypto wallet? Are these seed words completely useless then?
Is there a guide for deriving seed words that will restore the crypto wallet addresses to other wallets?
As I explained in https://github.com/brave/brave-browser/issues/9837#issuecomment-644477534, it is not computationally feasible to derive other-wallet seedwords from brave seedwords AFAICT. So given that this option isn't on the table, I'm leaning toward option 1.
So are you saving the Brave seed words won't even restore a Brave crypto wallet? Are these seed words completely useless then?
Where did you get this from? I explicitly said above that it will work to restore Brave wallets, but not other wallets, because we designed it without cross-compatibility as a goal.
So is the only option currently to export private keys of each used account with the Brave wallet? Is there currently an export feature, or are we just waiting for metamask to provide the lowercase private key export feature?
So are you saving the Brave seed words won't even restore a Brave crypto wallet? Are these seed words completely useless then?
Where did you get this from? I explicitly said above that it will work to restore Brave wallets, but not other wallets, because we designed it without cross-compatibility as a goal.
Is there currently an export feature, or are we just waiting for metamask to provide the lowercase private key export feature?
just waiting on metamask to convert to lowercase
Verification passed on
Brave | 1.12.114 Chromium: 84.0.4147.135 (Official Build) (64-bit) |
---|---|
Revision | c42bd09b3f24da1698d71d3b4f57402137163566-refs/branch-heads/4147@{#1102} |
OS | Windows 10 OS Version 1809 (Build 17763.1397) |
Component | 0.1.69 |
Verification passed on
Brave | 1.13.75 Chromium: 85.0.4183.69 (Official Build) beta (64-bit) |
---|---|
Revision | 4554ea1a1171bd8d06951a4b7d9336afe6c59967-refs/branch-heads/4183@{#1426} |
OS | Linux |
Component | 0.1.69 |
Verification passed on
Brave | 1.14.55 Chromium: 85.0.4183.69 (Official Build) nightly (64-bit) |
---|---|
Revision | 4554ea1a1171bd8d06951a4b7d9336afe6c59967-refs/branch-heads/4183@{#1426} |
OS | macOS Version 10.15.5 (Build 19F101) |
Component | 0.1.69 |
Hello,
it looks to me that this issue was originally tracking two different problems:
1) Export key in lower case 2) Have compatibility with other wallet providers as mentioned by @diracdeltas
I've created a wallet using MEW. When restoring with my seed (from MEW) in Brave's Crypto Wallets, it restores another account with a different public address. I think this is related to point number 2.
I guess this issue only solved point number 1 and left point number 2 out. Are there still plans to have better compatibility?
Thanks —Sebastian
@sebastianzolg We can't easily support importing words from Brave into another wallet because our derivation algorithm is different, but we could potentially support importing words from other wallets into Brave if that's a thing that people would find useful.
Alternatively, if MEW supports exporting private keys, we could add an option to restore from private key instead of mnemonic.
Thanks, @diracdeltas, for the clarification! My scenario is importing the seed from another Wallet into Brave. Given that key management is still a nightmare in this distributed ledger world. The behavior should at least be explained when importing in Brave, so newbies are not that confused.
Thanks for the clarification anyway. I would vote for such an import scenario.
@sebastianzolg i think it is technically feasible for Brave wallets to support import from other wallets (just not the other way around). i'll open an issue for that.
Chiming in here as well, as this issue bit my ass and wasted a bunch of time. My bad assuming Brave wallets were compatible with all the others.
I'm developing a smart contract and using HDWalletProvider
which takes a mnemonic as input. It does NOT work with the 24 words generated by Brave. I assumed it did, and was pulling out my hair trying to figure out why I couldn't deploy. So essentially, ethereum/ERC-20/smart contract developers cannot use Brave to generate an HD wallet for smart contract use. I have to use MetaMask or some other standards compliant wallet to generate the words.
Personally I think Brave should seriously consider evolving to be compatible. I realize this will be difficult since you need to maintain support for all existing wallets, but alienating developers is probably not in your best interest.
@tauren i already have a PR open for this. please see https://github.com/brave/brave-browser/issues/13245
^ sorry meant to reply to a comment from someone else that was apparently deleted
Can this be re-opened, as it still is an issue? It is still not fixed as I have a 24-word phrase that cannot be used in Brave because Brave doesn't follow the standard HD Wallet algorithm for key derivation from it.
IIUC, #13245 only fixed 12-word phrases, but 24-word phrases are still non-standards compliant. While I understand that this is a huge pain to fix, the pain of Brave mnemonics being standards non-compliant is only going to get worse with additional crypto adoption over time and the longer we wait to start on the road to standards compliance in brave the more painful this will be.
My recommendation on long-term migration strategy:
Another option would be that when the user tries to recover a 24 word phrase, check to see which accounts have assets on the current network so we can helpfully hint to the user which one they probably have.
Can this be re-opened, as it still is an issue? It is still not fixed as I have a 24-word phrase that cannot be used in Brave because Brave doesn't follow the standard HD Wallet algorithm for key derivation from it.
Can you restore that on MetaMask and have it work? I believe it's matching MetaMask at least with our Crypto Wallets extension.
cc @diracdeltas @darkdh
According to #13245, you cannot, and my experience agrees with this:
for users who are restoring a wallet, restore using the standard way if their mnemonic is 12 words, but restore using the legacy way if it's 24.
If I have a 24-word phrase it is interpreted one way, but if I have a 12-word phrase it is interpreted a different way. The 12-word interpretation is standards compliant, while the 24-word interpretation is non-compliant (something custom for Brave Crypto Wallets).
As a test case,
zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote
This mnemonic restores to address 0x1959f5f4979c5Cd87D5CB75c678c770515cb5E0E
in MetaMask and https://github.com/Zoltu/ethereum-crypto (when given derivation path m/44'/60'/0'/0/0
) and it restores to 0x63D1ec5Cb2D2D2d3168266E88DA0F08c7455e6D9
in Brave Crypto Wallets.
zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong
This seed phrase on the other hand resolves to 0xfc2077CA7F403cBECA41B1B0F62D91B5EA631B5E
in MetaMask, Brave, and https://github.com/Zoltu/ethereum-crypto
got it, I understand now, thanks.
Note that we're doing an entire rewrite of the wallet now so this old extension won't be maintained. We'll be sure to at least support both of these ways with the new wallet though.
It is still not fixed as I have a 24-word phrase that cannot be used in Brave because Brave doesn't follow the standard HD Wallet algorithm for key derivation from it.
that's a good point; if the phrase is 24 words, there's no way for us to automatically tell if it's a metamask-style phrase or a legacy brave phrase.
we could let the user pick which derivation path to use in this case, or just support importing from the raw private key.
I think importing from private keys is not the right solution. Users have been trained to understand recovery words and that they are secret, but "big hexadecimal numbers" look like account addresses, transaction hashes, etc. to users and they don't know to keep them secret. Also, a user with multiple wallets shouldn't have to import/export every key individually. Part of the point of HD Wallets is to make it so you can carry around a single value and it is portable between different tools.
Last month i create i brave crypto account in "crypto wallets", it give me 24 seed phrase, and now i go there, want to open the account with the 24 seed phrase and it ask me for 12 seed phrase... need some help. thanks i already read the above answers, but need help anyway.
it accepts both 12 and 24 words
Thanks for the answer bbondy.
I create the wallet in the "create" button in the image, and it gave me 24 words phrase. And now i restore it in another computer in the "restore" button (in the image) and it accept the 24 word phrase but open a different address account!!!
appreciate some help.
I also need help with this. My 24-word phrase provided by Brave Crypto Wallets does not open the same address in MetaMask that Brave had generated within its built-in browser.
What if I want to import the seed into Trezor or Ledger?
Does it require a 12-word seed? What is the 12-word seed compared to the 24-word?
@igloohead it's not possible for the legacy 24-word phrases to be metamask compatible. if you wish to export your wallet from brave for import into metamask, you have to do it via the private key export option.
Hi all... I found this page trying to solve a problem I have with restoring my Brave wallet with my seed phrase. I had multiple accounts in my wallet, one of which is very important to me. Unfortunately for me, I didn't back up the private key to that address, and the seed phrase loaded Account 1 (which I used before the one I need, and can't find right now) with the complete tnxn history, my contacts and custom networks. The way I understand the derivation path (I have no clue about coding/programming etc.) should load my addresses always in the same order when I click "Add account". Why is my address not showing up then? It was created in my Brave wallet, so it must have been derived from the seed derivation path... I made an account here for the sole purpose of trying to resolve this issue. If someone knows a solution to my problem, some help would be greatly appreciated. Thank you in advance.
@Jules-Win I'm not affiliated with Brave in any way but your story sux, so just to clarify:
Thank you for the response, sir. I actually derived (add account) more addresses by mistake while I was using the Flare Finance beta, while on the Coston testnet. A couple months after that, I connected one of the derived addresses to the app I used to create a node. I reset the wallet recently, and the first address derived was the one I used before setting up secondary ones. The tnxs history was there, all the custom networks I added were there as well, but when I clicked on "Add account", the address I needed wasn't showing up. Went frantic and added 400+ addresses, but it never showed. I can't see the derivation path, because of the difference in code, I guess. When I enter my seed in the MEW wallet, it derives a diff address for Account 1. I'll try installing this version and see if I can derive the right address. Thank you again for the feedback, regardless of how it goes. Will post what happened.
No luck, unfortunately... Derived 60. Not showing up. Any other ideas maybe. Thanks again regardless. :)
Man - the one time I used an seed to generate multiple addresses. I never double checked what brave was doing (which I should have done). Now trying to migrate and it is just not possible, it does not matter which hardware wallet or software wallet I use they all generate the same public addresses from the seed - but none of these addresses are the ones created by brave.
So yes - was an super fan of brave from day 1 - but these are the kind of mistakes that break trust in an un-restorable way. Will have to spent a lot of gas migrating all my brave software wallets - to a new wallet NOT generated by brave.
I will keep brave (probably) as browser maybe, but will NEVER let it have access to my crypto in anyway. Good luck with your company.
@BICE-BN Simply go to restore in the wallet, enter your seed phrase and check on the option for Import from legacy option.
Description
Brave does not correctly derive the Ethereum address for 24-word mnemonics. The crypto wallet automatically creates 24 seed words upon first start which are also not yielding the correct address. Entering those seed words in another tool such as MyEtherWallet or MyCrypto derives another address.
As a consequence all funds that are sent to a Brave address cannot be recovered and might be lost!
Steps to Reproduce
toward around purity endorse style assume seed discover beyond mosquito lend auto cattle shed smile pretty push slot grid hotel eagle govern defense element
0xC5443F1948FF4273222E04E93A9365780990Bc1D
0x815B52687Ff57Ae9a58B4894e66ad476f0ba224D
Actual result:
The Ethereum address generated in Brave does not match those generated with standard tools.
Expected result:
The Ethereum address generated in Brave should match those generated with standard tools.
Reproduces how often:
Easily reproduced
Brave version (brave://version info)
on Ubuntu 18.04
Miscellaneous Information:
Generally, Brave seems to be unable to import 24-word mnemonics correctly. E.g. the test vector
zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote
yields the address0x63D1ec5Cb2D2D2d3168266E88DA0F08c7455e6D9
(should be0x1959f5f4979c5Cd87D5CB75c678c770515cb5E0E
).12-word mnemonics on the other hand do work fine. The test vector
zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong
yields the correct address0xfc2077CA7F403cBECA41B1B0F62D91B5EA631B5E