mirror of
https://github.com/zulip/zulip.git
synced 2025-10-28 18:43:52 +00:00
python: Use standard secrets module to generate random tokens.
There are three functional side effects: • Correct an insignificant but mathematically offensive bias toward repeated characters in generate_api_key introduced in commit 47b4283c4b4c70ecde4d3c8de871c90ee2506d87; its entropy is increased from 190.52864 bits to 190.53428 bits. • Use the base32 alphabet in confirmation.models.generate_key; its entropy is reduced from 124.07820 bits to the documented 120 bits, but now it uses 1 syscall instead of 24. • Use the base32 alphabet in get_bigbluebutton_url; its entropy is reduced from 51.69925 bits to 50 bits, but now it uses 1 syscall instead of 10. (The base32 alphabet is A-Z 2-7. We could probably replace all of these with plain secrets.token_urlsafe, since I expect most callers can handle the full urlsafe_b64 alphabet A-Z a-z 0-9 - _ without problems.) Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
56546170cf
commit
b7b7475672
@@ -1,10 +1,8 @@
|
||||
import base64
|
||||
import hashlib
|
||||
import heapq
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import secrets
|
||||
from itertools import zip_longest
|
||||
from time import sleep
|
||||
from typing import Any, Callable, Iterator, List, Optional, Sequence, Set, Tuple, TypeVar
|
||||
@@ -107,14 +105,12 @@ def log_statsd_event(name: str) -> None:
|
||||
event_name = f"events.{name}"
|
||||
statsd.incr(event_name)
|
||||
|
||||
def generate_random_token(length: int) -> str:
|
||||
return str(base64.b16encode(os.urandom(length // 2)).decode('utf-8').lower())
|
||||
|
||||
def generate_api_key() -> str:
|
||||
choices = string.ascii_letters + string.digits
|
||||
altchars = ''.join(choices[ord(os.urandom(1)) % 62] for _ in range(2)).encode("utf-8")
|
||||
api_key = base64.b64encode(os.urandom(24), altchars=altchars).decode("utf-8")
|
||||
return api_key
|
||||
api_key = ""
|
||||
while len(api_key) < 32:
|
||||
# One iteration suffices 99.4992% of the time.
|
||||
api_key += secrets.token_urlsafe(3 * 9).replace("_", "").replace("-", "")
|
||||
return api_key[:32]
|
||||
|
||||
def has_api_key_format(key: str) -> bool:
|
||||
return bool(re.fullmatch(r"([A-Za-z0-9]){32}", key))
|
||||
|
||||
Reference in New Issue
Block a user