17db96d56Sopenharmony_ci"""Generate cryptographically strong pseudo-random numbers suitable for 27db96d56Sopenharmony_cimanaging secrets such as account authentication, tokens, and similar. 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ciSee PEP 506 for more information. 57db96d56Sopenharmony_cihttps://peps.python.org/pep-0506/ 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci""" 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci__all__ = ['choice', 'randbelow', 'randbits', 'SystemRandom', 107db96d56Sopenharmony_ci 'token_bytes', 'token_hex', 'token_urlsafe', 117db96d56Sopenharmony_ci 'compare_digest', 127db96d56Sopenharmony_ci ] 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ciimport base64 167db96d56Sopenharmony_ciimport binascii 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_cifrom hmac import compare_digest 197db96d56Sopenharmony_cifrom random import SystemRandom 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci_sysrand = SystemRandom() 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_cirandbits = _sysrand.getrandbits 247db96d56Sopenharmony_cichoice = _sysrand.choice 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_cidef randbelow(exclusive_upper_bound): 277db96d56Sopenharmony_ci """Return a random int in the range [0, n).""" 287db96d56Sopenharmony_ci if exclusive_upper_bound <= 0: 297db96d56Sopenharmony_ci raise ValueError("Upper bound must be positive.") 307db96d56Sopenharmony_ci return _sysrand._randbelow(exclusive_upper_bound) 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ciDEFAULT_ENTROPY = 32 # number of bytes to return by default 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_cidef token_bytes(nbytes=None): 357db96d56Sopenharmony_ci """Return a random byte string containing *nbytes* bytes. 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci If *nbytes* is ``None`` or not supplied, a reasonable 387db96d56Sopenharmony_ci default is used. 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci >>> token_bytes(16) #doctest:+SKIP 417db96d56Sopenharmony_ci b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b' 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci """ 447db96d56Sopenharmony_ci if nbytes is None: 457db96d56Sopenharmony_ci nbytes = DEFAULT_ENTROPY 467db96d56Sopenharmony_ci return _sysrand.randbytes(nbytes) 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_cidef token_hex(nbytes=None): 497db96d56Sopenharmony_ci """Return a random text string, in hexadecimal. 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci The string has *nbytes* random bytes, each byte converted to two 527db96d56Sopenharmony_ci hex digits. If *nbytes* is ``None`` or not supplied, a reasonable 537db96d56Sopenharmony_ci default is used. 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci >>> token_hex(16) #doctest:+SKIP 567db96d56Sopenharmony_ci 'f9bf78b9a18ce6d46a0cd2b0b86df9da' 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci """ 597db96d56Sopenharmony_ci return binascii.hexlify(token_bytes(nbytes)).decode('ascii') 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_cidef token_urlsafe(nbytes=None): 627db96d56Sopenharmony_ci """Return a random URL-safe text string, in Base64 encoding. 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci The string has *nbytes* random bytes. If *nbytes* is ``None`` 657db96d56Sopenharmony_ci or not supplied, a reasonable default is used. 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci >>> token_urlsafe(16) #doctest:+SKIP 687db96d56Sopenharmony_ci 'Drmhze6EPcv0fN_81Bj-nA' 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci """ 717db96d56Sopenharmony_ci tok = token_bytes(nbytes) 727db96d56Sopenharmony_ci return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii') 73