Recoverable Bitcoin Cash wallets

10 248
Avatar for Read.Cash
4 years ago

Please note, this is an unproven idea and a request for comments. Please avoid premature claims until at least a few experts confirm that this is indeed possible and secure. There is only one way to make something secure - to spread the algorithm as wide as possible and have experts poke the holes in it.

Discussion is here or in the comments below.

Feedback overview will be updated here as it happens, positive or negative.

(!) Negative feedback from BigBlocksIfTrue, presenting an interesting vector of attack.

Positive feedback from Karol Trzeszczkowski (who is definitely an expert in my opinion): "This is absolutely going to work, don't worry about that"

Positive feedback from btcfork: "Don't see a reason this couldn't work, and am quite excited by the idea."

Positive feedback from bit-architect: "Beautiful! Very well done" (with caveats)

Steve Shadders from Bitcoin SV points out that it would be possible to create a scheme with similar characteristics on Bitcoin SV next February (but you'd need to safekeep something like a paper wallet) .

Interesting, how sometimes people trying to troll you suddenly make you realize something even bigger about the thing you support (namely: Bitcoin Cash).

Today, I've read this on Reddit:

When at first I read this, I thought the guy was talking about Bitcoin (BTC)'s "Replace-by-Fee", but a cursory glance at his history showed he supports Bitcoin SV and dislikes BTC. Why would he be talking about "recoverability", if SV is no better in this regard than Bitcoin Cash, is beyond my understanding.

Having "recoverable" coins is pretty important (that means that if you lose your private key, you can still recover the access to them), while at the same time you should have the ability to spend your coins daily. (Ok, this point doesn't ring a bell with Bitcoin BTC supporters, I understand)

It seems that these both points are possible on Bitcoin Cash today.

Actually, it can be even be used to safely recover stolen phone's wallet (from the example) if the thief haven't spent the money yet.

A short intro to Bitcoin Cash contracts

A "contract" in Bitcoin Cash allows you to define who can spend the coins. You basically always send the money to a "locking" mechanism and whoever can unlock it - gets to spend the money.

A regular wallet in Bitcoin Cash

Your regular Bitcoin Cash address is a locking mechanism that says "whoever signs a message with the private key that matches in some complex way the number I have written here gets to spend this particular coin" (it's a bit more complex, read our other article for more details if you are interested in details about the contracts).

I sign the transaction and I can spend the coins now
A regular way to buy a coffee and send the change back: you sign a transaction with the private key - that allows you to spend the money

You actually have a whole programming language in Bitcoins (all of them) that allows pretty complex interaction: Bitcoin Script (again, see previous article for more details).

Multi-sig short introduction

You also have something like 2-of-3 multi-signature in Bitcoin Script, which was long thought of as the solution to recoverability. Hopefully, that changes today.

Multi-signature means that you can give 3 different private keys (very big numbers) to friends or institutions you trust and if you need to spend your coins - you can contact two of them and ask them to sign a transaction for you. Alas, it's not convenient and not secure. Let me explain.

Not very secure and inconvenient way for the recovery of the coins

You (actually, your wallet) can construct a special contract address and send your money to it, which has two unlocking functions "regularSpend" and "recover".

If you call the first one ("RegularSpend") - it is the usual spending: private key, address, change address, business as usual:

I'm signing a transaction
Buying my morning coffee with BCH and sending the change back

Or, alternatively, you can send the change to a new address, constructed in the same way - it's all the same, just a bit more secure.

Let's say you've lost your private key and can't sign a transaction. Typically, that means you're out of luck and lost your coins forever.

The second function could be a "recovery" multi-signature unlocking mechanism, where multiple trusted parties (Mom, bank, lawyer) can recover your money and then send any amount anywhere.

So, for 2-of-3 multi-signature that can look like this:

"Mom", "Bank" and "Lawyer" all have different private keys specially for this case
See the problems? Safekeeping, collusion, sending anywhere... Not to mention the usability nightmare to actually do the signing.

This is definitely possible on Bitcoin Cash and probably on BTC and BSV, so we're not any better in this regard.

Now, you can spend your funds daily using the first function, all your change goes the the new contract addresses, which also contain the recovery function.

Downsides:

  • you need to have 2-3 trusted third parties;

  • they must manage the keys for you;

  • they need to be very technically advanced to sign a transaction on your behalf;

  • if they aren't reliable and lose 2 keys - you're out of luck;

  • some of them can collude and send your money anywhere.

A better solution (not yet the best)

When I was writing the previous article about the contracts - the first and the easiest contract that I've explained was very simple. You can supply a "word" that would unlock your funds. So, like you say "read.cash" and you can spend the coins.

Seriously, this address: ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3 has $5 in it as of this writing. These $5 are there courtesy of btcfork's chaintip. Reward for the technically advanced or for fast learner!

To take it you need to just say read.cash in Bitcoin Script and that's it, you don't need my private key. Up for grabs!

You can even see one spending transaction here (I made it for the demonstration purposes):

The transaction was unlocked by the phrase 'read.cash', the second part is not important here, what's important is that it doesn't require my private key.

Can we modify our recovery idea using this new knowledge?

Can you spot the security problem here?

It's almost cool - now you can do your regular spending and you can use an additional way to recover your funds, kind of like a "password", to recover your money if you have lost your private key.

It has a security problem, obviously.

Even though nobody knows what unlocks this address ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3, still if someone can guess that it is "read.cash" - they can send your money anywhere! And it's cheap to guess - you can probably brute-force it in a few minutes to few days.

Sidenote: If you're wondering what "ppfuz.." address does even have to do with the script - it's actually an encoded hash of the locking script. When you lock the money - you don't reveal what the "locking" script is, just its hash. Again, previous article covers it in details.

The best solution

Here's the kicker. Bitcoin Cash has a great operation CHECKDATASIG (here's the story), which checks if the signature of the raw data matches some public key.

Bitcoin (BTC) didn't implement it and is against it. Can't use it there.

Bitcoin SV split away just to avoid adding this operation. Can't use it there.

For many of us it was a non-issue, which added some nice things to Bitcoin Cash.

What's important, CHECKDATASIG enables us to do something interesting (among other things) - it enables us to limit "where" the money goes.

Can you feel it coming? The power of the recoverable wallets exclusively on Bitcoin Cash?

We can now restrict "where" the money would go if somebody uses the secret word. That means we can do things like this:

Or this:

Obviously, even if somebody guesses that your recovery word is "mom" - they'll only be able to send the money to your Mom's wallet. They won't be able to send the money anywhere.

This is not possible to do without CHECKDATASIG operation, therefore it's possible exclusively on Bitcoin Cash. (Unlike Bitcoin BTC and Bitcoin SV)

Ok, let's talk about limitations and problems.

Spending reveals the contract

There is a small problem though - when you spend the money - you reveal what was in the contract. That, in turn, reveals your "recovery" words.

So, your first coffee would reveal the recovery word.

We can avoid it by doing what we do to store the passwords - by storing a salted hash of the password, which cannot be easily decrypted, instead of storing the plain-text password.

We don't do something like this:

verify password == "mom"

but rather

verify hash("abc#431!$" + password) == "871293fe891a298....3e289"

# where, "871293fe891a298....3e289" is the result of hash("abc#431!$mom")
# and "abc#431!$" is a random string called "salt"

Even though it doesn't even make sense to spend the time guessing your recovery word, since all it can do is send the money to your another trusted account (a minor inconvenience at best).

The salt can be probably stored in an OP_RETURN output, since it's needed for the recovery, at least for the first spending.

If the contract was already spent once - the salt can be recovered from the previous spending transaction, probably enabling the application of this to SLP tokens, which require at least 1 OP_RETURN. (I defer to experts on whether this is really possible)

The wallet of the future

If this idea really works that would mean that now when you create a wallet you can, for example add someones address as a "recovery" address with an associated "recovery" word, or you can buy another cheap phone, install a mobile wallet, use its address as a "recovery" address and just forget about the phone until recovery is needed. You can probably even have some institution's address, like a bank, in the worst case.

Lost private key? Just type in your recovery word phone and your last address (more on "how to recover the last address" in the next section) and your wallet will send your money to your phone, from where you can move them to your "recoverable" wallet again.

Even better you can have multiple recovery words and means. And you can change them as often as you want.

Be aware though that contract spending is a bit more expensive, than regular spending, so instead of typical $0.001 transaction fee, you'd pay something like $0.002 or maybe $0.003 each time you spend the money, because of the transaction size.

And you can use your wallet for your daily spending just as your regular Bitcoin Cash wallet - it will just send your change back to the contract or to a new contract using a nonce.

I defer to experts on whether any "replay" attacks are possible here with reusing the old contract. If they are possible - then the new contract should be used each time with a random nonce, not a problem.

Recovering the last address

Ok, there's one more problem to solve.

Even if you can recover the funds - you still need to remember where the funds are, like this address: ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3 and if the address changes after each spending - that means there will be a new address each time.

The good part: the address itself is not a secret. The wallet can publish it as widely as possible or store in on third-party servers in the open or use brute-force approach from any last-known address or transaction.

One way to do it is to use one last known "root" address - from there we can find all the UTXOs that stem from that transaction and try to brute-force them using the provided recovery word.

Brute-force from last-known address

In the worst case the owner can even attempt to brute-force spending all UTXOs (unspent transaction outputs) in existence using the recovery password, which is slow, but feasible. There aren't that many.

We can also filter some UTXOs out that doesn't match some user-provided information about when their last spending was done. Like if the user last used the wallet 2-3 days ago - try only UTXOs around that time.

No last known address, but we still can filter something out before the brute-force. Time is of course "fuzzy" in Bitcoin, so wallet should try additional UTXOs reasonably outside of the range later.

The constantly happening brute-force means though, that the "recovery" word should still be at least a bit harder than "mom" to avoid accidental recoveries (which again is more of a nuisance, rather than a security problem).

Possible solutions for accidental recoveries

Maybe the wallet can add something like the birthdate and wallet provider name (anything easily recallable by user later) to the recovery word of the user to avoid "accidental" recoveries. We're only trying to prevent accidents, there is no point for hackers to try to actively be stealing your funds, since in the end, they can only send it to trusted wallet.

We can use Satoshi-style hash(hash(...)) comparison to avoid disclosing personal information:

verify hash("abc#431!$" + "3298470923874") == "871293fe891a298....3e289"

# where "3298470923874" is hash(birthday + provider + password)
# and, "871293fe891a298....3e289" is the result 
# of hash(salt + hash(birthday + provider + password))

Conclusion

Again, I ask for everybody to wait for experts to weigh in on whether this is something great or it's a spectacular failure, but even if it is - hopefully at least that was an enjoyable read. It's also possible that I've invented something that was already widely known.

Anyway... Let's keep the innovation on Bitcoin Cash going!

By the way, read.cash uses Bitcoin Cash exclusively to upvote the authors (though you can deposit and withdraw other cryptocurrencies to your non-custodial browser-only wallet). You don't even need an account to upvote the articles.

Join us if you are an author (you don't even need to understand Bitcoin Cash to earn it!) and especially if you are a software developer that might benefit from having your own sponsorship program promoted by our affiliates. More about us.

6
$ 14.49
$ 5.00 from @btcfork
$ 5.00 from @molecular
$ 2.84 from Anonymous user(s)
A
+ 4
Sponsors of Read.Cash
empty
empty
Avatar for Read.Cash
4 years ago

Comments

These $5 is there courtesy of btcfork's chaintip

Ahaha, I like it! Now back to reading your fantastic article.

$ 0.00
User's avatar btcfork
This user is who they claim to be.
We have manually verified this user via some other channel.
4 years ago

These $5 is

Damn it. I've read the article like 5 times for typos! How did that "is" get there? :)

$ 0.00
4 years ago

:) 👍

$ 0.00
4 years ago

Now that the $5 is safe, a more serious reply to the proposal. :)

I like the idea of exploring what you can do with spending constraints. Tobias Ruck already demonstrated the possible UX improvement for smart card payments. This fits in the same category of ideas. However, this category of solutions comes also comes with increased transaction size and fees and reduced possibilities for privacy (emulate Ethereum-like accounts, get Ethereum-like poor privacy), so we must carefully evaluate whether the benefits exceed the costs.

Advanced spending constraints could reduce the need to maintain separate hot and cold wallets for some use cases. For example, transactions exceeding some daily/weekly limit could require additional authorisation, not unlike spending constraints in the banking system. In case of a lost/stolen wallet, this could help you to reclaim your wallet's contents before a finder/thief can.

The main problem I see is that the solution is designed for when you lose your private key, but you can only send to pre-selected trusted wallets. But if you are able to keep the private key for this trusted wallet safe, why can't you simply keep a safe back-up of your main wallet as well? You can even encrypt this wallet back-up with a password, or even write down the encrypted back-up on a piece of paper (existing wallet software can do this today). You also need to keep some record of the public address where the funds are, so you could simply keep the encrypted seed words in the same place.

Another issue is the likely brute-forceability of the password, since there is no rate limit for guessing (and everyone can see the challenge publicly on the blockchain). To prevent this, you both need long passwords (e.g. 20 characters or more) and a lot of sequential rounds of hashing to attach a real computational cost to each guess. People are notoriously bad at remembering long complex passwords the seldomly use.

I agree with Jonathan Silverblood's comment that safekeeping a (possibly encrypted) physical back-up is much easier overall - and also more secure against evil mothers.

$ 0.00
4 years ago

You're claiming in one paragraph that people are really bad with something as simple as making and keeping a long password and then you suggest that people are better off keeping encrypted private key...

Ok, I agree and it was pointed in Steve Shadders comments that yeah, this whole scheme in theoretical sense is basically safekeeping a second private key. However, again, we're talking about people. It's easier to safekeep a phone, than a piece of paper. It's easier if your relative has a wallet installed for you, rather than tracking where that encrypted file is on the internet.

As for the brute-force I'll have to again return to the idea that no dedicated hacker would spend time brute-forcing people's wallets, since he got nothing to win from it, except maybe schoolyard bragging rights.

So, my point is that we need to protect from accidental recoveries rather than malice. In that case I think the scheme that I replied to Jonathan is more than enough - stretch a password with email/birthday+wallet provider name and you have low/near zero (in case of an email) change of accidental recovery. hello@read.cash|bitcoincom|phone would do as a password. Again, like I said to Jonathan - we can use hash(hash()) to protect the privacy.

Again, there's a whole section on why you don't NEED to keep account of your public addresses (it's nice, but you don't need it). The space to search is not that big (UTXOs for last few days as specified by user about his/her last usage).

Personally, I trust my wife's phone (where I would have a spare wallet installed that she wouldn't use) much more than any cloud provider to safekeep my encrypted private key (and myself that I would remember the password for that key) and not delete my account because of some stupid reason. That's assuming I'm smart enough to encrypt my private key and safekeep it.

This is the third time I explain this. Either I'm stupid and fail to see something obvious, or it's the case of "If your ideas are any good, you'll have to ram them down people's throats." - Howard Aiken

$ 0.00
4 years ago

While I'd generally recommend people to encrypt their hard drive anyway (once remembered, you'll never forget this password because you use it daily), you could also give an unencrypted back-up to your mother/wife if you trust her.

I think it is confusing that you say "password", but you really mean something more like "username". A password protects against malice, a username just identifies. You enter your username into a recovery programme, and then it sends all your funds to a pre-chosen secondary wallet. I can see an advantage of choosing your username yourself instead of remembering the seed words the gods randomly select for you. But even then I feel like you can just store the primary wallet's seed along with the secondary wallet - an attacker who can get hold of the secondary wallet could guess the username anyway.

If the secondary wallet is safe, you can also safely store your primary wallet's seed words there (my solution). If the secondary wallet is not safe, then the guessable "password" (your solution) will not provide adequate security either. An attacker who accesses the secondary wallet can steal your funds in either case. This is why I don't understand the intended advantage of your solution compared to my solution (unless you add other useful spending constraints).

BTW if you store the hashed username on-chain and the username contains personal data like day of birth, then you still need to protect it against brute-forces to prevent people from stealing your personal data (even if they can't steal the money).

$ 0.00
4 years ago

That's an interesting vector - hacking the recovery wallet first. The attacker would hack the wallet of my wife and then it's an easy guess for him that my "username" could be "wife". This is definitely something that needs thinking.

If the secondary wallet is safe, you can also safely store your primary wallet's seed words there

I still have a feeling that this is not necessarily true. For example, it's very easy to install a secondary wallet on someone else's phone and forget about it at all. No passwords, no safekeeping at all. As long as that user has the phone - the phone safekeeps the private key. On the other hand - it's not exactly easy to store "primary key" safely on the phone. Where would someone keep it? Probably in "Notes" application. I think you'd agree that a good wallet would protect private key better than "Notes", right?

That's why I have a feeling that this is not exactly if A therefore B: "If the secondary wallet is safe, you can also safely store your primary wallet's seed words there", but rather B is much more complex ritual for humans than A.

$ 0.00
4 years ago

For the notes-on-phone case I would say the secondary wallet is not safe. If you can come up with a good solution for this case, that would indeed be useful. :)

$ 0.00
4 years ago

From my perspective, the person claiming that regular people will never use non-recoverable money is probably wrong - practically everyone used or use physical non-recoverable cash in the last 10 years.

From a cost perspective, the added cost to every transaction, while small, might be undesirable. One way to work with this here though, is to use this passwording scheme for savings rather than spending. This extra costs might also be solved in the future when we adopt a new transaction format.

From a privacy perspective, there's some interesting quirks here, like the incentive to use a common password so that your addresses are not uniquely recognizable, and to recover other peoples money whenever you need to recover yours to hide who may or may not have been the initiator of the recovery.

From a security perspective though, I think that's where the main pain point is. The mechanism relies on humans to effectively remember passwords. And not just passwords, but specifically passwords they do not frequently use. I have a hard time remembering my old passwords and since this recovery is for an event where things have gone wrong, I'm not sure human memory is the better option, compared to making backups easier with physical hardware.

This is an interesting idea, and it could very well get some use, but I would personally rather see a common standard for how to do NFC backups, then have people apply physical security to their recovery assets.

$ 0.00
4 years ago

Actually, you can use the simplest password possible, like "mom", but the wallet would have to do some simple password-stretching, like 1) add user's email or birthday to the password 2) add wallet's provider name - some things that are easily rememberable for user, but will help avoid collisions for accidental recovery.

All we're trying to do is to prevent accidental collisions in recovery, since there is no point why would hackers dedicate resources to that, since they can't claim the money - it'll go to "mom's wallet" anyway.

But as an afterthought I think we need to go even deeper Satoshi-style and compare hash(hash(email + password + providername)) == hash(hash(email + password + providername)) to avoid disclosing email (or birthday)

$ 0.00
4 years ago