1. mainly: the C library has no concept of “wrong password”; only “verification failed with an error”. If you want to know why it failed, you need the error. As you can see in the example, a wrong password is "Decoding failed” which can also be your fault. It seems like they want to interpret their own failures as little possible. Therefore raising an exception with the error seemed the best way forward. 2. secondarily: in security context, I tend to prefer loud failures for dangerous problems so they don’t pass unnoticed by accident. ymmv
Just ask Bitcoin miners how hard it is to pick an input which results in a hash with a desired n-bit prefix.
But as a belt-and-suspenders you often see an attempt at fixed time comparisons of digests in any case.
Coincidentally, hashing before comparing can be used in scripting languages where the compare function will often be optimized out from under you, making constant time compare difficult or impossible to actually guarantee.
Booleans are used in a variety of (popular) Python libraries when checking whether a password is correct (e.g. Django's `check_password` returns False if the password is wrong).
def handle_login():
try:
ph.verify(hash, "s3kr3tp4ssw0rd")
log_login()
redirect_to_page()
except VerificationError:
log_bad_login()
redirect_to_login() def handle_login():
try:
ph.verify(hash, "s3kr3tp4ssw0rd")
except VerificationError:
log_bad_login()
redirect_to_login()
else:
log_login()
redirect_to_page()
It's not a big deal for this code, but in general this is good practice because1. It makes it very obvious to the next developer which line is the one that is expected to raise that exception
2. One of the other lines could unintentionally raise that exception and mistakenly trigger the except clause. (This is more of an issue with Python's built in exceptions than with something very specific like this `VerificationError` example.)