On 18 September 2015 at 01:11, Tim Peters
Just two things to note:
1. Whatever task-appropriate higher-level functions people want, as you've shown "secure" implementations are easy to write for someone who knows what's available to build on. It will take 10000 times longer for people to bikeshed what "secrets" should offer than to implement it ;-)
Agreed, although the 4 I listed are fairly well-credentialed - the implementations of the first two (raw bytes and integers) are the patterns cryptography.io uses, the token generator is comparable to the Django one (with a couple of extra punctuation characters in the alphabet), and the hex digit generator is the Pyramid one. You can get more exotic with full arbitrary alphabet password and passphrase generators, but I think we're getting beyond stdlib level functionality at that point - it's getting into the realm of password managers and attack software.
2. I'd personally be surprised if a function taking a "number of bits" argument silently replaced argument `bits` with `bits - bits % 8`. If the app-level programmers at issue can't think in terms of bytes instead (and use functions with a `bytes` argument), then, e.g., better to raise an exception if `bits % 8 != 0` to begin with. Or to round up, taking "bits" as meaning "a number of bytes covering _at least_ the number of bits asked for".
Yeah, I took a shortcut to keep them all as pretty one liners. A proper rand_bits with that API would look something like: def rand_bits(bits): num_bytes, add_byte = divmod(bits) if add_byte: num_bytes += 1 return os.urandom(bits) Compared to the os.urandom() call itself, the bits -> bytes calculation should disappear into the noise from a speed perspective (and a JIT compiled runtime like PyPy could likely optimise it away entirely). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia