Closed AntoineRondelet closed 6 years ago
Thanks for the typo @shapeshed, and of course, the abi shouldn't have been committed, I explained how to generate it in the tuto, so it was an error. Should be fixed now :)
IMO the ABI should be committed. It allows people to more easily use a deployed contract without having to go through the multi-stage compile process. For example, with Parity - copy pasta the ABI file into the 'Contract' window and it gives you a nice UI to do stuff with.
If it becomes stale you have bigger problems, just add it into the Makefile.
I agree promoting ease of use is important so don't have any objections to the ABI being included. Providing the path of least resistance is obviously important at this phase of the project.
To lubricate the 'path of least resistance' you need a CLI app which you can point at an EthRPC instance and let it do its thing. Similar to the Dash 'Mixer' for Private Send. Orbital doesn't currently do that.
If you were to make a quick specification for a tool that does that, what would the command-line options be?
Think of:
deposit
(ETH, ERC-20, ERC-223) - converts the amount into denominations, sends to mixer, logs the private keys in your own databasesend
(ETH, ERC-20, ERC-223) - like deposit
, but somebody else is the owner.withdraw
- Retrieve denominations equal to the total amount from the database, performs withdraw
into a specific accounttransfer
- Change the owner of denominations equal to the total amount to a different set of public keys belonging to somebody else.mix
- Perform 'mixing' operationsThe problem is that, with denomination based stuff, and the gas payer problem, you basically lose all anonymity if you perform the operations too fast because that opens up correlation analysis attacks and makes it really damn easy to determine the total amount, time of transfer, who transferred etc.
With a normal style mixer it would spread the operations out over the course of whichever time-period you want, say a day, week or month.
It would also be good to have a 'mix rounds', where it will automagically perform the mixing for N rounds.
But none of that really works very well when you have to wait for rings to fill up, and it's all linked back to a single account (the gas payer). Compared to a mixer with UXTOs you have less privacy because of the gas payer problem.
But... need a tool that will implement the best practices as far as mixing goes, preferably some kinda proxy service over a .onion (which incentive) to hide the original gas payer, and then you might have something worth using outside of the 'gated community private blockchain thing' where there are much much better solutions to privacy that don't require ring signatures but nobody is listening to me.
Hum... What would the mix
command do @HarryR ? I don't really get the idea here. Please tell me if I am wrong, but as far as I understand, the privacy solution proposed by Mobius relies exclusively on the use of ring signatures along with stealth keys. The "mixing" is done "automatically". If Alice wants to send Bob 1 ether, she has to send 1 ether to the Mixer along with Bob's stealth public key (derived from Bob's master public key), in order to constitute the ring. Then, to withdraw, Bob has to wait for the ring to be full and derives some temporary keys used to generate a new address and provide a signature to claim his funds (some funds/denomination coming from some sender) from the Mixer.
Looking at the following scenario, I don't really understand what you mean by 'mixing operations' ?
For the CLI, I agree that it would be a good idea. I'll look into it, however, this would be the object of another PR. This PR only aims to recap the manipulations that one has to play around with Mobius as it is implemented for now :)
Yup I totally agree this would be a separate issue, but I'm just getting my thoughts out there and trying to think of ways that would make it more usable to a wider audience.
So the problem with mixing, and the mix
command, is that I don't think one round is not enough for sufficient privacy. My reasoning behind it is as follows:
With a ring size of 4 there's a 25% probability of any input being related to any output, if I deposit 1 ETH and you withdraw 1 ETH, any observer will know that the two parties are related with a probability of 1/4.
If you try and send an amount, broken into denominations, e.g. 1 ETH, 0.2 ETH and 0.03 ETH (sums to 1.23 ETH), the same Ethereum address will deposit all 3, and a different Ethereum address will withdraw all 3. At this point neither side has any anonymity, I can see 1.23 deposited, 1.23 withdrawn, therefore I know Alice send 1.23 to Bob.
Stealth addresses and one-time keys don't matter if the gas payer (e.g. Alice's or Bob's account) links multiple deposits or withdraws to each other. I am looking at the weakest links, pieces of information which allow transactions to be correlated or linked to each other etc. Such as: total or specific amounts, gas payer, multiple rings with the same participants etc.
Inference of the sender and recipient isn't that difficult, CoinJoin/CoinShuffle is fundamentally broken from an anonymity perspective, as are most BitCoin mixers (like... in-practice, people gone to jail because of it, it simply doesn't offer strong enough privacy guarantees). With Ethereum you are at even more of a disadvantage because the account which pays for Gas links all the transactions together.
In order to withdraw Bob has to wait for the ring to be full and derives some temporary keys in order to generate a new address and sign to take his funds from the Mixer.
Then Bob submits the ring signature from his account, or puts enough Gas into a new account and uses that to submit the ring signature to withdraw etc.
Lets think about side-channels for a minute, and you'll see what I mean:
So, how do we tackle this?
1) By carefully and repeatedly performing 'mix' operations you are reducing the probability of Alice and Bob being linked. A mix operation is depositing into another ring directly from a ring without the funds being temporarily deposited. After 1 mix operation the probability of Alice and Bob being linked should around 6% (1 / 4 / 4
? or am I missing some probability theory there...), the more mixing operations you perform the lower the probability gets until the point where everybody is statistically related to everybody else (the ideal). For mix
, instead of Withdraw
it would be WithdrawThenDeposit
- you provide it with the ring signature for Withdraw
and the public key to be used when it's deposited into the next ring.
2) Provide a proxy service which will anonymously submit transactions on your behalf to obscure the origin address, if you perform this over Tor, or with some kind of insecure legal BS contract which says 'I promise to not deanonymise you' (which... is not a strong privacy guarantee) then correlating Alice and Bob becomes more difficult as long as you cannot correlate the two by seeing the same denominations from the same rings move at the same time.
3) Wait for 'account abstraction' which means the mixing contract can pay for its own gas, e.g. you send from '000...' address and the contract pays the miner (but oh, wait... in 'enterprise blockchain' there are no miners, or Gas... so wtf am I even rambling on about). But you still have the problem of the total sum of the denominations moving at the same time making it easy to link deposit and withdraw unless it's carefully spread out over time, across multiple rings, multiple points of de-linking.
4) Don't do denominational splitting, Monero tried that and it got deanonymised very quickly... this isn't a hypothetical academic attack, this is real. DO NOT DO DENOMINATIONAL SPLITTING UNLESS YOU ARE VERY VERY CAREFUL ABOUT SPREADING THE INFORMATION OUT OVER A LONG TIME PERIOD. Even then, it is very fragile, and fragile crypto = bad crypto.
5) Implement RingCT, see https://github.com/solidblu1992/ethereum for full implementation.
6) Use Monero, or ZCash. I don't mind rolling my own crypto, but lol... no. There is better solution, I prefer win rather than pain.
From my perspective I am looking at the evolution of privacy technology over the past 10 years, the evolution of mixers, the different stages of development that Monero and ZCash went through, the advantages and disadvantages of technology like ZeroCoin and Dash's 'Private Send' and come to the conclusions which I have outlined above.
My concern is that I am not confident in the current design of Mobius to achieve anywhere near a comparable level of privacy compared to even the most rudimentary and somewhat flawed approaches which are in widespread use today (Dash... and the previous incarnations of Monero's design).
I would like the address them through, which is why I am writing this comment.
The weak point of Mobius is indeed the fact that the recipient has to pay some gas to retrieve his funds. This is undoubtedly the door wide open for an attacker to carry out an analysis and infer links between the recipient's multiple addresses.
If you try and send an amount, broken into denominations, e.g. 1 ETH, 0.2 ETH and 0.03 ETH (sums to 1.23 ETH), the same Ethereum address will deposit all 3, and a different Ethereum addresses will withdraw all 3. At this point neither side has any anonymity, I can see 1.23 deposited, 1.23 withdrawn, therefore I know Alice send 1.23 to Bob.
I'm not sure if this is as straightforward as you described it. In the case where Alice wants to send 1.23 eth to Bob, split into 1, 0.2 and 0.03 denominations, she needs to generate 3 stealth public keys from Bob's master public key. Here the "stealthiness" protects Bob. A passive attacker would not be able to distinguish between the case where Alice is doing a split payment to Bob (unique recipient) OR the case where she is doing a payment to 2 or 3 different recipients. Thus Bob should be able retrieve the funds without being worried about his identity being leaked by Alice's deposit. However, once again, Bob needs to have gas on his accounts to pay the gas of the withdrawals... which is the point where the attacker would be able to exploit side-channel leaks of information to threat Bob's anonymity.
The 'wait for the ring to fill' is a big problem because it allows anybody else to de-anonymize you by actively participating.
Interesting attack scenario indeed ! The n-1 participants of a ring of size n could collude to de-anonymize a participant (Bob) by filling the ring. I do not really see how using "multiple layers" of rings, alone, could protect Bob in such a scenario. The only solution that appears to me (although I would need to put more thoughts into it) would be to use multiple layers (or mixing rounds) of rings of DIFFERENT SIZES (although I directly see that doing this introduces a lot of problems and complexity to the system...). That way the n-1 attackers' payments trying to unveil the identity of Bob would be spread over multiple rings and other anonymous recipients. This would spread the group of attackers and introduce indistinguishably during the withdrawal.
I'm not sure if this is as straightforward as you described it. In the case where Alice wants to send 1.23 eth to Bob, split into 1, 0.2 and 0.03 denominations, she needs to generate 3 stealth public keys from Bob's master public key.
Ignore stealth keys, they are noise. Tag X/Y is noise. Ignore the noise.
Who | Action | Amount |
---|---|---|
Alice | Deposit | 1.0 |
Alice | Deposit | 0.2 |
Alice | Deposit | 0.03 |
Bob | Withdraw | 1.0 |
Bob | Withdraw | 0.2 |
Bob | Withdraw | 0.03 |
I have personally seen this approach being used to de-anonymise IRL, but without the 'Who' column... now think about that for a second. This approach has been tried, it has been proven to be insecure. You add the 'Who' column and it becomes 1000x easier.
You have to wait for other people to join your 'mixing session', and now you have another point where privacy can be removed.
You use denominational splitting instead of 'confidential values' and you have yet another point where privacy can be removed.
I have also seen arbitrary ring sizes be used IRL to de-anonymise people. There is a reason the TX fee in Zcash is fixed, there is a reason why Monero are very seriously considering making the ring size fixed. If you are able to decide the ring size for yourself you have human bias interfering with privacy, every single time that happens you create another opportunity for anonymity to be removed.
Spreading it out over multiple rings is good, but if you allow the ring size to be chosen by the participant then 1) because of the weird Mobius design you are reducing the number of peers that will participate in the mix, and 2) you are opening yourself to correlation attacks by your own choices. (e.g. if I leave ring size at 8, and only perform transactions with 'maximum privacy' then I'm the only person doing that, or at least the sample size is much smaller, so now my own choices mean I am identifiable versus everybody using the defaults).
Likewise with 'mixing' by putting things into a ring and then taking them straight back out, there was a recent academic study where they realised that a bunch of people were doing really really insecure things with ZCash - see: https://arxiv.org/pdf/1712.01210.pdf - It's only secure if it stays 'within the privacy system'. If it goes in then comes out you have little to no privacy because the values can be correlated exceedingly easily.
I really want to help you understand the kinds of problems that are being faced, but I fear it may not be helpful for you or the company to point out this kind of thing, but hey - that's what they hired me for.
Lets work on something more productive instead: https://github.com/clearmatics/mobius/issues/12
Also, see: http://coinjoinsudoku.com/
I have personally seen this approach being used to de-anonymise IRL, but without the 'Who' column...
In the case of Mobius, your array would most likely look like:
Who | Action | Amount |
---|---|---|
Alice (using Bob's spk1) | Deposit | 1.0 |
Alice (using Bob's spk2) | Deposit | 0.2 |
Alice (using Bob's spk3) | Deposit | 0.03 |
Bob (address 1) | Withdraw | 1.0 |
Bob (address 2) | Withdraw | 0.2 |
Bob (address 3) | Withdraw | 0.03 |
Which would translate in something like this from an attacker perspective:
Who | Action | Amount |
---|---|---|
Alice | Deposit | 1.0 |
Alice | Deposit | 0.2 |
Alice | Deposit | 0.03 |
Recipient 1 | Withdraw | 1.0 |
Recipient 2 | Withdraw | 0.2 |
Recipient 3 | Withdraw | 0.03 |
Now regardless of the gas problem for the recipient, the attacker here has to answer the question: "What are the links between recipient1, 2 and 3 ?", to which the answers would either be:
Answering this question with a decent probability is pretty hard in the case where we assume that:
1) The problem of the gas payer is ignored (each newly created address has a sufficient balance to call the Withdraw function)
2) A sufficient amount of transactions are handled by the system (A large amount of participants doing a large amount of Tx on the network). This hypothesis is important to guarantee that all 3 scenarios of the question "What are the links between recipient1, 2 and 3 ?"
are indistinguishable.
My question here is: "How an attacker could point determine the relationship between recipient1,2 and 3 with good probability ?". As first glance, timing information doesn't seem to be sufficient to guarantee the success of the attack (thanks to hypothesis 2). Moreover, Amount
could be used to link Alice to one of the recipient, but the relationship between recipients is still obfuscated in this case...
Anyway, the answer to my question might be presented in academic publications that I haven't read yet. Do you have good resources to provide me on these points ?
See:
I give up, enjoy the project m8.
This branch contains a README which resumes the list of commands a user has to run in order to do a payment through Mobius. Please try and run the "tutorial" and tell me if something's missing/unclear :)