Below is the message doctorevil sent to inform captain picard, cfb, and opticalc!
We must get this guy to join us as dev!
The disclosure
CfB recently announced on the BCT thread might leave some with questions regarding the exact details. Here's what I sent CfB, Jean-Luc, and OpticalC earlier:
-Gentlemen-
All versions of NXT are currently vulnerable to a transaction replay attack.
I've tested this exploit successfully (TXs 16383865633576457223 and 6120913904145250080).
This message has only been sent to you 3 (Jean-Luc, opticalc and CfB); however, I plan to eventually make a public disclosure.
Specifics:
Anyone on the network can create 15 replicas of a transaction that verify OK but which have distinct transaction ids. This has to do with a phenomenon called signature malleability. Given a valid signature X0, anyone (not just the original signer) can create 15 additional distinct signatures X1, X2 ... X15 which all verify correctly.
The only circumstances in which a transaction can not be replayed are if:
(1) the sender's balance is too low or
(2) the transaction deadline has expired
Example exploit scenario:
BTER currently has a 40M+ NXT wallet it sends withdrawals from. If I was evil, I could transfer 100k NXT back and forth between myself and BTER. Lets say I do this 10 times. A few hours later I could create 15 replays of each withdrawal transaction, netting 1.5M NXT. If I was super evil I could send the replays immediately after each withdrawal, redepositing the new NXT and growing the heist exponentially. One could drain their entire 40M wallet in 3 round trips starting with just 12500 NXT. Eviler still, one could also replay recent transactions flowing into BTER from depositors in order to steal their funds as well, swelling the total catch beyond 40M.
Several possible fixes come to mind:
(1) define a canonical signature representation (bitcoin's approach)
(2) exclude the signature field when calculating the transaction id (probably too sweeping a change at this point)
(3) explicitly check for replays in processTransactions (a bit of a kludge)
The math:
The output of Curve25519.sign is v. This value essentially acts like an element in a finite field who's order is the same as the curve group order (2252+2124). So for any v, you can add 2252+2124 and arrive at a value that is equivalent as far as the underlying field math is concerned. NXT encodes v using 256 bits (32 bytes). Since 2256 is significantly larger than the group order, there are ~16 distinct 256-bit encodings of each field element. Because everyone knows the group order and v is part of the signature, anyone can generate the other encodings to perform this attack.
In closing, I just want to say that it hurts my evil heart not to exploit this.
-Dr. Evil-
This was quickly followed up with some back and forth with CfB where I provided him actual code for the exploit (which I'll elide here for obvious reasons) and a discussion of the plan for how to rollout a fix (which they implemented within hours of initially communicating with them).
He also threw me 10 BTC, which I didn't really expect but greatly appreciated. I got all of jack shit (other than a warm fuzzy) when I privately
revealed to blockchain.info a RNG bug that had already lead to multiple documented thefts.
I'm happy to answer in this thread any remaining technical questions the community might have about the nature of the flaw.