The python code mentioned is still susceptible to timing attacks. Not on the same scale as a bytewise, return on first inequality algorithms, but it's there. The return statement will take longer when the result value is 0, because then it will compare 2 lengths of strings. This could be enough to distinguish between correct and incorrect compares.
Since the usage of zip in that case will only compare the shorter of the strings to the start of the longer string, you can still achieve the timing attack, since the only inconsistency happens on the final comparison.
A better solution would be to check for length equality before doing the zip, or to pad the shorter of the strings compared to the length of the longer. Maybe also to just make the return statement:
Ah, that's a very good point. I've updated the post to return early, since figuring out the short-circuiting behavior across a handful of languages is obviously not my strong suit. Thanks for pointing that out, sophacles.
y/w. This actually brings up an deeper problem too: the vast majority of the timing attacks exist because of little algorithmic optimizations, such as return on first inequality. In most cases such a comparison is desirable, as it is on average 50% faster (depending on specific data characteristics). We as computer people do these sorts of things as second nature, because we have been taught that efficient algorithms are always best. In cases like these, even when I know that there is a major problem being fixed, I cringe at the inefficiencies. It seems also to be a cause of other types of security hole, e.g. "why should I check this data, it should have already been checked, If I do it here, it's a bad redundancy".
Anyway, rambling thoughts aside: thanks for the article.
Since the usage of zip in that case will only compare the shorter of the strings to the start of the longer string, you can still achieve the timing attack, since the only inconsistency happens on the final comparison.
A better solution would be to check for length equality before doing the zip, or to pad the shorter of the strings compared to the length of the longer. Maybe also to just make the return statement:
return (len(a) == len(b)) and (result == 0)
which may be sufficient.