Bad news, testing this I found that your code actually makes the situation worse! I believe the problem is that the &&=
operator still short circuits the comparison, so you're still vulnerable to timing attacks. Additionally since the ruby code is much slower than the native comparison the timing difference is far more pronounced.
The solution given by: http://stackednotion.com/blog/2009/09/09/timing-attacks-in-ruby/ avoids all but one comparison operation at the end by using bitwise operations.
My code (tested in ruby 2, doesn't do upcase)
def safe_compare a, b
check = a.bytesize ^ b.bytesize
a.bytes.zip(b.bytes) { |x, y| check |= x ^ y.to_i }
check == 0
end
Correct me if I'm wrong, but since you're comparing hashes it only gives you a timing attack to find the hash. However if you are using a salt (which you should be) you don't know either of the values being compared, making it very hard to get any information back out at all. Unless I'm missing something this seems to be more trouble than it's worth.
Unless I'm missing the point wouldn't it be easier to use git add --all
. It won't have quite the same results since it will stage all new, modified, and deleted files not just the deleted ones. But that's usually what I want.
Looks like this is actually the expected behavior of zsh and has nothing to do with ruby (that is you would see the same thing for a program in any language run under zsh). For a bit more explination and some possible solutions see: http://unix.stackexchange.com/questions/19530/expanding-variables-in-zsh