Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to restore wallet using recorded 24-word backup phrase. #383

Closed
fresheneesz opened this issue Oct 19, 2020 · 20 comments
Closed

Unable to restore wallet using recorded 24-word backup phrase. #383

fresheneesz opened this issue Oct 19, 2020 · 20 comments

Comments

@fresheneesz
Copy link

I noticed I can create a new Breez wallet without logging in with Google, however if I try to restore my old wallet (from my previous phone) it asks me to log in. A. I don't want to log in, B. If it thinks my backup is going to be on my google drive, its not there. The previous version opened up an entry form where I could enter my recorded seed words. Where did that option go?

@kingonly
Copy link
Member

There was never an option to restore from seed.
https://github.com/breez/breezmobile/wiki/Backup-FAQ

@fresheneesz
Copy link
Author

Shouldn't the channel partner have the necessary state to be able to restore the channel? At very least the channel partner should be able to initiate closing the channel, which my side of the channel could sign with just the seed. What do I do if I don't have a state backup, but I do have my seed?

@kingonly
Copy link
Member

  1. Nope. Channel partner doesn't have the peer state.
  2. Yes, it would be possible to trigger a close, but only with SCB file.
  3. Breez doesn't and never exposed a wallet seed...

@fresheneesz
Copy link
Author

Nope. Channel partner doesn't have the peer state.

I'm pretty surprised Breez hasn't implemented data loss protection: #384

Breez doesn't and never exposed a wallet seed...

It certainly exposes a seed. Whether you would define it as a "wallet seed or not" is another story. The question is, what is the seed Breez has you record used for? Is it not used for generating private keys?

Yes, it would be possible to trigger a close, but only with SCB file.

Why isn't the following possible?:

  1. User requests closing the channel (or transferring the channel balance into a new channel)
  2. Breez node looks at their stored state and generates a transaction to refund itself to a Breez-owned address, and to refund the requesting user to an address they request (or alternatively, directly into a new Breez channel)
  3. Both nodes sign the transaction and broadcast.

Seems like technically, even if both nodes lost all the state and had no idea how much they each had in the channel, they could still come to some agreement (eg split the difference) and create a joint transaction to recover the funds. Its just a multisig address after all. If both sides agree, the funds can be spent. So I assume that perhaps this just isn't something that's implemented. Seems like it could certainly be implemented tho.

@fresheneesz
Copy link
Author

@kingonly Would you be so kind as to help me understand this and potentially recover my funds? It seems like at very least, my seed should be able to generate a public key that can be traced to one of the breeze nodes, a manual channel close can be triggered, and the funds should be returned to the on-chain address. With some additional manual work a transaction could be constructed and the associated private key could be used to sign it. This is in the worst case (where none of these mechanisms are currently automated). I would be happy to do most of the work for that. However, I can't initiate a channel close on my own. I'd appreciate any help you could offer here.

@kingonly
Copy link
Member

See: https://github.com/breez/breezmobile/wiki/Backup-FAQ
You don't have a wallet seed. You have a key phrase that was used as an additional encryption to the cloud backup.

@fresheneesz
Copy link
Author

You have a key phrase that was used as an additional encryption to the cloud backup.

I see. So you're saying that the information used to generate private keys is backed up only on the cloud, and the things that look like seed words are simply an encryption key? If that's true, my funds are a total loss. That's pretty disappointing. It must have been the case that when I created my Breez wallet, either cloud backup wasn't available or wasn't required. Does that sound right? My question is: why did I record an encryption key if there was no backup to encrypt? If I want to search my google drives for this backup, what do I search for?

I think having something that looks like seed words but is actually an encryption key is a very confusing design choice. The fact that you found it necessary to write an FAQ about it sounds like evidence that I wasn't the only person confused by this. It also leaves funds more vulnerable to loss in the case that the phone data and the backup are somehow both lost. If the encryption key is just for encypting, it shouldn't look like a seed. You don't need 24 words for a secure encryption passphrase. You just need 6 words. Make it 7 or 8 and its impenetrable. Fewer people will mistake this for a seed if its not 12 or 24 words.

If what you're going for is a two factor situation where you need both the encryption key and the file from your google drive, users need to be careful to not store the encryption key in plain text on a machine that might be signed into that google drive - otherwise both can be compromised at the same time in pretty much the same way. As long as users are writing down their encryption key on something physical and not computer-accessible, they should be fine. I'm not sure if that is made clear through the app.

What I would prefer is to be given a standard wallet seed to back up in standard ways, and simply use that seed to encrypt the google drive backup file (either by encrypting with the master public key, or as a simple symmetric key). That way you could use that seed as a last resort recovery mechnism in case something goes wrong with your google drive backup (eg its accidentally deleted). I understand this could be a bit more error prone for newbs, since they need to know how to store a seed securely. However, I'd argue they still need to know how to store their encryption key securely in order to be safe from theft.

Another thing that could be done to prevent misfortunate loss like this is for the encryption key to be hashed and used as an identifier that breez servers can associate with a copy of the google drive backup. That way if the google drive backup is lost, Breez can supply its copy (of the encrypted backup) to someone who requests it with the correct hash.

@kingonly
Copy link
Member

kingonly commented Nov 1, 2020

  1. Breez used only Cloud backup from day 1.
  2. There's a warning in the app in case there's no backup. The warning only goes away if there's a valid cloud backup.
  3. After you set an encryption key, there's a backup to the cloud. If that backup fails - users see a warning.
  4. Maybe, but that's the first time we've gotten this feedback.
  5. The backup is stored in a private data folder, accessible only via the mobile app. You can see if Breez was used to store data in your Google Drive by logging in into Google Drive in the browser and looking at Settings > Manage Apps.
  6. We will probably move to this model in the future: https://github.com/photon-sdk/photon-lib

Unless you've ignored the warning messages in the app, there's no way to use Breez w/o performing a cloud backup.
We will take a look how to make it clearer to users this isn't a seed.

@fresheneesz
Copy link
Author

fresheneesz commented Nov 2, 2020

Thanks for the help! I do see on my drive that Breez has 10 MB of hidden app data, and of all my google accounts, that's the only one that Breez shows up for. I'm also reasonably confident I wrote down the encryption key correctly. Does Breez ask users to verify the encryption key after backing it up?

I'm not testing the app to find the above out right now because I'm worried about the drive data. If I create a new Breez wallet connected to my drive, what will happen to my old back up data? Will it be lost, or will both backups be stored and accessible on my drive? Because there are so many words in the encryption key, I wrote it down in a grid like the following:

word1 word2 word3 word4 word5
word6 wordetc word word word
word word word word word
word word word word word
word word word word

At this point, I've entered it left to right as shown above, but I've also attempted to input them top to bottom (word1 word6 word11, etc). Both ways give me "Failed to restore from backup." Does the encryption key contain any error correction / detection? The words must be valid so I couldn't have written invalid words. I could have maybe swapped words, or miswrote a word as another very similar valid word. Is there any tool that I could use to programmatically test various modifications of my key on the backup to attempt to catch one of those mistakes?

If the app asks users to verify the encryption key after backing it up, I'm completely stumped as to how this is going wrong.

@kingonly
Copy link
Member

kingonly commented Nov 2, 2020

  1. Breez ask you to verify the key after chosing to use and encryption key and before performing the first backup using the key.
  2. Both backups will be saved. Backups are saved per node id in the cloud.

We don't have any tools available besides the app.

@kingonly
Copy link
Member

kingonly commented Nov 2, 2020

This is the ways words are presented in Breez, it might help you:

Screenshot_20201102-033540

@fresheneesz fresheneesz changed the title Why is Breez requiring me to log into Breez using my Google account in order to restore? Unable to restore wallet using recorded 24-word backup phrase. Nov 2, 2020
@fresheneesz
Copy link
Author

Hmm, it would be quite a pain to type it in on my phone a bazillion times, especially with the restore pages deleting words when I go back (I think that behavior should be changed). Well maybe I can make a tool for this. I would need some way to extract the backup from google drive. Pointers to the code that decrypts the backup would be helpful too.

One thing I have noticed is that Breez is asking for permission to my google drive every time I click restore. I assumed that's just what it does when you click that button, but on the offchance that having to give permission multiple times in a row is a red flag, I thought I'd mention it. I also have had a couple situations where it did not ask for permission on clicking restore, and it just went straight to the key phrase entry screen.

@kingonly
Copy link
Member

kingonly commented Nov 3, 2020

Unfortunately, the Google Drive code needs to be signed with Breez's key (the Drive information is only accessible via a specific app). There can be only a few ways (4?) to order the words. If all fail, maybe it's more likely you are using the wrong words or incorrectly copied them.

@fresheneesz
Copy link
Author

fresheneesz commented Nov 24, 2020

I'd like to figure this out. I'm generally quite careful with these kinds of things. Especially when the app itself has checks that prevent people from screwing up. I wasn't able to build the app with windows linux subsystem, and no one's responded to my issue here: breez/breez#132. So maybe I'll spin up a linux VM and build it that way. When I do, I'd like some way to use the app I build with the data stored in my Google Drive. I either need to be able to access my google drive directly, or better yet, access a downloaded copy of the data (so I can back it up, and so I can't accidentally delete it forever).

What I'd like to do is create a recovery method that tests related seeds so that even if someone records their seed wrong somehow, the program can still catch the mistake unless they really wrote it all wrong.

How will I be able to access my Google Drive data? Will simply building and running the app work, or will I have to do other things? If nothing else, it would be great if someone (you) could build a way for someone to download their backup from google drive from the Breez app itself.

@fresheneesz
Copy link
Author

After #414 was completed, I've finally had time to come look at this and looking at the code, if there's only one restore option, it doesn't go through the codepath that creates a RestoreDialog that allows downloading the backup.

So I created another wallet, backed it up with an encryption key like the first backup was, and reset Breez to get myself to the RestoreDialog. I was able to download my original backup. However I thought it would put it in my downloads or something, when really it goes to an app temporary folder that's inaccessible. So I had to open it in an archiver program and save it in a folder I could access. However, to do that, going back to the RestoreDialog, both backups were now tagged with the same date, tho still had different hashes. Did it update the file's date stamp when I accessed it? The problem is now I don't know which one is my original backup.

Another thing I noticed is that one of the zip files opened up automatically in my archive app (ZArchiver), which was annoying because it wouldn't let me just download the zip file. However, the other one did show the zip file, allowing me to save the zip directly. I found out the reason was that ZArchiver couldn't open the zip file. Tapping on it and tapping "open" gave me "Achive is corrupt". However, opening it on my computer with 7zip works fine. I'm wondering if perhaps there was a different zip format used for my original backup vs the new one i made just now? I think that's probably all irrelevant info since I have the 3 db files inside for both. Seems like those are the files that are encrypted, not the zip file.

In any case, now I need to figure out how the files in the zip file are decrypted. It was hard for me to figure out until I realized the app is doing some proxying to the go code in a different repository. I eventually found this source which helped a lot. I was able to write a node.js program that successfully decryped the new backup I created:

var bip39 = require('bip39')
var hex = require('convert-hex')
var crypto = require('crypto')
var fs = require('fs')

var nonceSize = 12 // The standard nonce size for aes gcm
var tagSize = 16   // The standard tag size for aes gcm

var mnemonic = [
 "moral",
 "ranch",
 "wall",
 "fix",
 "unknown",
 "equal",
 
 "true",
 "stairs",
 "green",
 "escape",
 "deny",
 "demand",
 
 "joke",
 "place",
 "another",
 "toddler",
 "distance",
 "light",
 
 "speed",
 "shiver",
 "swap",
 "chat",
 "travel",
 "forum",
].join(' ')

var encryptedSourceBytes = fs.readFileSync("backupOld/breez.db")
var decryptedContent = decrypt(encryptedSourceBytes, mnemonic)

console.log(decryptedContent)

function decrypt(sourceBytes, mnemonic) {  
  var entropy = bip39.mnemonicToEntropy(mnemonic)
  var keyArray = hex.hexToBytes(entropy)
  var key = Buffer.from(keyArray)
  
  var nonce = sourceBytes.slice(0, nonceSize)
  // Assumes that the tag is at the end - this assumption turned out to be correct
  var cipherContent = sourceBytes.slice(nonceSize, sourceBytes.length - tagSize)
  var tag = sourceBytes.slice(sourceBytes.length - tagSize)
  
  var decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce)
  decipher.setAuthTag(tag)
  
  var dec = decipher.update(cipherContent, 'hex', 'utf8')
  dec += decipher.final('utf8')

  return dec
}

I was honestly surprised it worked. So after putting my original mnemonic in (in place of the new wallet's mnemonic), I had another surprise: it worked too. I didn't need to do any kind of brute force search whatsoever. The file simply decrypted successfully.

So my question is: why is the Breez app not successfully decrypting my original backup? I don't know the answer to that question, but it seems to me that there's a bug. @kingonly would you mind please reopening this issue. I'm happy to send you my backup and mnemonic password so you/someone can investigate what's going on here.

@fresheneesz
Copy link
Author

@kingonly Would you mind taking a look at my comment here? I think this warrants a reopening of this issue.

@kingonly
Copy link
Member

Please send us your mnemonics, the backup zip file and a video recording of you entering the same mnemonics in Breez to contact@breez.technology.

@fresheneesz
Copy link
Author

fresheneesz commented Mar 7, 2021

Ok, so I did two attempts. Actually I got the same error for restoring both backups (my real backup and my test backup). So I'll just attach my test wallet info here, since they're both getting the same error

Attempting to restore my backup backupTest.zip gave me the error "Failed to restore backup due to incorrect PIN". I don't know what this could possibly mean, since it never asked me for a PIN. Note that this is not the error I had originally gotten when attempting to restore (which was "Failed to restore from backup"). Its possible the version I'm using now is newer than the version I had when I was originally giving information for this ticket.

This is my test wallet backup:

1. moral   2. ranch
3. wall    4. fix
5. unknown 6. equal
7. true    8. stairs
9. green   10. escape
11. deny   12. demand

13. joke     14. place
15. another  16. toddler
17. distance 18. light
19. speed    20. shiver
21. swap     22. chat
23. travel   24. forum

Here's a video of the whole process.

FYI, app info says its version 0.11-beta.

@roeierez
Copy link
Member

roeierez commented Mar 7, 2021

@fresheneesz First I would like to thank you for investing time on it.
From your video I see you have two backups for two different nodes.
The backupTest.zip that you have attached is not the one that you try to restore on your video.
I know that because each backup has a node id (You can see that from the video).
To see that just decrypt the breez.db using your code and grep for the node ID in the printed file content. If you think there is a problem with the other backup using the same mnemonics please send it to me and I will check.

@fresheneesz
Copy link
Author

I see. Well I was able to successfully restore both my test wallet and my main wallet. I had thought I tried my main encryption key on both backups, but apparently not, or perhaps I had made a mistake each time I tried it. I still find it weird that it works now after so many tries before. Maybe there was a bug in the version I was using previously. Or maybe I just made the same mistakes over and over again. IDK, I've never had any problem inputting seeds like this before. But since I can't repro it, I suppose there's nothing to fix.

I still think the restore page should be made easier to use. The seed should all appear in one view, instead of separating it into 4 separate views. You should be able to scroll through the whole thing and verify that what you entered was correct (and have the ability to correct it) before pressing restore. The way Breez initially displays the key should be in the same format as well. As I recall, the key is displayed like this:

1. some   2. word
3. etc       4. etc
5....

If that's the still the case, I highly recommend changing it to something like:

1. some
2. word
3. etc
4. etc
5....

In any case, thanks for the help. Sorry to be so much trouble. If I come across this kind of thing again, I'll add more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants