[NXTmixer announcement]Based on feedbacks and ideas in the NXTcash thread, I think i might have come up with a pretty good NXT mixing algo. I just got a successful encrypt/decrypt cycle in the multigateway. Obviously, still very new as I just started coding this today, but now that I have verified proper public/private key handling, the rest is a matter of debugging.
The initial model supports both a mixing service using the gateway and a totally decentralized direct "payment" path. However, since NXT doesnt support multisig (hint, hint, CfB) the mixing is totally centralized on one of the gateway servers. The decentralized part allows (nearly?) undetectable transmission of NXT acct password (or any other data) directly to the destination acct.
Even though I am adding this functionality to the gateway, it is totally independent of the multisig DOGE gateway and also NXTcash. It just shares a lot of the code base, so it was easiest to add to the existing multigateway code. I am using libnacl
http://nacl.cr.yp.to/index.html that xyzzyx recommended.
Ah, you want to know how it works?
I added the following to the gateway_AM structure:
struct payment_bundle
{
unsigned char escrow_pubkey[crypto_box_PUBLICKEYBYTES];
unsigned char depositaddr[MAX_NXTADDR_LEN];
unsigned char paymentacct_key[crypto_box_SECRETKEYBYTES];
unsigned char txouts[8][MAX_NXTADDR_LEN];
int64_t amounts[8],sessionid;
};
added to gateway_AM:
struct
{
unsigned char publickey[crypto_box_PUBLICKEYBYTES];
unsigned char nonce[crypto_box_NONCEBYTES];
unsigned char paymentkey_by_prevrecv[crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + crypto_box_ZEROBYTES];
unsigned char payload_by_escrow[sizeof(struct payment_bundle) + crypto_box_ZEROBYTES];
};
At the high level there are what I call sessions. Initially, when the activity is low, a session might be as long as a day, but as activity grows, the duration of a session will shrink. It is critical that your transaction isnt the only one in a session, otherwise no amount of anything will help anonymity. If there are 1000 transactions, then with a good system, the best anybody should be able to do is 0.1% accuracy, eg. random guessing.
Each session goes as follows:
A. NXTmixer pays out all the funds that cleared during the last session to the depositaddrs for each NXT addr that received anonymous payment during the session
B. NXTmixer publishes new sessionid and its public key for this session
C. ALL participating nodes publish a SEND_ANONYMOUS_PAYMENTS AM. Yes, I said ALL nodes.
D2. ALL nodes process all of the SEND_ANONYMOUS_PAYMENTS from C and they try to decrypt every paymentkey_by_prevrecv. If they are able to decrypt it (first half matches their previous public key) then they have access to the NXTacct that the password in the rest of the message contains.
D2. NXTmixer also scans all SEND_ANONYMOUS_PAYMENTS from C and processes all payment bundles that properly decrypt. paymentacct_key is for a (temporary) account that is funded with the amount necessary to make all the payments specified in the payment bundle. In order to make sure it wont be emptied and to MIX all the NXT together, the funds required to make all the payments are sent to a shared account. Since NXT is totally fungible, this step is actually VERY effective in removing payment source information.
The NXTmixer updates the credits for each NXTacct during session and when there is enough different payments or max time elapsed, the session ends and we go back to A, where the payments are made.
************
The NXTmixer cannot implement all parts of this by itself, the clients need to implement code that synchronizes all participating nodes. The reason for this is that if everybody is broadcasting, then there is no information leaked when you publish your public key and payment bundle. Since everything is on the same broadcast, anybody can receive the message, but nobody knows if they did or not. This allows a direct transmission of a funded NXT acct to somebody else. Let us assume you will trust them to not drain the account during the next two sessions. Since he is the one paying you, if he does, then whatever deal was in place is off.
userA funds acct A with 10000 NXT
userA encrypts password for acct A using public key of B and it goes into paymentkey_by_prevrecv
userB decrypts the AM and gets the password for acctA and locally verifies that it has 10000 NXT
Now, for the next session, userB sets the paymentacct_key to be the key for acctA and payments can be made from this acctA on behalf of userB, even though userB has NEVER used the password for acctA other than locally to encrypt it into the payment_bundle.
Similarly, you can specify your depositaddr to be an acct that you have never used, but know the password for. Then in later sessions, you can use depositaddr's password as the paymentacct_key. As long as you are receiving payments, you are able to make pretty anonymous payments as I am finding it hard to figure out how anybody can determine payment paths.
Can anybody find any serious flaws with this approach? Should I debug this and add it to the multigateway?
James