Comparação de hash de tempo constante

Comparar dois hashes (por exemplo, para verificação de senha ou ao lidar com um HMAC ou id de sessão) pode vazar informações sobre os dados de origem que estão sendo hash.

Usar uma comparação trivial de strings para verificar o hash deixa a
pessoa vulnerável a ataques de temporização . Veja também este post .

Esta pequena função é algo que eu usei para ( tento ) verificar em um tempo constante se dois hashes são iguais

def still_bad_time_constant_compare(string_A, string_B)
result
= true;
string_A
.split("").each_with_index do |c,idx|
result
&&= (string_B[idx].upcase==c.upcase)
end
result

end

Ele simplesmente compara todos os caracteres nas duas strings sem causar curto-circuito na operação na primeira diferença.

Conforme explicado por @khalsah nos comentários abaixo, o operador && = ainda causa um curto-circuito na comparação, portanto, ainda é vulnerável.

Esta é uma maneira correta de fazer isso:

def time_constant_compare(string_A, string_B)
a
= string_A.upcase
b
= string_B.upcase
check
= a.bytesize ^ b.bytesize
a
.bytes.zip(b.bytes) { |x, y| check |= x ^ y.to_i }
check
== 0
end

É basicamente a solução por @khalsah abaixo com a adição das strings (que eu precisava)

NB constante de tempo aqui não significa no sentido big-O (o algoritmo é O (n) no tamanho das strings beng comparadas), mas significa que o algoritmo levará o mesmo tempo para comparar quaisquer duas strings de um dado comprimento