Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upTiming of block downloads leaks whether or not any notes belonging to the wallet were discovered #95
Comments
This comment has been minimized.
This comment has been minimized.
|
Until we change the way data access works, I'm concerned about option A because it could lead to concurrent access of the SQLite file holding the cached blocks. Since the Rust side of the logic (scanning) and the Kotlin side both use the I'd also like to detect blocks as soon as possible after their availability. Would random time be acceptable? Perhaps with some fixed minimum? I'm thinking at least 10 but up to blocktime/2 seconds. So instead of:
We'd use something like:
Where FIXED_TIME is around 20 seconds or so. @defuse thoughts? |
This comment has been minimized.
This comment has been minimized.
|
I wouldn't recommend the randomized delay approach, due to the following attack: |
This comment has been minimized.
This comment has been minimized.
|
Thank you for the feedback @ftramer this information is very helpful! I'd like to implement changes immediately but I have some questions, to help me understand this correctly:
In our current implementation, the app only downloads blocks while the app is in the foreground. So the attacker would have to 0) know the suspected address of their target 1) catch the target actively using the app 2) either be on the same network, intercepting TLS communications, or have fully compromised the lightwalletd server 3) send many payments across many blocks in order to average out the random delay (it seems like it would take a LOT of payments to do this) 4) and possibly be able to distinguish the other potential sources of timing delays on the mobile device (like switching apps, receiving a phone call or a text or doing other background processing in that thread pool)--which I think just increases the amount of blocks required to pull this off. Does that sound about right or is the attack easier than this? Overall, it seems reasonable to do both things: request blocks on time boundaries and ALSO add some random jitter as one additional obstacle to timing attacks, which might also help Lightwalletd servers have a more balanced distribution of requests. |
This comment has been minimized.
This comment has been minimized.
|
Yes this attack model assumes either a compromised lightwalletd or a network adversary that can passively observe the communication between the mobile device and lightwalletd (e.g., an ISP). I agree that the averaging attack might need many blocks to obtain a reliable signal. This depends on how much longer the transaction processing takes when the wallet is the payee. On my desktop machine, the delay is a few milliseconds. On a weak mobile device it could be much larger. Ultimately, it just seems that requesting blocks on fixed time boundaries is arguably not too complicated and a more private approach than using jitter. Of course combining the two cannot hurt. |
This comment has been minimized.
This comment has been minimized.
|
The delay introduced by the current code is always a multiple of 1 millisecond. Does this still leak a small amount of timing information? |
This comment has been minimized.
This comment has been minimized.
|
It's conceivable that network and other load delay would be sufficient to kill the hundreds of microseconds delay leakage, assuming that the oracle is network-based and not local. I think that's probably a safe assumption on mobile in a practical sense, but it's also something that we could revisit later on. |
This comment has been minimized.
This comment has been minimized.
|
Of course ideally we would just decouple network and wallet operations completely. |
This issue was originally discovered and reported by Florian Tramèr. I'm making it public since no users are currently at risk.
The issue is that the SDK will:
A passive network adversary can measure the time between (1) and (4) to determine whether any notes in the blocks belonged to the wallet. To fix this, either
a. Decouple the network code from the block processing code, such that downloaded blocks are queued up to be processed on a separate thread and the processing won't affect the timing of network requests,
b. Florian's suggestion, to request blocks at absolute time intervals, i.e. instead of sleeping for 20 seconds between requests, request new blocks at times *:00, *:20, *:40. In order for this to not leak information, the block processing MUST always complete before the next request is due to be made.
I recommend (b) since it's easier and we're about to run into even harder side-channel challenges with memo downloading and mempool access.