December 10: Python Cryptographic Service Modules
Shhh! 🤫 As part of the Python Standard Library traversal, after yesterday's
look at file format modules, today is going to be all about secrets.
Well, all about secrets
and hmac
and hashlib
, to be precise.
Highlights
- There's an awful lot of hash algorithms in
hashlib
. - The
secrets
module exists and is suitable for (reasonably) strong randomness, eg for generating long secret URLs.
hashlib
The hashlib
module grants access to a ton of hash algorithms – not all of which are strong or safe. Please hash data
responsibly and make sure you're up to date on safe choices etc etc. There is one constructor for each algorithm, named
after the lower-cased algorithm. All of these return hash objects, which you feed (byte!) data with update()
and get
output with digest()
or hexdigest()
. You can pass usedforsecurity=False
to every constructor to permit the use of
insecure and blocked algorithms in restricted settings.
algorithms
Supported hash algorithms (on most platforms) are MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 (plus the SHA3-* variants
where appropriate), BLAKE2b, BLAKE2s, SHAKE-128 and SHAKE-256. algorithms_available
will return a set of all currently
available algorithms.
Apart from regular hashing functions, you can (and should!) be using key derivation functions for secure password
hashing, which can be configured with a salt and a number of iterations and some other parameters. Use pbkdf2_hmac
or
scrypt
.
hmac
hmac
implements the HMAC RFC, which serves to verify both the data integrity and the authenticity of a given message.
It relies on a secret cryptographic key, which you have to manage separately. As with all cryptography, make sure you
know what you're doing, and that you wouldn't be better off using libraries to handle this for you. Use of the module is
straightforward, but please remember to use compare_digest
instead of ==
to protect against timing attacks.
secrets
If you want secure random numbers, eg for password hashing or secret storage, use secrets
and not random
! Use
choice()
to pick an element out of a secret, randbelow
to pick a number between 0 and the argument, and randbits
to get an integer with n random bits. Use token_bytes
, token_hex
or token_urlsafe
to generate secure tokens, eg
for hard-to-guess URLs or password resets. You can specify the length in bytes, or rely on Python to pick a safe (and
increasing, over the years) default value.