Successful recovery from 2014 Bitcoin paper wallet (invalid checksum)

Bitcoin paper wallet

Note: This recovery is not directly related to ledger, but when I posted it on the r/bitcoin subreddit (which seemed more appropriate), it was deleted by the admins for unknown reasons.

—- TL;DR

Client bought some BTC in 2014, and stored them on a so-called “paper wallet”. They still had the address of the BTC (that we could still see on the blockchain, unmoved since 2014), and the paper wallet with the private key. Unfortunately, the private key checked out as “invalid” (i.e. bad checksum) each time client attempted to access the wallet, for the last 10 years.

Client provided us the photo of the paper wallet showing the private key, and a partial QR code. Client generated and printed the paper wallet using one of the “BTC paper wallet generator” websites that was popular at the time to generate “BTC paper wallets”.

(parts of the private key photo have been redacted for privacy)

We were able to find the issue with the printed private key and recover the BTC.

The likely cause of the issue is that the font data was somehow corrupted on the computer that printed the private key at the time.

—- Long version:

Read the TL;DR first.

This photo was the only version of the private key that client had. It is not very sharp, but good enough to read all the characters. And it contained a partial QR code.

The private key is in so called “wif” format (Wallet Import Format), encoded in base58, with 51 characters. The “wif” format used for BTC private keys is basically a raw BTC private key, with 4 bytes of double-SHA256 checksum added at the end, and encoded in base58.

The partial QR code could have been useful to figure out what was wrong with the private key. But we did not find any free or opensource tool that could easily extract usable data from a partial QR code. So we decided that for now, it would be too much effort to try using information from the partial QR code image.

Looking at the private key, most characters (including those that we redacted) were absolutely unambiguous.

The first questionable character, on the right of the first X, looks like a circular blob, but it can only be an “e”, as the other lowercase candidates (“o”, “s” and “a”) appear later on, and are clearly distinct.

The next character, just before the next “X”, looks like a vertical bar, so it could be an “l” (lowercase L), an “I” (uppercase i), an “i” or a “1” (digit). Lower case “L” and uppercase “I” are not allowed in base58. The digit “1” always has a part sticking out at the top-left, so we decided it was not “1”.

The last possibility is “i”, but strangely there is no visible space under the dot of the “i”. But if you look further, you see a character that is clearly a “j” (lowercase J), and it too does not have a visible space under the dot. So we were pretty sure our “l” was in fact an “i”.

The next interesting character, on the right of the second “X”, looks like a “7” but with a vertical bar, instead of the normally diagonal bar of the “7”. But there is no other base58 character that looks like it, so we figured that this font had a “stylized” shape for the glyph “7”. This “7” character appears at 3 locations in the string, as you can see.

The resulting “wif” string we got was incorrect (bad checksum), and that was a string that our client had already tested. And even ignoring the invalid checksum, the private key did not lead to the account where the BTC were.

So we decided to do a bruteforce search, assuming that up to 3 characters in the “wif” string were completely incorrect.

We needed the code to check that a “wif” string checksum was valid, and to generate the corresponding BTC address (that we had in “wif” format too, i.e. a so called legacy BTC address). In fact, there are two formats for the “wif” BTC address: One is referred to as “public key (uncompressed), and the other one as “public key (compressed)”, and from the BTC address we had, it was not possible to know what format it was using – without knowing the private key. So we had to generate both addresses (uncompressed and compressed) for each private key, to check if one of them matched our known BTC address.

Since we did not have the code to calculate the BTC public keys from the “wif” private key, we asked ChatGPT to help us:

  • ChatGPT, can you write a python function that converts a Bitcoin private key into the bitcoin public address?
  • Sure, here's a Python function that converts a Bitcoin private key into the corresponding Bitcoin public address: …

All the code that we got from ChatGPT was bogus (e.g. it forgot to call the elliptic curve function!!), and we told it to the AI:

  • Thank you for catching that mistake! Now the code should work correctly [no, it still had bugs!]. I apologize for the mistakes in the code. As an AI, I aim for accuracy, but occasionally errors slip through. I appreciate your patience and understanding.

ChatGPT saved us some time, but we still had to spend several hours debugging, fixing and optimizing ChatGPT's code, and testing that it worked correctly using some test-cases.

We then started the bruteforce search for 3 wrong characters anywhere in the “wif” string (which was estimated to take a few days using no GPU).

While the bruteforce search was running, we thought that in fact, the only really questionable character was this strange “7” with the vertical bar. So we modified the bruteforce search to only test all possible base58 characters at the 3 positions where those strange “7” characters appears.

After a few seconds, we hit our BTC public key! So we found the correct private key: The character looking like a “7” was in fact a “T”, with the right part of the horizontal bar missing.

So the likely explanation is that the font data for the “T” glyph was somehow corrupted on the computer that printed the private key at the time.

The BTC were finally recovered, with a small bonus in Bitcoin Cash (BCH) and Bitcoin Gold (BTG), from those BTC forks.

In the same Recovery series:

Successful Recovery Story: How we recovered 100 ETH from an old Ledger Nano S with firmware 1.0 (seed lost!)
byu/loupiote2 inledgerwallet

Successful Recovery of BTC from a HW.1 Ledger Wallet with Firmware 1.0.0 (seed lost!)
byu/loupiote2 inledgerwallet

Nano S with 1.2 firmware vs EIP-155: Successful recovery of 24 ETH and $50+k worth of ERC-20 tokens (seed lost)
byu/loupiote2 inledgerwallet

Successful recovery of 70 ETH (EIP2333) in validator on the beacon chain (seed lost)
byu/loupiote2 inledgerwallet

Nano S with Firmware 1.2: 539 ETH recovered successfully (seed lost)
byu/loupiote2 inledgerwallet

Successful recovery of $137k worth of cryptos from invalid seed phrase (two incorrect words!)
byu/loupiote2 inledgerwallet

reddit image

10 thoughts on “Successful recovery from 2014 Bitcoin paper wallet (invalid checksum)”

  1. The Ledger subreddit is continuously targeted by scammers. Ledger Support will never send you private messages. Never share your 24-word recovery phrase with anyone, never enter it on any
    website or software, even if it looks like it’s from Ledger. Only keep the recovery phrase as a physical paper or metal backup, never create a digital copy in text or photo form. Learn more at
    https://reddit.com/r/ledgerwallet/comments/ck6o44/be_careful_phishing_attacks_in_progress/

    If you’re experiencing battery problems, check out our [troubleshooting guide](https://support.ledger.com/hc/en-us/articles/4409233434641-How-to-troubleshoot-Ledger-Nano-X-battery-issues?
    support=true). If you’re still having issues head over to the My Order page to explore options for replacement or refunds. Learn more here.

    I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

  2. So you have enough experience to debug, read and understand & compile or run a python code that ChatGPT offers to you but you cannot find an opensource qr code reader / didn’t search “qr code github” on google / or thought it’s a big hassle? Probably one of the highest opencourced type of an app. Other than that, you can use a throw-away cheap android phone without network to decode the qr code and then destroy it?

    Sorry but your thinking method sounds like a you are not a productive person😬

    Btw you should also learn to notice those weird ASCII/Unicode characters because it’s one of the best common methods to phish users on the internet. Anyway, you’ve got a good lesson.

  3. Lol /r/bitcoin removing good content like this… disapointing.

    I really like the walkthrough especialy the use of chatgpt. I like it, AI so good it compute the public key without using ec curves =)
    Maybe it can also divide in eliptic space that would be nice =)

  4. For those who want to learn how to do this sort of thing yourself give BTCRecover a go https://btcrecover.readthedocs.io/

    It would have knocked this one over no problem at all. (Has supported single key paper wallets for a few years)

    Hopefully you never need to make use of it πŸ™‚

  5. Very good. You are helping people and making a living while doing it!! Doesn’t get better than that.

Comments are closed.