Created
June 28, 2023 17:57
-
-
Save jszym/d3c7907b7b6e916f68205c99e5e48922 to your computer and use it in GitHub Desktop.
Namespaced, random token.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from base64 import urlsafe_b64encode | |
from blake3 import blake3 | |
import krock32 | |
from time import time | |
import secrets | |
import math | |
def generate_token(namespace: str) -> str: | |
""" | |
Generates a random, namespaced token with a time component. | |
Example: | |
|-A-|-|------------B--------------| | |
NMSPC-9TWN1-HR7SV-MTX00-0H8VP-YCCJZ | |
A = Namespace, padded to 5 chars. Max 5 chars. Uppercase. | |
B = Blake3 hashed microtime. | |
:param namespace: Namespace for the token. | |
:return: | |
""" | |
if not namespace.isalnum(): | |
raise ValueError("Namespace must be alphanumeric.") | |
if not namespace.isupper(): | |
raise ValueError("Namespace must be entirely uppercase.") | |
if len(namespace) > 5: | |
raise ValueError("Namespace must not have more than 5 characters.") | |
while len(namespace) < 5: | |
namespace = f"{namespace}_" | |
time_bytes = math.floor(time() * 100).to_bytes(6, "little") | |
random_key = secrets.token_bytes(32) | |
hashed_time_bytes = blake3(time_bytes, key=random_key).digest(length=16) | |
encoder = krock32.Encoder() | |
encoder.update(hashed_time_bytes) | |
hashed_time_b32 = encoder.finalize() | |
seg_token = "".join( | |
[ | |
f"{char}-" if (idx + 1) % 5 == 0 else char | |
for idx, char in enumerate(hashed_time_b32) | |
] | |
)[:-1] | |
ns_time_token = f"{namespace}-{seg_token}"[:-1] | |
return ns_time_token |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment