def make_cookie_content( name, load, sign_key, domain=None, path=None, timestamp="", enc_key=None, max_age=0, sign_alg="SHA256", ): """ Create and return a cookies content If you only provide a `seed`, a HMAC gets added to the cookies value and this is checked, when the cookie is parsed again. If you provide both `seed` and `enc_key`, the cookie gets protected by using AEAD encryption. This provides both a MAC over the whole cookie and encrypts the `load` in a single step. The `seed` and `enc_key` parameters should be byte strings of at least 16 bytes length each. Those are used as cryptographic keys. :param name: Cookie name :type name: text :param load: Cookie load :type load: text :param sign_key: A sign_key key for payload signing :type sign_key: A :py:class:`cryptojwt.jwk.hmac.SYMKey` instance :param domain: The domain of the cookie :param path: The path specification for the cookie :param timestamp: A time stamp :type timestamp: text :param enc_key: The key to use for payload encryption. :type enc_key: A :py:class:`cryptojwt.jwk.hmac.SYMKey` instance :param max_age: The time in seconds for when a cookie will be deleted :type max_age: int :return: A SimpleCookie instance """ if not timestamp: timestamp = str(int(time.time())) _cookie_value = sign_enc_payload( load, timestamp, sign_key=sign_key, enc_key=enc_key, sign_alg=sign_alg ) content = {name: {"value": _cookie_value}} if path is not None: content[name]["path"] = path if domain is not None: content[name]["domain"] = domain content[name]["httponly"] = True if max_age: content[name]["expires"] = in_a_while(seconds=max_age) return content
def test_valid(): assert valid("2000-01-12T00:00:00Z") is False current_year = datetime.today().year assert valid("%d-01-12T00:00:00Z" % (current_year + 1)) is True this_instance = instant() assert valid(this_instance) is False # unless on a very fast machine :-) soon = in_a_while(seconds=10) assert valid(soon) is True
def _expiration(timeout, time_format=None): """ Return an expiration time :param timeout: When :param time_format: The format of the returned value :return: A timeout date """ if timeout == "now": return time_util.instant(time_format) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, time_format=time_format)
def create_cookie(self, value, typ, **kwargs): cookie = SimpleCookie() timestamp = str(utc_time_sans_frac()) _payload = "::".join([value, timestamp, typ]) bytes_load = _payload.encode("utf-8") bytes_timestamp = timestamp.encode("utf-8") cookie_payload = [bytes_load, bytes_timestamp] cookie[self.name] = (b"|".join(cookie_payload)).decode('utf-8') try: ttl = kwargs['ttl'] except KeyError: pass else: cookie[self.name]["expires"] = in_a_while(seconds=ttl) return cookie
def test_later_than_str(): a = in_a_while(seconds=10) b = in_a_while(seconds=20) assert later_than(b, a) assert later_than(a, b) is False
def test_timeout(): soon = in_a_while(seconds=-1, time_format="") assert valid(soon) is False
def make_cookie(name, load, seed, domain="", path="", timestamp="", enc_key=None, max_age=0): """ Create and return a cookie The cookie is secured against tampering. If you only provide a `seed`, a HMAC gets added to the cookies value and this is checked, when the cookie is parsed again. If you provide both `seed` and `enc_key`, the cookie gets protected by using AEAD encryption. This provides both a MAC over the whole cookie and encrypts the `load` in a single step. The `seed` and `enc_key` parameters should be byte strings of at least 16 bytes length each. Those are used as cryptographic keys. :param name: Cookie name :type name: text :param load: Cookie load :type load: text :param seed: A seed key for the HMAC function :type seed: byte string :param domain: The domain of the cookie :param path: The path specification for the cookie :param timestamp: A time stamp :type timestamp: text :param enc_key: The key to use for cookie encryption. :type enc_key: byte string :param max_age: The time in seconds for when a cookie will be deleted :type max_age: int :return: A SimpleCookie instance """ cookie = SimpleCookie() if not timestamp: timestamp = str(int(time.time())) bytes_load = load.encode("utf-8") bytes_timestamp = timestamp.encode("utf-8") if enc_key: # Make sure the key is 256-bit long, for AES-128-SIV # # This should go away once we push the keysize requirements up # to the top level APIs. key = _make_hashed_key((enc_key, seed)) # key = AESGCM.generate_key(bit_length=128) aesgcm = AESGCM(key) iv = os.urandom(12) # timestamp does not need to be encrypted, just MAC'ed, # so we add it to 'Associated Data' only. ct = split_ctx_and_tag(aesgcm.encrypt(iv, bytes_load, bytes_timestamp)) ciphertext, tag = ct cookie_payload = [bytes_timestamp, base64.b64encode(iv), base64.b64encode(ciphertext), base64.b64encode(tag)] else: cookie_payload = [ bytes_load, bytes_timestamp, cookie_signature(seed, load, timestamp).encode('utf-8')] cookie[name] = (b"|".join(cookie_payload)).decode('utf-8') if path: cookie[name]["path"] = path if domain: cookie[name]["domain"] = domain if max_age: cookie[name]["expires"] = in_a_while(seconds=max_age) return cookie
def make_cookie_content( name, load, sign_key, domain=None, path=None, expire=0, timestamp="", enc_key=None, max_age=0, sign_alg="SHA256", secure=True, http_only=True, same_site="" ): """ Create and return a cookies content If you only provide a `seed`, a HMAC gets added to the cookies value and this is checked, when the cookie is parsed again. If you provide both `seed` and `enc_key`, the cookie gets protected by using AEAD encryption. This provides both a MAC over the whole cookie and encrypts the `load` in a single step. The `seed` and `enc_key` parameters should be byte strings of at least 16 bytes length each. Those are used as cryptographic keys. :param name: Cookie name :type name: text :param load: Cookie load :type load: text :param sign_key: A sign_key key for payload signing :type sign_key: A :py:class:`cryptojwt.jwk.hmac.SYMKey` instance :param domain: The domain of the cookie :param path: The path specification for the cookie :param expire: Number of minutes before this cookie goes stale :type expire: int :param timestamp: A time stamp :type timestamp: text :param enc_key: The key to use for payload encryption. :type enc_key: A :py:class:`cryptojwt.jwk.hmac.SYMKey` instance :param max_age: The time in seconds for when a cookie will be deleted :type max_age: int :param secure: A secure cookie is only sent to the server with an encrypted request over the HTTPS protocol. :type secure: boolean :param http_only: HttpOnly cookies are inaccessible to JavaScript's Document.cookie API :type http_only: boolean :param same_site: Whether SameSite (None,Strict or Lax) should be added to the cookie :type same_site: byte string :return: A SimpleCookie instance """ if not timestamp: timestamp = str(int(time.time())) _cookie_value = sign_enc_payload( load, timestamp, sign_key=sign_key, enc_key=enc_key, sign_alg=sign_alg ) content = {name: {"value": _cookie_value}} if path is not None: content[name]["path"] = path if domain is not None: content[name]["domain"] = domain if max_age: content[name]["expires"] = in_a_while(seconds=max_age) if path: content[name]["path"] = path if domain: content[name]["domain"] = domain if expire: content[name]["expires"] = _expiration(expire, "%a, %d-%b-%Y %H:%M:%S GMT") if same_site: content[name]["SameSite"] = same_site # these are booleans so just set them. content[name]["Secure"] = secure content[name]["httponly"] = http_only return content