decred / atomicswap

On-chain atomic swaps for Decred and other cryptocurrencies.
https://blog.decred.org/2017/09/20/On-Chain-Atomic-Swaps/
ISC License
507 stars 232 forks source link

obfuscated secrets: basic extractsecret can fail for non-push-only scriptsig #89

Closed markblundeberg closed 5 years ago

markblundeberg commented 5 years ago

I was thinking some more about atomic swaps today and how Alice might try to obfuscate her secret when redeeming Bob's contract, in order to confuse him long enough to refund her side as well. For example, consider the extraction code here:

https://github.com/decred/atomicswap/blob/master/cmd/bchatomicswap/main.go#L984-L1003

On most bitcoin-based blockchains, Alice can collude with a miner to create a convoluted scriptsig, such as one including the fragment PUSH(<pre-secret>) SHA256 in place of PUSH(<secret>). Here Alice has chosen a random pre-secret ahead of time and used it to calculate secret=SHA256(pre-secret). She needs to collude with a miner to include her strange transaction since it's non-standard (but valid). When the extractSecretCmd() is run on this script, it finds only pre-secret which does not hash to the expected value, and thus it fails.

In general it seems that a full script interpreter would be required to evaluate scriptsig and find out exactly what is on the stack, before the redeemscript starts executing. Only then do you know for sure what the actual secret value is.

(In Bitcoin Cash, starting in November the scriptsig-push-only rule will change from being a relay policy to being a consensus rule, so at least then it will be easy to extract the secret when Alice is on BCH.)

markblundeberg commented 5 years ago

I have a solution to this: disallow all sizes that can be produced as outputs of opcodes. For BTC script, opcodes are only able to output byte strings with sizes 0,1,2,3,4,5,20,32. So, a secret of size 31 or 33 bytes would not be possible to obfuscate.

On BCH, no secret size is safe until the push-only rule activates, due to OP_CAT / OP_SPLIT being able to obfuscate any size of secret.

jrick commented 5 years ago

We can step through the script VM execution to inspect the stack at each step (see https://godoc.org/github.com/decred/dcrd/txscript#Engine.Step).

devwarrior777 commented 5 years ago

Another simpler solution is for some session sequencing code to send the secret in the clear to the participant after the initiator's contract is redeemed and confirmed as mined.

jrick commented 5 years ago

That can't work for two reasons. First, the initiator's contract is the last contract to be redeemed, and is done so by the participant, and requires the secret to redeem. Maybe you meant the participant's contract?

Second, the secret must be revealed to the participant at the exact same moment the redemption of the participant's contract is performed. If not, the entire process is not atomic, and there is nothing stopping a malicious initiator from aborting the protocol and redeeming the participant's mined contract in a way that obfuscates the secret for long enough that the initiator is also able to perform a refund of their own contract.

devwarrior777 commented 5 years ago

You are correct of course I meant the first contract to be redeemed Once the first redeem tx in the mempool the secret is out so that is not atomic. However the secret is not useful to anyone but the participant.

david4neblio commented 5 years ago

@markblundeberg I like your suggestion regarding setting the secret size to a size that cannot be reproduced by op codes. It would seem that would be the easiest to implement.

@devwarrior777 There may not be an incentive for the initiator to send the secret to the participant via other channels. In fact if the initiator was malicious, there would indeed be an incentive to hide the secret from the participant long enough to get a refund.

devwarrior-cool commented 5 years ago

yep .. so I am building a proprietary gui sequencer that manages the whole set of steps in a swap between both parties. That is my 'channel'. The participant will definitely get the secret when the initiator has redeemed and the tx has been mined. The UI will also show the initiator's redeem txid so an astute participant can also get the secret from the transaction signature script before that.

This is perhaps still gameable .. but I have not come up with anything better yet.

As for BCH I expect other atomic swap methods will start to be used (other than straight HTLC)

markblundeberg commented 5 years ago

Just to follow up on this, after gaining some perspective:

markblundeberg commented 5 years ago

One final follow up, that renders this whole thing pretty much moot! P2SH actually includes a rule that the scriptsig must be push-only. So, I think people don't really have to worry about this at all. False alarm, everyone. :-)