Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
utils.py89 linesDownload Raw Back to pyotp
1import unicodedata2from hmac import compare_digest3from typing import Dict, Optional, Union4from urllib.parse import quote, urlencode, urlparse5 6 7def build_uri(8    secret: str,9    name: str,10    initial_count: Optional[int] = None,11    issuer: Optional[str] = None,12    algorithm: Optional[str] = None,13    digits: Optional[int] = None,14    period: Optional[int] = None,15    image: Optional[str] = None,16) -> str:17    """18    Returns the provisioning URI for the OTP; works for either TOTP or HOTP.19 20    This can then be encoded in a QR Code and used to provision the Google21    Authenticator app.22 23    For module-internal use.24 25    See also:26        https://github.com/google/google-authenticator/wiki/Key-Uri-Format27 28    :param secret: the hotp/totp secret used to generate the URI29    :param name: name of the account30    :param initial_count: starting counter value, defaults to None.31        If none, the OTP type will be assumed as TOTP.32    :param issuer: the name of the OTP issuer; this will be the33        organization title of the OTP entry in Authenticator34    :param algorithm: the algorithm used in the OTP generation.35    :param digits: the length of the OTP generated code.36    :param period: the number of seconds the OTP generator is set to37        expire every code.38    :param image: optional logo image url39    :returns: provisioning uri40    """41    # initial_count may be 0 as a valid param42    is_initial_count_present = initial_count is not None43 44    # Handling values different from defaults45    is_algorithm_set = algorithm is not None and algorithm != "sha1"46    is_digits_set = digits is not None and digits != 647    is_period_set = period is not None and period != 3048 49    otp_type = "hotp" if is_initial_count_present else "totp"50    base_uri = "otpauth://{0}/{1}?{2}"51 52    url_args: Dict[str, Union[None, int, str]] = {"secret": secret}53 54    label = quote(name)55    if issuer is not None:56        label = quote(issuer) + ":" + label57        url_args["issuer"] = issuer58 59    if is_initial_count_present:60        url_args["counter"] = initial_count61    if is_algorithm_set:62        url_args["algorithm"] = algorithm.upper()  # type: ignore63    if is_digits_set:64        url_args["digits"] = digits65    if is_period_set:66        url_args["period"] = period67    if image:68        image_uri = urlparse(image)69        if image_uri.scheme != "https" or not image_uri.netloc or not image_uri.path:70            raise ValueError("{} is not a valid url".format(image_uri))71        url_args["image"] = image72 73    uri = base_uri.format(otp_type, label, urlencode(url_args).replace("+", "%20"))74    return uri75 76 77def strings_equal(s1: str, s2: str) -> bool:78    """79    Timing-attack resistant string comparison.80 81    Normal comparison using == will short-circuit on the first mismatching82    character. This avoids that by scanning the whole string, though we83    still reveal to a timing attack whether the strings are the same84    length.85    """86    s1 = unicodedata.normalize("NFKC", s1)87    s2 = unicodedata.normalize("NFKC", s2)88    return compare_digest(s1.encode("utf-8"), s2.encode("utf-8"))89 
codekingpro/portable-devtools · Team Ai