Lo stai facendo con complessità inutile.
In primo luogo, hai una query SQL complessa, che dovrebbe essere evitata. La tua logica di business non dovrebbe essere scritta in SQL. Vorrei usare SQL solo per le query e implementare la logica in Java. Essenzialmente, il tuo codice sembra che tu non voglia implementare la logica in Java, e quindi esegui le modifiche SQL per mantenere il codice Java non modificato il più possibile. Perché è così?
In secondo luogo, stai sprecando preziosi cicli della CPU.
Aggiungi una sospensione casuale con un intervallo di tempo approssimativo adeguatamente definito, all'incirca lo stesso tempo necessario per verificare l'hash. Fallo se l'utente non viene trovato. Ciò rende impossibile per il cliente ottenere informazioni sui tempi, e salva anche preziosi cicli della CPU dormendo sinceramente invece che in loop. Potresti aggiungere un po 'di casualità comune ai percorsi di codice "non trovato" e "trovato" per renderlo ancora più sicuro, per impedire alle persone di accedere troppo velocemente.
Come dovrebbe essere la casualità? Per il percorso del codice "non trovato", ottenere la deviazione standard e la media dei tempi di calcolo dell'hash della password per molti campioni (ad es. 1000), quindi approssimare questo con un Distribuzione gaussiana . Per il percorso di codice comune, è necessario aggiungere più deviazione standard rispetto al percorso di codice "non trovato".
Inoltre, potresti assumere il ruolo di attaccante e provare a fare analisi statistiche per quanto sia difficile tramite le informazioni di cronometraggio possibile verificare se c'è un solo indirizzo email. Se ci vuole più di un minuto, sono sicuro che nessuno elencherà i tuoi indirizzi email, ma attaccherà solo quelli isolati. Se impiega più di un'ora, probabilmente non verranno interrogati anche quelli isolati.
Inoltre, potresti voler limitare in qualche modo le richieste provenienti da un singolo indirizzo IP. Vorrei utilizzare l'algoritmo token bucket per consentire le burst di accesso, ma limitare la velocità degli accessi a lungo termine. Ciò renderebbe anche più difficile enumerare gli indirizzi e-mail o persino interrogare quelli isolati.