Guardando una Java SE 6 Update 10 implementazione, vediamo:
public static boolean isEqual(byte digesta[], byte digestb[]) {
if (digesta.length != digestb.length)
return false;
for (int i = 0; i < digesta.length; i++) {
if (digesta[i] != digestb[i]) {
return false;
}
}
return true;
}
Mentre dopo la correzione vediamo:
public static boolean isEqual(byte[] digesta, byte[] digestb) {
if (digesta.length != digestb.length) {
return false;
}
int result = 0;
// time-constant comparison
for (int i = 0; i < digesta.length; i++) {
result |= digesta[i]^digestb[i];
}
return result == 0;
}
La vecchia implementazione sembra essere più efficiente, dal momento che restituisce false
quando viene trovato il primo byte non uguale, ma presumo che sia stato sostituito perché potrebbe consentire al chiamante di verificare quanto due array di byte di input sono tra loro in base al tempo di esecuzione del metodo.
La nuova implementazione ha sempre la stessa durata (per gli stessi array di lunghezze), poiché itera su tutti gli array (anche se gli array si differenziano per il loro primo byte).
Ho cercato dove viene chiamato questo metodo. Un esempio è engineVerify(byte[] signature)
nella classe com.sun.org.apache.xml.internal.security.algorithms.implementations.IntegrityHmac
, che verifica se la matrice di byte della firma passata è valida confrontandola con un array di byte interno. Prima della correzione, misurando il tempo di esecuzione di quel metodo, si poteva provare a generare un array di byte che avrebbe superato il confronto (più lungo il metodo impiegato per eseguire implica che un prefisso più grande dei due array è uguale).