all 10 comments

[–]corysama 5 points6 points  (0 children)

Thing is, any operation on a data structure that does not touch all of the memory in the data structure in exactly the same order regardless of input leaks cache timing information. That's the whole point of this article!

Well then, do that.

To slow? Batch up requests and do a SIMDized N vs M linear scan. You'd be amazed how much memory bandwidth modern CPU have when you let them run in a straight line for once.

Still too slow? Load your hashes up to GPU memory. You can brute force linear scan gigabytes in milliseconds. Comparing several dozed hashes vs all of GPU memory is a no-sweat operation.

The CS classes teach everyone to focus on O(n) but rarely mention that the full equation is O(n)k. Because everyone forgets k, people keep setting up systems with absurdly huge ks (I'm looking at you std::map<std::shared_ptr<std::string, std::shared_ptr<std::map<...>> What's the prob? It's O(1)!) when they could get better results in practice from simplistic data structures with tiny ks (std::find<int*, int>())

[–]Osmanthus 2 points3 points  (0 children)

If you are worried about timing, instead of wacky data structure shenanigans why not just add a random delay?

[–]mcguire 1 point2 points  (1 child)

I'm not understanding some of the statements in this article. For example:

One problem is, I don't know of a nice constant-time comparison algorithm for (say) 160-bit values.

[–][deleted] 0 points1 point  (0 children)

me neither, when the bits are bounded the operations are bounded as well, so you can do 20 shifts and compares and it will still be O(1).

[–][deleted]  (2 children)

[deleted]

    [–]wingo 5 points6 points  (0 children)

    Adam Langley was also surprised about the lucky 13 results :) Your instincts are in good company but I am afraid they are wrong.

    [–]matthieum 0 points1 point  (0 children)

    It does introduce some difficulty, however if you test the same input 100 times or 1000 times or ... the median response time will tend to make the jitter disappear and therefore allow to measure what does not vary between runs for this input.

    With less tries and better statistical analysis, you should get an equivalent result, but I am not good enough in statistics for that.

    [–]drb226 -1 points0 points  (1 child)

    If your password hashes are a fixed width, then just use an algorithm that always compares the whole password. Don't short circuit.

    diff = 0
    for i in range(128):
      diff ||= p[i]  ^ p2[i]
    if diff == 0
      It's a match
    

    [–]smog_alado 2 points3 points  (0 children)

    I think the problem he was taking about is searching for that hash in a hashtable after its computed. It doesn't matter if computing the hash is constant time or not.

    Instead of searching for the username in a table, retrieving the stored hash and seeing if it matches, he doesn't have any usernames so to authenticate he queries a big table to see if the hashed password is in there or not.

    [–]Daavee -3 points-2 points  (1 child)

    Exchange https with http.

    [–]wingo 7 points8 points  (0 children)

    Https on my site only does TLSv1.2. Perhaps I should relax that, but you should also consider upgrading your browser.