It's unlikely there is an explotable attack here given than network
latencies and variability will swamp any local timing differences but
it's best practice and there's no reason not to.
if Argon2::HashFormat.valid_hash?(hash)
Argon2::Password.verify_password(candidate, hash)
elsif salt.nil?
if Argon2::HashFormat.valid_hash?(hash)
Argon2::Password.verify_password(candidate, hash)
elsif salt.nil?
- hash == Digest::MD5.hexdigest(candidate)
+ ActiveSupport::SecurityUtils.secure_compare(hash, Digest::MD5.hexdigest(candidate))
elsif salt.include?("!")
algorithm, iterations, salt = salt.split("!")
size = Base64.strict_decode64(hash).length
elsif salt.include?("!")
algorithm, iterations, salt = salt.split("!")
size = Base64.strict_decode64(hash).length
- hash == pbkdf2(candidate, salt, iterations.to_i, size, algorithm)
+ ActiveSupport::SecurityUtils.secure_compare(hash, pbkdf2(candidate, salt, iterations.to_i, size, algorithm))
- hash == Digest::MD5.hexdigest(salt + candidate)
+ ActiveSupport::SecurityUtils.secure_compare(hash, Digest::MD5.hexdigest(salt + candidate))
+exit 0 unless ActiveSupport::SecurityUtils.secure_compare(token, digest[0, 6])
exit 0 unless from.active?
exit 0 unless from.active?
-exit 0 unless token == digest[0, 6]
exit 0 if date < 1.month.ago
message&.update(:message_read => true)
exit 0 if date < 1.month.ago
message&.update(:message_read => true)