1*cda5da8dSAndroid Build Coastguard Worker"""Generate cryptographically strong pseudo-random numbers suitable for 2*cda5da8dSAndroid Build Coastguard Workermanaging secrets such as account authentication, tokens, and similar. 3*cda5da8dSAndroid Build Coastguard Worker 4*cda5da8dSAndroid Build Coastguard WorkerSee PEP 506 for more information. 5*cda5da8dSAndroid Build Coastguard Workerhttps://peps.python.org/pep-0506/ 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Worker""" 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard Worker__all__ = ['choice', 'randbelow', 'randbits', 'SystemRandom', 10*cda5da8dSAndroid Build Coastguard Worker 'token_bytes', 'token_hex', 'token_urlsafe', 11*cda5da8dSAndroid Build Coastguard Worker 'compare_digest', 12*cda5da8dSAndroid Build Coastguard Worker ] 13*cda5da8dSAndroid Build Coastguard Worker 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard Workerimport base64 16*cda5da8dSAndroid Build Coastguard Workerimport binascii 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard Workerfrom hmac import compare_digest 19*cda5da8dSAndroid Build Coastguard Workerfrom random import SystemRandom 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Worker_sysrand = SystemRandom() 22*cda5da8dSAndroid Build Coastguard Worker 23*cda5da8dSAndroid Build Coastguard Workerrandbits = _sysrand.getrandbits 24*cda5da8dSAndroid Build Coastguard Workerchoice = _sysrand.choice 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Workerdef randbelow(exclusive_upper_bound): 27*cda5da8dSAndroid Build Coastguard Worker """Return a random int in the range [0, n).""" 28*cda5da8dSAndroid Build Coastguard Worker if exclusive_upper_bound <= 0: 29*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Upper bound must be positive.") 30*cda5da8dSAndroid Build Coastguard Worker return _sysrand._randbelow(exclusive_upper_bound) 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard WorkerDEFAULT_ENTROPY = 32 # number of bytes to return by default 33*cda5da8dSAndroid Build Coastguard Worker 34*cda5da8dSAndroid Build Coastguard Workerdef token_bytes(nbytes=None): 35*cda5da8dSAndroid Build Coastguard Worker """Return a random byte string containing *nbytes* bytes. 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Worker If *nbytes* is ``None`` or not supplied, a reasonable 38*cda5da8dSAndroid Build Coastguard Worker default is used. 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker >>> token_bytes(16) #doctest:+SKIP 41*cda5da8dSAndroid Build Coastguard Worker b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b' 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Worker """ 44*cda5da8dSAndroid Build Coastguard Worker if nbytes is None: 45*cda5da8dSAndroid Build Coastguard Worker nbytes = DEFAULT_ENTROPY 46*cda5da8dSAndroid Build Coastguard Worker return _sysrand.randbytes(nbytes) 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Workerdef token_hex(nbytes=None): 49*cda5da8dSAndroid Build Coastguard Worker """Return a random text string, in hexadecimal. 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker The string has *nbytes* random bytes, each byte converted to two 52*cda5da8dSAndroid Build Coastguard Worker hex digits. If *nbytes* is ``None`` or not supplied, a reasonable 53*cda5da8dSAndroid Build Coastguard Worker default is used. 54*cda5da8dSAndroid Build Coastguard Worker 55*cda5da8dSAndroid Build Coastguard Worker >>> token_hex(16) #doctest:+SKIP 56*cda5da8dSAndroid Build Coastguard Worker 'f9bf78b9a18ce6d46a0cd2b0b86df9da' 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard Worker """ 59*cda5da8dSAndroid Build Coastguard Worker return binascii.hexlify(token_bytes(nbytes)).decode('ascii') 60*cda5da8dSAndroid Build Coastguard Worker 61*cda5da8dSAndroid Build Coastguard Workerdef token_urlsafe(nbytes=None): 62*cda5da8dSAndroid Build Coastguard Worker """Return a random URL-safe text string, in Base64 encoding. 63*cda5da8dSAndroid Build Coastguard Worker 64*cda5da8dSAndroid Build Coastguard Worker The string has *nbytes* random bytes. If *nbytes* is ``None`` 65*cda5da8dSAndroid Build Coastguard Worker or not supplied, a reasonable default is used. 66*cda5da8dSAndroid Build Coastguard Worker 67*cda5da8dSAndroid Build Coastguard Worker >>> token_urlsafe(16) #doctest:+SKIP 68*cda5da8dSAndroid Build Coastguard Worker 'Drmhze6EPcv0fN_81Bj-nA' 69*cda5da8dSAndroid Build Coastguard Worker 70*cda5da8dSAndroid Build Coastguard Worker """ 71*cda5da8dSAndroid Build Coastguard Worker tok = token_bytes(nbytes) 72*cda5da8dSAndroid Build Coastguard Worker return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii') 73