def _generate_signature(secret: str, *parts: Iterable) -> bytes: """generate signature using sha1 """ hash_ = hmac.new(tob(secret), digestmod=hashlib.sha1) for part in parts: hash_.update(tob(part)) result = tob(hash_.hexdigest()) return result
def create_secure_value(name: str, value: str, *, secret: str) -> bytes: """create secure value will be following format b'base64 value|timestamp|signature' """ timestamp = tob(str(int(time.time()))) value_b64 = base64.b64encode(tob(value)) signature = _generate_signature(secret, name, value_b64, timestamp) return b"|".join([value_b64, timestamp, signature])
def write_json(self, data): if issubclass(type(data), Mapping): data_str = json.dumps(data) elif hasattr(data, '_asdict'): data_str = json.dumps(data._asdict()) else: raise TypeError("Must to dict-like type") self.headers['Content-Type'] = 'application/json' self._chunks.append(tob(data_str))
def output(self): if 'Content-Length' not in self.headers: self.headers['Content-Length'] = touni( sum(len(_) for _ in self._chunks)) headers = b''.join(b'%b: %b\r\n' % (tob(key), tob(value)) for key, value in self.headers.items()) if self.cookies: headers += tob(self.cookies.output()) + b'\r\n' status = ALL_STATUS.get(self.status_code) return (b'HTTP/%b %d %b\r\n' b'%b\r\n' b'%b' % ( tob(self.version), self.status_code, tob(status), headers, b''.join(self._chunks), ))
def reverse(self, *args): if self._path is None: raise ValueError("Cannot reverse url regex " + self.regex.pattern) assert len(args) == self._group_count, "required number of arguments "\ "not found" if not len(args): return self._path converted_args = [] for a in args: converted_args.append(url_encode(tob(a), plus=False)) return self._path % tuple(converted_args)
def _generate_request(self, method=b'GET', path=b'/', version=b'1.1', accept=b'*/*', accept_encoding=b'gzip, deflate', connection=b'Keep-alive', data=b'', **options): headers = [ b'%b: %b\r\n' % (tob(hkey(key)), tob(value)) for key, value in options.items() ] return (b'%b %b HTTP/%b\r\n' b'Accept: %b\r\n' b'Accept-Encoding: %b\r\n' b'Connection: %b\r\n' b'%b' b'\r\n' b'%b' % (method, path, version, accept, accept_encoding, connection, b''.join(headers), data))
def verify_secure_value(name: str, value: Union[str, bytes], *, secret: str) -> Union[str, None]: """verify the signature if correct return the value after base64 decode else return None """ parts = tob(value).split(b"|") if len(parts) != 3: return None signature = _generate_signature(secret, name, parts[0], parts[1]) # print(signature, parts[2]) if not hmac.compare_digest(parts[2], signature): return None else: return touni(base64.b64decode(parts[0]))
def post(self, path, **headers): request = self._generate_request(path=tob(path), method=b'POST', **headers) response = self._get_response(request) return response
def write(self, str_): self._chunks.append(tob(str_))