Pages:
Author

Topic: The FinderOuter, a bitcoin recovery tool (v0.16.0 2022-09-19) - page 3. (Read 3882 times)

legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
Version 0.9.0 is released.
https://github.com/Coding-Enthusiast/FinderOuter/releases/tag/v0.9.0.0
See changelog for details.
  • New recovery option: find encoding of an arbitrary input string

  • Add a new help view that shows up at startup and suggests which recovery option to choose


  • Add knowledge Base window that contains explanation of different parts
There are small question marks on different UI objects that can be clicked to move to the respective KB

The KB will contain some general information about what the input is, how it is used, etc.


  • Some small improvements in address validation and error message

A good news
I've made good progress on solving issue #9 and next release will hopefully solve it for good as we will replace BigInteger entirely with a UInt256 struct that doesn't have the same issues as BigInteger and also it adds a huge speed gain.
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
When searching for Base58 wif code, can you bring up a method of adding several addresses instead of one destination address?
It could be added but I don't see the point in it and here is why, the checksum in a WIF is big enough to have very little collisions when going through permutations. Most of the times with small number of missing characters (that would take reasonable time) only 1 valid key exists and as the number of missing characters grow the number of valid keys that are returned remain too small. For example with 7 missing chars at random positions worst case scenario is that you get 2 or 3 keys. It is easy for user to check all of them. If the number of missing chars is too big then recovery is most probably not possible, accepting more addresses won't change that. In any case the program is already printing any valid key it finds as it goes.

BTW the Missing base58 option is not using the extra input field (ie. address/pubkey) for WIF recovery. It is just used for a special case where the missing chars are all located at the end.
jr. member
Activity: 38
Merit: 13
This fraudster is selling your software : https://youtu.be/zowg-o4Fszk
Thanks for informing me. The corresponding google account is banned now.

You're welcome. When searching for Base58 wif code, can you bring up a method of adding several addresses instead of one destination address?
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
This fraudster is selling your software : https://youtu.be/zowg-o4Fszk
Thanks for informing me. The corresponding google account is banned now.
jr. member
Activity: 38
Merit: 13
This fraudster is selling your software : https://youtu.be/zowg-o4Fszk
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
Version 0.8.0 is released.
https://github.com/Coding-Enthusiast/FinderOuter/releases/tag/v0.8.0.0
See changelog for details.
  • Some user interface improvements
  • New recovery option: find BIP-32 derivation path
    Note: this is a simple option with only a handful of standard paths, I'll try finding more paths used by different wallets and optimize it but for now it is very basic.
  • New recovery option: recover Armory backup phrases missing some characters
    Note: this option's speed is wildly variable because it depends a lot on the existence of the checksum. It can be from dozens of keys per second to hundred billion key per second. For example if the recovery phrase has its checksum and is missing 10 characters you can check 1 trillion variations and recover it in 1 second.
  • Main window size has a limit so it can no longer be shrinked to nearly nothing

A small RoadMap
  • For next release I'd like to work more on the user experience by adding a Help window where user can interact with at the start of the application and can figure out which option to use.
  • I would also like to add some more "tips" to the UI explaining different terminology. For example explaining what WIF, Base58, derivation path, ... are.
  • Let me know if there is any interest in changing UI theme like having light or dark theme instead of the default light one or a colored one.
Version 0.9.0 will probably be released with these. But I also have 2 more options in mind:
  • BIP-39 passphrase (the extension words) recovery (hopefully for 0.10.0)
  • BIP-38 password (for encryption) recovery

I've also started working on optimizing ECC to hopefully solve issue #9 but it's still very challenging.
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
Maybe, I do something wrong on building.
Probably. This has nothing to do with the UI (Avalonia).
Inside your Visual Studio place a break on the Find method line and then go to Debug > Start debugging (F5).
After that enter your data in text boxes and click find, the execution should stop at that line where you placed the break.


Then continue pressing F11 to step into each method or F10 to step over until you figure out where the evaluation is failing. You can move your mouse over to any variable and see their value when in debug mode.



I can write something that is considered invalid inside a file, but it'll be normally built. It makes me curious. Do I change the program or not?
Did you open the solution file or the csproj file or did you just open the .cs file from your explorer? Because the only thing that I can think of is that when you open a .cs file you can't build it, it has to be inside a .csproj file.
This file: https://github.com/Coding-Enthusiast/FinderOuter/blob/v0.6.0.0/Src/FinderOuter.sln or this https://github.com/Coding-Enthusiast/FinderOuter/blob/v0.6.0.0/Src/FinderOuter/FinderOuter.csproj
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
All I can think of is that you should debug the code line by line and see where it calls report.Fail("") (remember to change to debug mode if you haven't already).

It doesn't make sense. I comment the specific part of the code, but I still get the same error. Maybe, I do something wrong on building. Yes, I use Debug, but I've never used Avalonia in the past. Is there something that I have to prepair before building? I've also noticed that there is no syntax error detector shown in VS. For example, I can write something that is considered invalid inside a file, but it'll be normally built. It makes me curious. Do I change the program or not?

Code:
/*words = mnemonic.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (!allowedWordLengths.Contains(words.Length))
{
    return report.Fail("Invalid mnemonic length. Mnemonic is: " + mnemonic);
}*/

legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
I wanted to see, what mnemonic it reads. Is there any other part of the source code that prints the same error?
No. https://github.com/Coding-Enthusiast/FinderOuter/search?q=Invalid+mnemonic+length
All I can think of is that you should debug the code line by line and see where it calls report.Fail("") (remember to change to debug mode if you haven't already).
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
Here is the error message. See what the value of mnemonic is.
I don't believe that's the error message. Once I change it to the following I still get "Invalid mnemonic length.", that I shouldn't.

Code:
words = mnemonic.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (!allowedWordLengths.Contains(words.Length))
{
    return report.Fail("Invalid mnemonic length. Mnemonic is: " + mnemonic);
}

I wanted to see, what mnemonic it reads. Is there any other part of the source code that prints the same error?

That's a typo.
Okay, changed.
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
but still I ge tthe same error
Try placing a break point where the error is being created and see what input is being checked. That should give you a good idea where the problem is. Here is the error message. See what the value of mnemonic is.
My guess is that the input is not split into separate lines correctly.

Why is it nvironment? Why not Environment? Based on your code, it doesn't seem you've used it as a variable.
That's a typo.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
The FindMissing(..) in Service expects a single mnemonic, changing that is a lot of work so you should just change the ViewModel code to call it more than one time with each mnemonic instead of once

I did had changed that. I wasn't taking the entire string with all the lines and starting the brute force. I just used for loop instead foreach as you did. But, I still face the same issue. I replaced everything you said, the Find() and the Message on Report.cs, but still I ge tthe same error:


As for this one:
Quote
nvironment.NewLine
Why is it nvironment? Why not Environment? Based on your code, it doesn't seem you've used it as a variable.
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
I'll have to admit that your code is literally beautiful. Everything is organized and I can understand the functionalities of each file. Somehow, FinderOuter on Visual Studio 2019 goes really fast in contrast with my WinForms programs. Does it have to do with Avalonia? How did they manage to make it that light?
Thanks. I believe XAML is generally cleaner and faster for UI development but I'm not sure since I haven't really used WinForms myself.

Anyway, I got off topic. What I wanted to say is that by changing line 149 on ViewModels/MissingMnemonicViewModel.cs and line 1483 on Services/MnemonicSevice.cs it's not possible. For example line 1425 on Services/MnemonicSevice.cs returns me "Invalid mnemonic length." when I try to add more than one mnemonics:
The FindMissing(..) in Service expects a single mnemonic, changing that is a lot of work so you should just change the ViewModel code to call it more than one time with each mnemonic instead of once
VM code turns into:
Code:
public async override void Find()
{
   string[] mns = Mnemonic.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
   foreach (var item in mns)
   {
      await MnService.FindMissing(item, MissingChar, PassPhrase, AdditionalInfo, SelectedInputType.Value,
                                  KeyPath,
                                  SelectedMnemonicType, SelectedWordListType,
                                  SelectedElectrumMnType);
   }
}
The FindMissing(..) method has to return a task to be awaitable:
Code:
public async Task FindMissing(string mnemonic, char missChar, string pass, ....
And since IReport.Init() on each call clears the message you have to change that so that on each call to FindMissing() the new messages are added at the end.
https://github.com/Coding-Enthusiast/FinderOuter/blob/681225416796a926479c8d246fb7afbf1e34484c/Src/FinderOuter/Models/Report.cs#L60
Code:
Message += $"{Environment.NewLine}Finished checking first input. Moving on to next.{Environment.NewLine}";

Now you can enter multiple mnemonics in mnemonic textbox in mnemonic recovery option separating them with a new line and each will be checked one after the other.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
Change this line into a loop where it breaks each line into a single mnemonic and makes the call. And modify the Init() on report so that it doesn't clear the report on each call.

I'll have to admit that your code is literally beautiful. Everything is organized and I can understand the functionalities of each file. Somehow, FinderOuter on Visual Studio 2019 goes really fast in contrast with my WinForms programs. Does it have to do with Avalonia? How did they manage to make it that light?



Anyway, I got off topic. What I wanted to say is that by changing line 149 on ViewModels/MissingMnemonicViewModel.cs and line 1483 on Services/MnemonicSevice.cs it's not possible. For example line 1425 on Services/MnemonicSevice.cs returns me "Invalid mnemonic length." when I try to add more than one mnemonics:

Code:
words = mnemonic.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (!allowedWordLengths.Contains(words.Length))
{
     return report.Fail("Invalid mnemonic length.");
}

I guess that everything goes dominos if I change it to:

Code:
words = mnemonic.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (!allowedWordLengths.Contains(words.Length) && Mnemonic.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries))
{
     return report.Fail("Invalid mnemonic length.");
}

Thanks in advance!
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
I'd also like to ask something else. Is it possible to brute force multiple mnemonics one after the other? One per line? If not, do you plan on doing something similar in the future? (Like adding some extra features on FinderOuter, not necessarily multiple mnemonics at once)
Normally people have one mnemonic that is damaged and want to recover it and if they have more they can just enter the second one after the first finished. I don't think there is any point in accepting more than one at a time.
You can make minimal modification to the code to run it for yourself though.
Change this line into a loop where it breaks each line into a single mnemonic and makes the call. And modify the Init() on report so that it doesn't clear the report on each call.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
Additionally when the path is something like m/0/0 the final round
And for me that I want to brute force a lot of derivation paths, makes the entire process even slower. This is what I enter on these fields:


(Where "x" is the number I change every time)



I'd also like to ask something else. Is it possible to brute force multiple mnemonics one after the other? One per line? If not, do you plan on doing something similar in the future? (Like adding some extra features on FinderOuter, not necessarily multiple mnemonics at once)
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
4-bit checksum means 1 in 16. That's why you've written 261,774 (~ 20482 / 16) on the SetBip32() call count?
Essentially yes. I modified the code to add a simple counter that incremented on each call.

I still don't understand why you wrote 00:02:44. There is no machine that can do so many operations in such little time. On my pc, brute forcing a 12-words mnemonic with 2 words missing takes me around 12 hours. (Given only the address)
It's not really that many operations.
Each SetBip32() method consists of 2048 HMACSHA512 + (path depth * 1 HMACSHA512). That is 2050 HMACSHA512 for brute forcing m/0'/0'. The 2:44 min is to compute 536,636,700 HMACs in total (it's actually a lot less due to using "specialized" code).
The specialized part is that FinderOuter isn't using the general HMAC functions, everything is specialized to compute only what it's supposed to. For example each HMAC consists of computing at least 2 SHA512 and each SHA512 has at least 2 blocks to compress. PBKDF2 (the 2048 round) repeats this in a loop where roughly 50% of it (4094 block compressions) is skipped on each call which greatly improves the speed.

The only reason why it takes a much longer time (hours) to recover using an address is because of issue #9. ECC on its own is very slow and my implementation of it turns out to be terribly slow.
Additionally when the path is something like m/0/0 the final round (after the PBKDF2) is to compute public keys (so there is an ECMultiply) which is a slow process itself. As a result the recovery process becomes a lot slower and the slowness of FinderOuter on top of it makes it take that long.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
I explained last time: https://bitcointalksearch.org/topic/m.56129399
Let me know if you have any additional questions.
Okay then, I'll reply on your previous post:

The number of times checksum is valid depends on the size of the checksum, the bigger it is the less collision occurs and SetBip32() is called less times.
A 12-words BIP39 mnemonic only has a 4-bit checksum while a 12-word Electrum mnemonic has at least 8 bits of checksum (8 bits for standard type, 12 bits for other types).
4-bit checksum means 1 in 16. That's why you've written 261,774 (~ 20482 / 16) on the SetBip32() call count?

Quote
                   SetBip32() call count         time
BIP39                    261,774                00:02:44
Electrum-Standard         16,464                00:00:12
Electrum-SegWit            1,064                00:00:02
Electrum-Legacy2FA         1,057                00:00:02
Electrum-SegWit2FA         1,015                00:00:02

I still don't understand why you wrote 00:02:44. There is no machine that can do so many operations in such little time. On my pc, brute forcing a 12-words mnemonic with 2 words missing takes me around 12 hours. (Given only the address)
legendary
Activity: 1039
Merit: 2783
Bitcoin and C♯ Enthusiast
Hi, I have a question. Let's assume that I've forgotten 1 word out of 12. This means that it'll have to try among 2048 combinations. Does it skip the checksum validation? Because if it checks for valid checksums it should not take that much time. For example, when I have 2 missing words, it has to check among 20482 different combinations. But if it counts the checksum, it should take less than an hour.
I explained last time: https://bitcointalksearch.org/topic/m.56129399
Let me know if you have any additional questions.

I remember a thread talking about mnemonic checksum, but I can't find it so I'll ask it here. How many are the valid mnemonics assuming that there is one word missing?
It is not possible to predict because it depends on how many collisions (purely by chance) we are going to get. It usually is somewhere between 120 and 130 for BIP39 and about 6 for Electrum.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
Hi, I have a question. Let's assume that I've forgotten 1 word out of 12. This means that it'll have to try among 2048 combinations. Does it skip the checksum validation? Because if it checks for valid checksums it should not take that much time. For example, when I have 2 missing words, it has to check among 20482 different combinations. But if it counts the checksum, it should take less than an hour.

I remember a thread talking about mnemonic checksum, but I can't find it so I'll ask it here. How many are the valid mnemonics assuming that there is one word missing?
Pages:
Jump to: