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
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')
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}')
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)