Pages:
Author

Topic: Jumblr - decentralized bitcoin mixer with 0.1% fee (Read 4075 times)

newbie
Activity: 41
Merit: 0
https://soundcloud.com/coremediaradio/jumblr Here is the latest on Jumblr fellas
legendary
Activity: 1176
Merit: 1132
But then you trust the initiator of the shuffle to not be an attacker himself. If he occupies the first k spots, it is as if the shuffle starts from k+1. At least in the Nxt core implementation, the shuffle creator is equal to all other participants, and will be penalized the same way if discovered to cheat.
I think in all variants the assumption is that there are non-attacker nodes participating. if the attacker is a passive statistics gathering attacker, i dont see how anything can be done to prevent (or even detect) such info gathering attackers

But if you control, the first two slots and assume at least one other non-attacking node, at least the initiator will get some privacy.

It would be interesting to see the math on how many shuffle rounds are needed to obtain practical privacy. I am thinking at least 10. Assuming there are 100 nodes ready to shuffle, then by making 10 random groupings of ~10 nodes to shuffle with, unless the attacker controls the majority of nodes, it seems to gain privacy.

James
sr. member
Activity: 392
Merit: 250
But then you trust the initiator of the shuffle to not be an attacker himself. If he occupies the first k spots, it is as if the shuffle starts from k+1. At least in the Nxt core implementation, the shuffle creator is equal to all other participants, and will be penalized the same way if discovered to cheat.

I have all parts of the algorithm implemented and working now, including the blame phase of detecting and penalizing rogue participants who either submit invalid data or do not submit their transactions in time, with all integration tests passing. What remains is only to make the shuffle process user friendly, by automating the submission of process/verify/cancel transactions.

For the AES encryption, I now use GCMBlockCipher:

Code:
    public static byte[] aesGCMEncrypt(byte[] plaintext, byte[] key) {
        try {
            byte[] iv = new byte[16];
            secureRandom.get().nextBytes(iv);
            GCMBlockCipher aes = new GCMBlockCipher(new AESEngine());
            CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
            aes.init(true, ivAndKey);
            byte[] output = new byte[aes.getOutputSize(plaintext.length)];
            int ciphertextLength = aes.processBytes(plaintext, 0, plaintext.length, output, 0);
            ciphertextLength += aes.doFinal(output, ciphertextLength);
            byte[] result = new byte[iv.length + ciphertextLength];
            System.arraycopy(iv, 0, result, 0, iv.length);
            System.arraycopy(output, 0, result, iv.length, ciphertextLength);
            return result;
        } catch (InvalidCipherTextException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
legendary
Activity: 1176
Merit: 1132
@timruffing:

On the attack vector with the second and last positions occupied by the attacker. The fact that the initial node is only sending its own vins/vouts seems to create this attack, but of course this streamlining of data offers a lot of speedup.

Anyway, I have an idea to avoid this attack. Why couldnt the initiator of a shuffle occupy the first two spots? this would protect the first node from the 2+last attack wouldnt it? Granted if the attacker is in spot 3+last, it would still leak information, but at least there are two possible accounts and by making one of them like the change outputs and not expecting additional privacy, maybe this will reduce the attack?

Alternatively, what do you think about all (more?) nodes sending their vin/vout to the first node? That would seem to totally thwart the 2nd+last attack

James
legendary
Activity: 1176
Merit: 1132
Okay, my point was the other way: I assume it's not obvious that it is okay to give out the secret key. Indeed, if you look at the description of NaCl, the security model section (http://nacl.cr.yp.to/box.html) and the referenced paper do not claim that the message stays secret in a situation where the senders's secret key is known, even if the recipient's secret key is not.

Still, publishing the sender's key seems to be for that NaCl scheme, and everything else would surprise me, but I haven't looked at it in detail...
OK, it seems safer to just use GCM mode of AES using standard shared secret with a onetime sender keypair

Thanks for the feedback.

James
legendary
Activity: 1218
Merit: 1006
What actually is the mixer means? As i haven't heard this before so i came to this thread but after reading all post i can't get any clue about what the mixer is actually. If anybody don't mind to explain me can you?
Mixer is essentially this
1) You send bitcoins to an address(from the bitcoin mixer service)
2) After the payment is recieved in the address, the service sends you your btc to your 2nd address through a completely random address.
Of course this is just the simplified version of it, most mixer noawadays provide many customizations for added privacy. As as you can probably guess, people do it to hide their tracks that people can track through their transactions.
Thanks for good explanation brother. Maybe i will also try to giveaway bitcoin payouts from my site.
newbie
Activity: 14
Merit: 10
Actually, I don't think we use AES in authenticated mode, here is how it is called, using the BouncyCastle library:

Code:
    public static byte[] aesEncrypt(byte[] plaintext, byte[] key) {
        try {
            byte[] iv = new byte[16];
            secureRandom.get().nextBytes(iv);
            PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
                    new AESEngine()));
            CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
            aes.init(true, ivAndKey);
            byte[] output = new byte[aes.getOutputSize(plaintext.length)];
            int ciphertextLength = aes.processBytes(plaintext, 0, plaintext.length, output, 0);
            ciphertextLength += aes.doFinal(output, ciphertextLength);
            byte[] result = new byte[iv.length + ciphertextLength];
            System.arraycopy(iv, 0, result, 0, iv.length);
            System.arraycopy(output, 0, result, iv.length, ciphertextLength);
            return result;
        } catch (InvalidCipherTextException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

Hm, the security argument depends on the fact that the whole encryption scheme is IND-CCA secure, and CBC does not ensure that. I have even a concrete attack idea with CBC in mind but that would require some additional thinking... (and I prefer to think about countermeasures. Wink ). The general problem is similar to the one with the duplicates. Instead of just duplicating a ciphertext, P2 can try to duplicate and change it such that it decrypts to something similar not exactly the same plaintext. Because it is not exactly the same plaintext, the duplicate check does not help here. A later peer then sees that there are two related plaintexts.
IND-CCA provides exactly the property that you cannot change the ciphertext in a meaningful way. If you try to change it, it does not decrypt at all (decryption error) or it decrypts to garbage, which is not related to the original plaintext anymore. 

Note that the signing that you've described does not help either, because the attacker is one of peers and not just in the network. 

The safe choice is to use GCM mode, which is available in BouncyCastle. Probably you just have to replace CBCBlockCipher by GCMBlockCipher but I haven't read the docs.


Actually I think you assume that it is obvious the secret key cannot be given to everybody, however there is not basis for this assumption.
Okay, my point was the other way: I assume it's not obvious that it is okay to give out the secret key. Indeed, if you look at the description of NaCl, the security model section (http://nacl.cr.yp.to/box.html) and the referenced paper do not claim that the message stays secret in a situation where the senders's secret key is known, even if the recipient's secret key is not.

Still, publishing the sender's key seems to be for that NaCl scheme, and everything else would surprise me, but I haven't looked at it in detail...
legendary
Activity: 1176
Merit: 1132
@TimRuffing

in your paper you say that the change can also be shuffled, but I do not see how it can avoid being correlated due to the specific amount of the change relative to the input. What I have done is separate the outputs into the shuffled amounts and change amounts and treat the change outputs at just one step above the normal unspents.
This is a misunderstanding actually. You don't get any privacy for the change, so we don't say that the change can be shuffled. The paragraph in the paper just clarifies that you can add change addresses to the list of output of the CoinJoin transaction in case some peer does not have the exact shuffle amount (which will be almost always the case, just as for ordinary transactions). As far as I understand, this is what your implementation does?

yes, I shuffle the change treating them as ordinary outputs, but categorize it as "jumblrchange", so it is not counted as being shuffled. though i think it is marginally more private than normal outputs, so given a choice for using inputs it seems the jumblrchange would be a bit better than ordinary unspents

I think you missed that I am generating onetime keypair from the sender side. Only the receiver's pubkey is known.
    crypto_box_keypair(onetime_pubkey.bytes,onetime_privkey.bytes);
    if ( (cipher= encode_str(&cipherlen,src,len,destpubkey,onetime_privkey,onetime_pubkey)) != 0 )

Since this onetime keypair is generated for each packet, I do not see how this is linkable.
I missed that indeed. However, it is still linkable even with new keypairs: assume again that the attacker controls P2 and P50. Then P2 sees which key belongs to P1, and P50 can use that knowledge the determine P1's output address.

You say that this is fixed now by using a common account. How does that work? Did you also change the encryption scheme? The current scheme needs a the secret key even for encrypting. So I don't see how that should work, because you obviously cannot give that secret key to everybody.
Actually I think you assume that it is obvious the secret key cannot be given to everybody, however there is not basis for this assumption.

#define GENESISPRIVKEYSTR "1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b"

The genesis account in NXT is a special account and its privkey is known. So I can use the genesis privkey to encrypt all messages and for decrypting, all nodes use the genesis pubkey (in addition to their privkey)

I did feel there was some sort of clever attack like your P2+Plast and so it is good to go to no leakage at all. If everybody is using the same account, it is like a public payphone, a call from that number doesnt link to any specific person (we ignore the cameras recording the payphone as it is only an analogy)

James
sr. member
Activity: 392
Merit: 250
Mixer is essentially this
1) You send bitcoins to an address(from the bitcoin mixer service)
2) After the payment is recieved in the address, the service sends you your btc to your 2nd address through a completely random address.

This is how a centralized mixer works. The way coin shuffling will work in Nxt is a bit different:

You announce that you want to shuffle for example 10,000 NXT, or join an existing shuffle that somebody else started. You enter in your wallet the recipient address, known only to you, where those 10,000 NXT should be sent. Those are deducted from your account. Each shuffle participant does the same (shuffling exactly the same amount), and each shuffle when created is set to require a certain number of participants (say 20) and the amount being shuffled. When the shuffle completes, each participant finds that amount in the recipient account he specified, yet none of the other participants, and no external observer, can find out which recipient account belongs to which participant.

Shuffling will be possible not only for the NXT coin itself, but for any asset on the NXT Asset Exchange too.

The jumblr service that James is working on is for BTC and similar coins, but the idea is the same.
sr. member
Activity: 392
Merit: 250
Actually, I don't think we use AES in authenticated mode, here is how it is called, using the BouncyCastle library:

Code:
    public static byte[] aesEncrypt(byte[] plaintext, byte[] key) {
        try {
            byte[] iv = new byte[16];
            secureRandom.get().nextBytes(iv);
            PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
                    new AESEngine()));
            CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
            aes.init(true, ivAndKey);
            byte[] output = new byte[aes.getOutputSize(plaintext.length)];
            int ciphertextLength = aes.processBytes(plaintext, 0, plaintext.length, output, 0);
            ciphertextLength += aes.doFinal(output, ciphertextLength);
            byte[] result = new byte[iv.length + ciphertextLength];
            System.arraycopy(iv, 0, result, 0, iv.length);
            System.arraycopy(output, 0, result, iv.length, ciphertextLength);
            return result;
        } catch (InvalidCipherTextException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
where the shared key is obtained as:
Code:
    public static byte[] getSharedKey(byte[] myPrivateKey, byte[] theirPublicKey) {
        return sha256().digest(getSharedSecret(myPrivateKey, theirPublicKey));
    }
    private static byte[] getSharedSecret(byte[] myPrivateKey, byte[] theirPublicKey) {
        try {
            byte[] sharedSecret = new byte[32];
            Curve25519.curve(sharedSecret, myPrivateKey, theirPublicKey);
            return sharedSecret;
        } catch (RuntimeException e) {
            Logger.logMessage("Error getting shared secret", e);
            throw e;
        }
    }

However, after encryption, the full list of ciphertexts that each participant sends to the next becomes a part of the transaction bytes that are signed by this participant (using his regular private key, as derived from the secret phrase without additional nonces, as done for all Nxt transactions). So modifying anything inside the encrypted payload will invalidate the transaction and it will no longer be acceptable in the blockchain. And the transaction that the next participant submits, includes the hash of this previous transaction, so is only valid as a response for this specific encrypted payload.

Note that we use the same method for encrypting messages between Nxt accounts, with the difference that the shared key is derived adding a random nonce for each message, and the regular secret phrase, same for every transaction of this account, is used:
Code:
    public static byte[] getSharedKey(byte[] myPrivateKey, byte[] theirPublicKey, byte[] nonce) {
        byte[] dhSharedSecret = getSharedSecret(myPrivateKey, theirPublicKey);
        for (int i = 0; i < 32; i++) {
            dhSharedSecret[i] ^= nonce[i];
        }
        return sha256().digest(dhSharedSecret);
    }
and after the AES encryption step, same as above, the encrypted text becomes part of the transaction bytes that are signed by the sender.
legendary
Activity: 1176
Merit: 1132
What actually is the mixer means? As i haven't heard this before so i came to this thread but after reading all post i can't get any clue about what the mixer is actually. If anybody don't mind to explain me can you?
Mixer is essentially this
1) You send bitcoins to an address(from the bitcoin mixer service)
2) After the payment is recieved in the address, the service sends you your btc to your 2nd address through a completely random address.
Of course this is just the simplified version of it, most mixer noawadays provide many customizations for added privacy. As as you can probably guess, people do it to hide their tracks that people can track through their transactions.

Step 0) You make the brave decision to trust a third party won't steal your coins, isn't a honeypot, and isn't compromised by hackers/TLAs.
Do you realize with Jumblr, there is no third party that you have to trust?
You dont send coins to any address other than one that you specifiy
plz read the coinshuffle whitepaper for the details.

decentralized mixer != centralized mixer
newbie
Activity: 14
Merit: 10
For the encryption, for each sender we generate a new public/private key pair using curve25519, unique for each sender/shuffle/recipient combination, and then use this plus the recipient public key to generate a DH shared key, then use AES for the actual encryption.
Looks good. Smiley How exactly do you use AES? It must be something that provides authentication, i.e., either an authenticated mode (such as GCM) or a MAC must be added in the proper way.

Independently of James' work, we are also working on implementing coin shuffling using your algorithm in the upcoming version of Nxt. The blame phase is really the complicated part to get right, and here we are taking the approach to disclose the one-time keys used by each participant, to find and penalize the rogue participant. When ready, we would certainly welcome you to have a look at our implementation too.
Sorry, I forgot to reply to that. I offered that already to lyaffe some time ago. I'm not sure if I have the time to go through it line-by-line but I can certainly have a close look. Smiley
legendary
Activity: 2156
Merit: 1072
Crypto is the separation of Power and State.
What actually is the mixer means? As i haven't heard this before so i came to this thread but after reading all post i can't get any clue about what the mixer is actually. If anybody don't mind to explain me can you?
Mixer is essentially this
1) You send bitcoins to an address(from the bitcoin mixer service)
2) After the payment is recieved in the address, the service sends you your btc to your 2nd address through a completely random address.
Of course this is just the simplified version of it, most mixer noawadays provide many customizations for added privacy. As as you can probably guess, people do it to hide their tracks that people can track through their transactions.

Step 0) You make the brave decision to trust a third party won't steal your coins, isn't a honeypot, and isn't compromised by hackers/TLAs.
hero member
Activity: 532
Merit: 500
You have eyes but can see Mt. Tai?!
What actually is the mixer means? As i haven't heard this before so i came to this thread but after reading all post i can't get any clue about what the mixer is actually. If anybody don't mind to explain me can you?
Mixer is essentially this
1) You send bitcoins to an address(from the bitcoin mixer service)
2) After the payment is recieved in the address, the service sends you your btc to your 2nd address through a completely random address.
Of course this is just the simplified version of it, most mixer noawadays provide many customizations for added privacy. As as you can probably guess, people do it to hide their tracks that people can track through their transactions.
legendary
Activity: 1218
Merit: 1006
What actually is the mixer means? As i haven't heard this before so i came to this thread but after reading all post i can't get any clue about what the mixer is actually. If anybody don't mind to explain me can you?
sr. member
Activity: 392
Merit: 250
Thanks for the explanation, now I added a check for duplicate data at each processing step.

For the encryption, for each sender we generate a new public/private key pair using curve25519, unique for each sender/shuffle/recipient combination, and then use this plus the recipient public key to generate a DH shared key, then use AES for the actual encryption. If you take a look at the current way public keys are generated based on secret phrase: https://bitbucket.org/JeanLucPicard/nxt/src/369546f91ba32142562c18d224369ea64a3f0720/src/java/nxt/crypto/Crypto.java?at=master#Crypto.java-63 , for shuffling I have added generation of one-time keys based on secretPhrase plus known nonces:

Code:
    public static byte[] getKeySeed(String secretPhrase, byte[]... nonces) {
        MessageDigest digest = Crypto.sha256();
        digest.update(Convert.toBytes(secretPhrase));
        for (byte[] nonce : nonces) {
            digest.update(nonce);
        }
        return digest.digest();
    }

    public static byte[] getPublicKey(byte[] keySeed) {
        byte[] publicKey = new byte[32];
        Curve25519.keygen(publicKey, null, Arrays.copyOf(keySeed, keySeed.length));
        return publicKey;
    }

    public static byte[] getPublicKey(String secretPhrase) {
        byte[] publicKey = new byte[32];
        Curve25519.keygen(publicKey, null, Crypto.sha256().digest(Convert.toBytes(secretPhrase)));
        return publicKey;
    }

    public static byte[] getPrivateKey(byte[] keySeed) {
        byte[] s = Arrays.copyOf(keySeed, keySeed.length);
        Curve25519.clamp(s);
        return s;
    }

    public static byte[] getPrivateKey(String secretPhrase) {
        byte[] s = Crypto.sha256().digest(Convert.toBytes(secretPhrase));
        Curve25519.clamp(s);
        return s;
    }

and for the one-time keys used in the shuffle, shuffleId and recipientId are used as nonces. Then the one-time sender public key is added to the encrypted data, to allow its decryption by the recipient, yet it is not possible for the recipient (or anyone else) to tell who the sender of each encrypted data is.

If the blame phase needs to be entered, each participant discloses the array of sha256 digests ("keySeeds") used to generate each public/private key pair he used to encrypt to each of the next participants, which allows anyone to decrypt the content ot the data.
newbie
Activity: 14
Merit: 10
@TimRuffing

in your paper you say that the change can also be shuffled, but I do not see how it can avoid being correlated due to the specific amount of the change relative to the input. What I have done is separate the outputs into the shuffled amounts and change amounts and treat the change outputs at just one step above the normal unspents.
This is a misunderstanding actually. You don't get any privacy for the change, so we don't say that the change can be shuffled. The paragraph in the paper just clarifies that you can add change addresses to the list of output of the CoinJoin transaction in case some peer does not have the exact shuffle amount (which will be almost always the case, just as for ordinary transactions). As far as I understand, this is what your implementation does?



Each peer must check that there are no duplicate plaintexts after decrypting. Otherwise attacks on unlinkability are possible.
Is that the same as checking that no two recipient addresses are the same, once the shuffle reaches the last participant, or is there more to it?

Multiple participants submitting the same recipient account would be a trivial attack to counteract, however there is no way to protect against a real sybil attack in which multiple participants, each submitting a different recipient address, are actually controlled by the same entity.
Right, this cannot be prevented. The reason checking for checking for duplicates is indeed different and there's more to it than just checking at the end.

Consider a shuffle of 50 participants with peers P1, ..., P50 (in that order). The attacker controls the two peers P2 and P50. Without the duplicate check, the attacker can break the unlinkability of P1 entirely.

The attack is as follows:
P2 (attacker) receives a single ciphertext from P1 (technically, it's a list of ciphertexts with one entry so far) and removes one layer of encryption, resulting in another ciphertext C1. C1 has still 49 layers of encryption and the inner plaintext is the output address OUT1 of P1.

P2 is now supposed to add his own ciphertext C2 (again 49 layers of encryption, inner plaintext his output address OUT2).
However P2 just duplicates the ciphertext C1, i.e., sets C2 = C1. So P2 sends in fact [C1, C1] to P3.

Then the protocol continues normally but P1's output address OUT1 is now the only one that is there twice. Now assume that the honest participants P3, ..., P49 do not check for duplicates after decryption. The last participant P50 (attacker), who removes the innermost layer of encryption, will obtain a list of 50 output addresses. All of these addresses will be different except for P1's output address OUT1, which is the only address that appears twice in the list! So P50 just knows P1's output address, i.e., unlinkability is totally broken for P1.

To ensure that the attack remains undetected, P50 corrects the list of output addresses before publishing it, i.e., P50 replaces one of the OUT1 entries by an address under the control of the attacker. Note that P2 will not complain that his output address is not there in the final list, because P2 is controlled by attacker, too.

So the attacker can fully deanonymize P1 with only two peers in the right positions. In contrast, if the protocol is implemented correctly, the attacker needs 49 peers to fully deanonymize P1, i.e., everybody expect P1 need to be malicious.

This example where the attacker is in the second and the last position is the worst case for P1 and easy to explain, but the attack works also if the attacker is in other positions and wants to decrease the size of the anonymity set for other peers.



I think you missed that I am generating onetime keypair from the sender side. Only the receiver's pubkey is known.
    crypto_box_keypair(onetime_pubkey.bytes,onetime_privkey.bytes);
    if ( (cipher= encode_str(&cipherlen,src,len,destpubkey,onetime_privkey,onetime_pubkey)) != 0 )

Since this onetime keypair is generated for each packet, I do not see how this is linkable.
I missed that indeed. However, it is still linkable even with new keypairs: assume again that the attacker controls P2 and P50. Then P2 sees which key belongs to P1, and P50 can use that knowledge the determine P1's output address.

You say that this is fixed now by using a common account. How does that work? Did you also change the encryption scheme? The current scheme needs a the secret key even for encrypting. So I don't see how that should work, because you obviously cannot give that secret key to everybody.
legendary
Activity: 2156
Merit: 1072
Crypto is the separation of Power and State.
As amazingly good that xmr is, I think BTC -> BTC is a much easier path as it doesnt have to go through a market trading. unless you are saying that xmr is better than btc?

XMR isn't "better than" BTC for all purposes, but on-chain mixing (via ring signature+steal addresses) is infinitely superior to off-chain obfuscation.
legendary
Activity: 1176
Merit: 1132
let me get this straight. this requires use of 3 block chains? btcd, btc, and nxt? so do we have to download all 3 blockchains on our local to utilize this decentralized coinshuffling?

BTCD and NXT are very low volume, so they are worse than useless for obfuscating BTC tx.

Any significant amount of BTC volume sticks out like a sore thumb on the other two (silent abandoned ghost town) chains.

Use Monero and XMR.to if you want real (ie on-chain zero-knowledge) unlinkablity for your BTC.
There is no converting of BTC to anything. The coinshuffle creates a BTC transaction which uses the BTC blockchain, which is far more volumes than the monero blockchain

the shuffle tx never hits either the NXT or BTCD blockchain. so their volumes are irrelevant

So if you are saying that there is a problem with the coinshuffle algo, I am eager to hear how it is inferior as I am implementing the coinshuffle (without the conflict resolution for now)

As amazingly good that xmr is, I think BTC -> BTC is a much easier path as it doesnt have to go through a market trading. unless you are saying that xmr is better than btc?
legendary
Activity: 1176
Merit: 1132
let me get this straight. this requires use of 3 block chains? btcd, btc, and nxt? so do we have to download all 3 blockchains on our local to utilize this decentralized coinshuffling?
for now it is the quickest way to get it working as I built it on top of InstantDEX

But the BTCD blockchain is not needed even now for this to work for BTC. It is using the NXT address just for a directory. So it would be possible to make it just require the BTC blockchain
Pages:
Jump to: