I have used btcrecover several times to help others crack forgotten passwords or incomplete seed phrases.
Sorry, just curious: do others just trust you and provide their phrases/passwords? Or do you provide paid services? I think usually people are able to do the work themselves, they are just not aware of possible tools. As long as it does not require enormous computational power to find lost password, many things could be resolved on quite cheap hardware (it is just a matter of time). If you lost 1-2 words from your seed or you remember parts of wallet password or lost just a small piece of WIF - could be done at home... Most of people who successfully gain access to their coins just disappear, very few of them appreciate help and sometimes toss a coin to their witcher... On the other hand there are professionals for whom it is full-time business - but it requires a serious investments.
|
|
|
I hope that it has been reviewed. I wouldn't like to get a keylogger or so. Does it mean you do not know address and you must check each generated WIF to see what is behind?
That is correct. Database of founded addresses: https://gz.blockchair.com/bitcoin/addresses/Amounts are in satoshis, so 1 BTC looks like "100000000". BTCrecover is OK. edit:a Long time ago I did something very simple for my own tests, now I have found it - maybe someone will make a good use of that. it is java program, I loaded addresses into local database and checked some phrases, with a simple modifications (lower/uppercase etc.), nothing serious. import org.bitcoinj.core.Base58; import org.bitcoinj.core.ECKey; import org.bitcoinj.core.LegacyAddress; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.params.MainNetParams; import java.io.*; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.*; import java.util.Date;
public class Brain {
static final NetworkParameters NETWORK_PARAMETERS = MainNetParams.get(); static final int STATUS_PERIOD = 1000*60*1; static MessageDigest messageDigest; static Statement statement;
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, InterruptedException {
db();
messageDigest = MessageDigest.getInstance("SHA-256"); String filename=args[0]; int skip = 0; if (args.length>1){ skip = Integer.valueOf(args[1]); } FileReader fileReader = null; try { fileReader = new FileReader(filename); } catch (FileNotFoundException e) { System.err.println("not found: " + filename); System.exit(-1); } long count = 0; long start = 0; System.out.println("Brain start"); try { BufferedReader bufferReader = new BufferedReader(fileReader); String line; while ((line = bufferReader.readLine()) != null) { if (line.trim().isEmpty()){ continue; } count++; if (skip>0){ if (count<skip) { continue; } skip = 0; } test(line); test(line.toLowerCase()); test(line.toUpperCase()); if (line.endsWith(",")){ line=line.substring(0, line.length()-1); test(line); test(line.toLowerCase()); test(line.toUpperCase()); } if (System.currentTimeMillis()-start > STATUS_PERIOD){ System.out.println("UP!"+count+" "+ line + " " + (new Date())); start = System.currentTimeMillis(); count = 0; } } }catch (Exception e){ System.err.println(e.getLocalizedMessage()); System.exit(-1); } System.out.println("Brain end"); }
private static void db() {
try{ Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5433/btc", "postgres", "password"); System.out.println("Connected to PostgreSQL database!"); statement = connection.createStatement(); }catch (Exception e){ System.out.println(e.getMessage()); System.exit(-1); } }
private static void test(String text) throws IOException, SQLException { messageDigest.update(text.getBytes("UTF-8")); ECKey ecKey = new ECKey(messageDigest.digest(), (byte[])null); String address = LegacyAddress.fromKey(NETWORK_PARAMETERS, ecKey).toString(); if (checkAddressDatabase(address)){ System.out.println(text + "|" + ecKey.getPrivateKeyAsHex()+"|"+ecKey.getPrivateKeyAsWiF(NETWORK_PARAMETERS)+"|"+address); FileWriter myWriter = new FileWriter("brainResult.txt", true); myWriter.write(text + "|" + ecKey.getPrivateKeyAsHex()+"|"+ecKey.getPrivateKeyAsWiF(NETWORK_PARAMETERS)+"|"+address); myWriter.close(); } ecKey = PrivateKey.fromBase58(NETWORK_PARAMETERS, getCompressedWif(ecKey.getPrivateKeyAsHex())).getKey(); address = LegacyAddress.fromKey(NETWORK_PARAMETERS, ecKey).toString(); if (checkAddressDatabase(address)){ System.out.println(text + "|" + ecKey.getPrivateKeyAsHex()+"|"+ecKey.getPrivateKeyAsWiF(NETWORK_PARAMETERS)+"|"+address); FileWriter myWriter = new FileWriter("brainResult.txt", true); myWriter.write(text + "|" + ecKey.getPrivateKeyAsHex()+"|"+ecKey.getPrivateKeyAsWiF(NETWORK_PARAMETERS)+"|"+address); myWriter.write("\r\n"); myWriter.close(); } }
private static String getCompressedWif(String hex){ String string = "80"+hex+"01"; byte[] digest = messageDigest.digest(hexStringToByteArray(string)); String checksum = bytesToHex(messageDigest.digest(digest)).substring(0,8); byte[] data = hexStringToByteArray(string + checksum); return Base58.encode(data); }
private static boolean checkAddressDatabase(String address) throws SQLException { ResultSet resultSet = statement.executeQuery("SELECT balance FROM public.address WHERE address='"+address+"'"); while (resultSet.next()) { return true; } return false; }
private static String bytesToHex(byte[] bytes) { StringBuffer result = new StringBuffer(); for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); return result.toString(); }
private static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } }
|
|
|
And if you do not know address but you know +- balance, you may always download the list of founded addresses and find potential candidates.
|
|
|
Does it mean you do not know address and you must check each generated WIF to see what is behind?
|
|
|
To conclude: you need tool which will generate keys (wif or hash) for some entry, right? Do you want to use the list of your exact phrases or you want tool to automatically adjust your input (like change to uppercase or add numbers)? Check https://btcrecover.readthedocs.io/en/latest/I would propose to prepare a tool for you (if you have some special requirements), but honestly speaking that program should fulfil yourneeds.
|
|
|
My LATEST version is currently stuck at January 5, 2022. It turns out Blockchair hasn't updated their archives in the last 6 days, and before that their archives were offline for a few days. I'm hoping it will be back online eventually. They informed about troubles, AFAIK something related to situation in Kazakhstan. Archive pages were completely inaccessible recently, now they are back, but with old data.
|
|
|
Just a remark. I am not aware of any tool based on WIF creation which would use GPU. Maybe I am wrong and you have something extra. The problem I see is that with your WIF it is not easy to calculate stride for tools like BitCrack. Like I described in one of my posts (later I will try to find it and attach link) solving by BitCrack is based on: 1) calculating range (or at least startKey) - by base85 decoding WIF with missing characters filled with 1111... Then taking only private key part. 2) calculating stride - as a 58^(index of first missing character from right), then from stride (hex) you must remove last characters (8 or 10) to obtain only the part which has impact on private key. 8 in your case, as you do not have compression flag encoded BUT it works only if last characters of stride are ZEROs. In perfect situation, if you take private part of decoded initial WIF, add shortened stride and encode again, you should receive WIF where missing characters will look like 111112 - having correct stride you "changed" one missing character into next one. But there is also checksum encoded and if your stride collides with checksum (last 8 characters are not ZEROs), then change of private key part is not linear and adding shortened stride in tool which works on private key only would produce wrong results - you may have a lot of luck and hit correct "key/character", or most likely you will miss it.
If you really want to solve your problem, you must first have a proper tool. You must have kind of BitCrack which would calculate address based not on private key + stride, but on "extended" private key (key+checksum) + stride, then cut off checksum part and then check public key, address. I believe it is doable and I have planned to do something like that for a long time, but I never had a good motivation ;-) Maybe now I will start.
|
|
|
Thanks for the help..! This is exactly what i provided in the Console window for privkey importing: which triggered the error of "Invalid private key encoding (code -5)" Is it possible that you made a mistake when you were writing the key? Maybe one or more characters are wrong. You may go to website: https://iancoleman.io/bitcoin-key-compression/ or if you prefer, download it's source https://github.com/iancoleman/keycompression, disable internet connection and launch file "standalone.html". Then copy your key into "Input Key" field and see if it is correctly decoded - to the address you expect. If something is wrong and luckily only 1 or 2 characters are misspelled: You may use my program WifSolver ( https://github.com/PawelGorny/WifSolver) - there is worker 'ROTATE' which should find the correct WIF.
|
|
|
Do you have any compute hardware locally by any chance? GPUs, FPGAs or anything like that?
I can give you a calculation of how many days years it will take using WIF brute-force, if I know what hardware is available.
I made such a calculation for the guy in the other thread and I came around to 3.7 days with 2x nvidia gtx 1070 cards and 8 missing characters.
It was an optimistic estimation for BitCrack. Following that, just multiply 4 days * 58 * 58 * 58... But his problem cannot be converted easily into BitCrack.
|
|
|
Your problem is complicated. Because of the position of missing characters it cannot be quickly and simply converted into problem for tools like BitCrack. You my try using tools for WIFs, like finderouter or my WifSolver ( https://github.com/PawelGorny/WifSolver) but with 11 characters it is rather hopeless - of course you may always try your luck and launch search on subset of base58 characters, not all (for example you may assume that on position X you test only digits). If you have public key (you had outgoing transaction) problem could be potentially solved using my version of Kangaroo, but as it is untouched paper wallet I guess it is not the case. Do you have by chance any other data? Is it hand-written or printed? Do you have maybe (even partially) visible QR code - in the past I was able to restore some WIFs decoding less than half of QRcode. So anything you have may increase your chances.
|
|
|
Nie, BSB nie miał być stable. Jakiś czas temu się tym zainteresowałem, po paru spotkaniach teamowych i rozmowach z developerami odpuściłem, bo wszystko opierało się o jakiś nieokreślony owczy pęd i brand "Zaorski", a technicznie to to miało być nie wiem co... forumo-sklep na którym ktoś mógłby kupować/sprzedawać informacje. Szczególnie pytanie o to "jak będzie zabezpieczona treść, tak aby administrator forum nie będzie miał do niej dostępu, a jedynie kupiec" pozostawała zbywana "będzie pan zadowolony". Co do postaci Rafała Zaorskiego to doceniam szeroką wiedzę i ugruntowany punkt widzenia, ale wydaje mi się ze w tego alta wszedł wyłącznie bo był hype, bez serca. Mpay to chyba po prostu kolejna ofiara/cel albo środek do ugrania swojego. Dziki Trener - nie mam zdania, nie znam. Obejrzalem z ciekawosci pare filmików i stwierdzam że raczej nie jestem w grupie docelowej. Kto to, co to - no idea.
|
|
|
A co z tym projektem Zaorskiego do "przecieków", Big Short Bets? Żyje to czy rozeszło się po kościach jak zebrali ETH którego cena od tego czasu się podwoiła czy potroiła?
|
|
|
~ remaining 8 characters at a combined speed of 400Mkeys/s, over Discord. The estimated runtime is 16 days. ~
These numbers don't look correct. With 8 missing characters it should take less than 4 days (1/4 the reported runtime) to check all permutations. 58^8= 128,063,081,718,016 / 400,000,000 k/s = 320,157 s = 3.7 days
I had different calculations... Anyway, the problem is that OP is unsure about one of known characters, so work must be multiplied *4.
|
|
|
Indeed. He contacted me and we have some estimations. With 10 missing characters it is really doubtful, but as he wants to risk with 2 extra characters, it is more realistic. My estimation for his cards was 400MKeys but with settings he sent me it will be a bit less. Estimation was 11 days, BUT unfortunately he said he is not sure about the beginning, so maybe it will be around 40 days total (11 days for Kz, Ky, Kx and around 7 days for Kw). We will see…
|
|
|
Not really. The rule is that checksum takes last 8 hex characters of decoded WIF. And for compressed there are also 2 characters of compression flag. All together may takes in general last 5 characters of WIF and very often also 6th character. All depends on values of checksum and flag, and how they are convertible to base58. In my WifSolver for wifs with missing end I think I made assumption that last 5 characters are not important (are checksum).
|
|
|
Thanks for the answers.
In particular, is the WIF that begins with: "L1111111111......." a valid private key? Leaving out all the checksum bytes of course so those can be anything. I just want to know if it's valid to place a sequence of 1's inside a private key WIF (I read somewhere that that may not be the case for addresses), as the number "1" in base58 is equal to the number "0" in base10.
Of course. It is just a text in given encoding. It is only our (people) ability to find patterns which looks "nice"... WIF L111111111111111111111111111111111111111111111CbeH6a is fully correct, leads to private key 70cfa0d40309798a5bd144a396478b5b5ae3305b7413601b18767666bdb2f800 which is key like any other... Some strings looks "nice" in binary, others in hex and others in base58 encoding....
|
|
|
Pollard's Kangaroo method also uses a start and end range. However, it does not support strides (AFAIK) because Pollard's Kangaroo algo is using it's own kind of stride while making the tame and wild kangaroos hop. There's no way to tell Kangaroo: "OK, there is a part of the private key at the end that's already known, don't search those bits". The consequence is that for this particular situation, Kangaroo will take longer to find the PK (way too long actually).
Normal Kangaroo yes, but I have already patched it for solving WIFs, custom stride is supported. Link in post above
|
|
|
|