They steal your database and cannot crack a single password
Picture the worst Monday: someone walked off with a dump of your users table. Emails, names, and the password column. The good news is that you do not store passwords in the clear — you store hashes, with Argon2id . The bad news is that this matters less than it seems . Why the hash alone is not enough Argon2id makes every attempt cost memory and time. It is a real defence and you should use it.…
In a worst-case Monday scenario, a malicious actor could steal your users table, which includes users' emails, names, and hashed passwords. Despite storing passwords as hashes using Argon2id, this isn't as secure as it seems. The hash alone is not sufficient to protect against brute force attacks. Argon2id does make each attacker's attempt costly in memory and time, but the attacker holding your database can afford to take their time.
They don't need to guess passwords randomly; they can start with leaked password lists and use powerful GPUs rented by the hour.
The real problem is that the attacker has everything they need: the hash, salt, and parameters are all in the same database dump. They can compute the whole function on their own. To mitigate this, consider adding a secret key, known as a pepper, to the hashing process. However, there are two major issues with this approach: it often leaks with the database, and it cannot be rotated.
An Oblivious Pseudo-Random Function (OPRF) can help solve these issues by making the secret live in another service, keeping it separate from the database. An OPRF allows for the computation between two parties, with each party sending blinded data to the server, which applies its secret key and returns noise. The client unblinds the noise and stores the resulting value, which is then hashed with Argon2id and stored securely.
This way, the attacker holding your database cannot test a single candidate offline, as they need to communicate with the OPRF service for each attempt, subjecting them to rate limits, quotas, and logs.
The main challenge with OPRF is that if the service is compromised or uses the wrong key, it returns incorrect values, and this issue cannot be detected. This is why the verifiable OPRF (VOPRF) variant is crucial. The server attaches a DLEQ proof to demonstrate that it used the correct key, and the client verifies it using a pinned public key.
However, the public key must be pinned out of band, meaning the client cannot simply ask the server for the key during verification. Implementing this solution in Django is possible by installing the 'quipu-oprf-django' package and configuring the settings accordingly. The server can be self-hosted as an open-source AGPL project or paid for as a service at oprf.xiliux.com.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.