This is my attempt to answer my own equally named question on SO. In this case, I need a method comparing two strings so that the running time is input independent.
// Not private in order to prevent optimizations.
static class Blackhole {
private static void eat(long n) {
dummy += n;
}
// Not private in order to prevent optimizations.
static volatile long dummy;
}
public boolean areEqual(String input, String secret) {
final int length = secret.length();
// No need to keep the length secret.
if (input.length() != length) {
return false;
}
long delta = 0;
for (int i = 0; i < length; ++i) {
// Any char is interpreted as a non-negative number.
// Xoring such numbers preserves non-negativity.
// The result depends on every input bit, so no short-circuit is possible.
// Overflow is impossible, therefore diff is zero <=> all chars are the same.
delta += input.charAt(i) ^ secret.charAt(i);
}
Blackhole.eat(delta);
return delta == 0;
}
It's a really short snippet and I'm mainly interested in ensuring that it really works in constant time. In particular, I'm afraid that the loop could indeed get optimized to something like
int i = 0 for (; ; ++i) { if (input.charAt(i) != secret.charAt(i)) break; } for (; i < length; ++i) { delta += input.charAt(i) ^ secret.charAt(i); }
where the first loop could be faster on some architectures, as -- after unrolling -- it translates to load, xor with memory, and a conditional jump. Assuming some future architecture capable of executing 6 instructions per cycle when there are no data dependencies and no mispredictions, it could be a win. Or the JIT could believe, it makes sense...
Concerning the Blackhole
, I wonder if volatile
is necessary. I didn't want to depend on JMH nor copy this monster.
In the meantime I've got an idea avoiding volatile writes nearly perfectly
private static void eat(long n) {
if (n == dummy) {
dummy = new SecureRandom().nextLong();
}
}
52**37 = 2e66
possibilities. Gaining or losing a factor of 10 (or a million) just doesn't count. \$\endgroup\$intern()
? :-D \$\endgroup\$