Esempio n. 1
0
def encrypt_password(password, salt=None):
    """Encrypt a password string"""
    if salt is None:
        # salt = os.urandom(8)
        salt = generate_random_str(random_length=8)
    assert 8 == len(salt)
    assert isinstance(salt, str)
    assert isinstance(password, str)
    result = password
    for i in range(10):
        result = HMAC(bytes(salt.encode('utf-8')),
                      bytes(result.encode('utf-8')), sha256).hexdigest()
        # result = str(result)
    return salt + result
Esempio n. 2
0
def encrypt_password(password, salt=None):
    """Hash password on the fly."""
    if salt is None:
        salt = os.urandom(8) # 64 bits.

    assert 8 == len(salt)
    assert isinstance(salt, str)

    if isinstance(password, unicode):
        password = password.encode('UTF-8')

    assert isinstance(password, str)

    result = password
    for i in xrange(10):
        result = HMAC(result, salt, sha256).digest()
    return salt + result.encode('hex')
Esempio n. 3
0
def user_auth(username,
              token=None,
              password=None,
              prompt=None,
              totp=None,
              psbt_file=None,
              debug=False,
              version3=False):
    """
    Indicate specific user is present (for HSM).

    Username and 2FA (TOTP, 6-digits) value or password are required. To use
    password, the PSBT file in question must be provided.
    """
    import time
    from hmac import HMAC
    from hashlib import pbkdf2_hmac, sha256

    dryrun = True
    with get_device() as dev:
        dev.check_mitm()

        if psbt_file or password:
            if psbt_file:
                psbt_hash = sha256(psbt_file.read()).digest()
                dryrun = False
            else:
                psbt_hash = bytes(32)

            pw = token or click.prompt('Password (hidden)', hide_input=True)
            secret = dev.hash_password(pw.encode('utf8'), v3=version3)

            token = HMAC(secret, msg=psbt_hash, digestmod=sha256).digest()

            if debug:
                click.echo("  secret = %s" % B2A(secret))
                click.echo("    salt = %s" % B2A(salt))

            totp_time = 0
        else:
            if not token:
                token = click.prompt('2FA Token (6 digits)', hide_input=False)

            if len(token) != 6 or not token.isdigit():
                raise click.UsageError("2FA Token must be 6 decimal digits")

            token = token.encode('ascii')

            now = int(time.time())
            if now % 30 < 5:
                click.echo(
                    "NOTE: TOTP was on edge of expiry limit! Might not work.")
            totp_time = now // 30

        #raise click.UsageError("Need PSBT file as part of HMAC for password")

        assert token and len(token) in {6, 32}
        username = username.encode('ascii')

        if debug:
            click.echo(" username = %s" % username.decode('ascii'))
            click.echo(
                "    token = %s" %
                (B2A(token) if len(token) > 6 else token.decode('ascii')))
            click.echo("totp_time = %d" % totp_time)

        resp = dev.send_recv(
            CCProtocolPacker.user_auth(username, token, totp_time))

        if not resp:
            click.echo("Correct or queued")
        else:
            click.echo(f'Problem: {resp}')
Esempio n. 4
0
class TencentAuth(AuthBase):
    sign_key = ""
    key_time = ""
    expire_time = -1
    sign_mode = None
    service_name = None

    def __init__(self, config):
        self.expire_seconds = config.expire_seconds or 10
        self.secret_key = config.secret_key or ""
        self.secret_id = config.secret_id or ""
        self.mode = config.use_mode or "headers"

    def build(self):
        time_now = int(time.time())
        end_time_stamp = time_now + self.expire_seconds
        self.expire_time = end_time_stamp
        key_time = f"{time_now};{end_time_stamp}"
        self.sign_key = HMAC(self.secret_key.encode("utf8"),
                             key_time.encode("utf8"),
                             "sha1").hexdigest().lower()
        self.key_time = key_time

    def build_kv(self, path_url):
        plist = path_url.split("?", 2)
        _base = plist[1] if len(plist) == 2 else None
        if not _base:
            return "", ""
        _param = {}
        for _signal_param in _base.split("&"):
            if "=" in _signal_param:
                k, v = tuple(_signal_param.split("=", 2))
            else:
                k = _signal_param
                v = ""
            if k not in _param:
                _param[k] = v
            else:
                if isinstance(_param[k], list):
                    _param[k].append(v)
                else:
                    _param[k] = [_param[k], v]

        klist = sorted(_param.keys())
        # 字典序排序
        _values = []
        for k in klist:
            _p = _param.get(k, "")
            if isinstance(_p, list):
                _p = sorted(_p)
                _values.append("&".join([f"{i}={_p}" for i in _p]))
            else:
                _values.append(f"{k}={_p}")
        _value = "&".join(_values)
        # XXX: 需要注意,这里有缺陷,因为lower中的dict_order会受到影响
        _k = ";".join(klist).lower()
        return _k, _value

    def build_header_kv(self, headers):
        _klist = sorted(headers.keys())
        _values = []
        for k in _klist:
            _v = headers.get(k, "")
            _values.append(f"{k.lower()}={parse.quote(_v, safe=[])}")
        _value = "&".join(_values)
        _k = ";".join(_klist).lower()
        return _k, _value

    def use_signature(self, signature: Dict[str, str], r):
        if self.mode == "headers":
            _vs = []
            for k, v in signature.items():
                _vs.append(f"{k}={v}")
            r.headers["Authorization"] = "&".join(_vs)
        elif self.mode == "args":
            r.prepare_url(r.url, signature)

    def custom_auth(self, r):
        if time.time() > self.expire_time:
            self.build()
        pk, v = self.build_kv(r.path_url)
        hk, hv = self.build_header_kv(r.headers)
        http_string = "\n".join(
            [r.method.lower(),
             r.path_url.split("?")[0], v, hv, ""])
        signed_string = "\n".join([
            "sha1", self.key_time,
            sha1(http_string.encode("utf8")).hexdigest().lower(), ""
        ])
        signed_header = HMAC(self.sign_key.encode("utf8"),
                             signed_string.encode("utf8"),
                             "sha1").hexdigest().lower()
        signature = {
            "q-sign-algorithm": "sha1",
            "q-ak": self.secret_id,
            "q-sign-time": self.key_time,
            "q-key-time": self.key_time,
            "q-header-list": hk,
            "q-url-param-list": pk,
            "q-signature": signed_header
        }
        self.use_signature(signature, r)
        return r

    def v3_auth(self, r):
        body_dict = json.loads(r.body or "{}")
        method = r.method.upper()
        path_url = r.path_url.split("?")
        uri = path_url[0]
        query = path_url[1] if len(path_url) != 1 else ""

        hkv = list(
            zip([i.lower() for i in r.headers.keys()], r.headers.values()))
        hkv.sort()
        cheaders = "\n".join([f"{k}:{v.lower()}" for k, v in hkv]) + "\n"

        signed_headers = ";".join([i for i, _ in hkv])
        body = b"" if r.body is None else r.body \
            if isinstance(r.body, bytes) else r.body.encode("utf8")
        hash_request_payload = sha256(body).hexdigest()
        ws = "\n".join((method, uri, query, cheaders, signed_headers,
                        hash_request_payload))

        al = "TC3-HMAC-SHA256"
        rt = int(time.time())
        cs = datetime.utcfromtimestamp(rt).strftime("%Y-%m-%d") + "/" + \
            self.service_name.lower() + "/tc3_request"
        hcr = sha256(ws.encode("utf8")).hexdigest()
        ws2 = "\n".join((al, str(rt), cs, hcr))

        sd = HMAC(
            ("TC3" + self.secret_key).encode("utf8"),
            datetime.utcfromtimestamp(rt).strftime("%Y-%m-%d").encode("utf8"),
            "SHA256").digest()
        ss = HMAC(sd, self.service_name.encode("utf8"), "SHA256").digest()
        ss2 = HMAC(ss, b"tc3_request", "SHA256").digest()
        signature = HMAC(ss2, ws2.encode("utf8"), "SHA256").hexdigest()
        authorization = al + " Credential=" + \
            self.secret_id + "/" + cs + ", " + \
            "SignedHeaders=" + signed_headers + \
            ", Signature=" + signature

        qs = dict([_q.split("=", 1) for _q in query.split("&") if query])
        qs.update(body_dict)

        r.headers["Authorization"] = authorization
        r.headers["X-TC-Action"] = qs.get("Action")
        r.headers["X-TC-Version"] = qs.get("Version")
        r.headers["X-TC-Region"] = qs.get("Region")
        r.headers["X-TC-Timestamp"] = str(rt)
        return r

    @contextmanager
    def use_v3(self, service_name):
        self.sign_mode = "v3"
        self.service_name = service_name
        yield
        self.sign_mode = None

    def __call__(self, r):
        if self.sign_mode == "v3":
            return self.v3_auth(r)
        else:
            return self.custom_auth(r)