def verify(jws, jwk, validate_claims=True, expiry_seconds=None): """ Verifies the given :class:`~jose.JWS` :param jws: The :class:`~jose.JWS` to be verified. :param jwk: A `dict` representing the JWK to use for verification. This parameter is algorithm-specific. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ header, payload, sig = map(b64decode_url, jws) header = json_decode(header) (_, verify_fn), mod = JWA[header['alg']] if not verify_fn(_jws_hash_str(jws.header, jws.payload), jwk['k'], sig, mod=mod): raise Error('Mismatched signatures') claims = json_decode(b64decode_url(jws.payload)) _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def verify(jws, jwk, alg, validate_claims=True, expiry_seconds=None): """ Verifies the given :class:`~jose.JWS` :param jws: The :class:`~jose.JWS` to be verified. :param jwk: A `dict` representing the JWK to use for verification. This parameter is algorithm-specific. :param alg: The algorithm to verify the signature with. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ header, payload, sig = map(b64decode_url, jws) header = json_decode(header) if alg != header['alg']: raise Error('Invalid algorithm') (_, verify_fn), mod = JWA[header['alg']] if not verify_fn( _jws_hash_str(jws.header, jws.payload), jwk['k'], sig, mod=mod): raise Error('Mismatched signatures') claims = json_decode(b64decode_url(jws.payload)) _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def spec_compliant_decrypt(jwe, jwk, validate_claims=True, expiry_seconds=None): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ protected_header, encrypted_key, iv, ciphertext, authentication_tag = map( b64decode_url, jwe ) header = json_decode(protected_header) if not _verify_header(header): raise Error('Header is invalid') alg = header[HEADER_ALG] enc = header[HEADER_ENC] # decrypt cek encryption_key = _decrypt_key(encrypted_key, jwk, alg) mac_key, enc_key = _parse_encryption_keys(encryption_key, enc) # verify authentication tag expected_tag = _generate_authentication_tag( mac_key, protected_header, ciphertext, iv, enc ) if not const_compare(expected_tag, authentication_tag): raise Error('Mismatched authentication tags') # decrypt body ((_, decipher), _), _ = JWA[enc] # http://tools.ietf.org/html/rfc7516#section-5.1 step 11 M = decipher(ciphertext, enc_key, iv) if HEADER_ZIP in header: try: (_, decompress) = COMPRESSION[header[HEADER_ZIP]] except KeyError: raise Error('Unsupported compression algorithm: {}'.format( header[HEADER_ZIP])) plaintext = decompress(M) else: plaintext = M claims = json_decode(plaintext) _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def spec_compliant_decrypt(jwe, jwk, validate_claims=True, expiry_seconds=None): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ protected_header, encrypted_key, iv, ciphertext, authentication_tag = map( b64decode_url, jwe) header = json_decode(protected_header) if not _verify_header(header): raise Error('Header is invalid') alg = header[HEADER_ALG] enc = header[HEADER_ENC] # decrypt cek encryption_key = _decrypt_key(encrypted_key, jwk, alg) mac_key, enc_key = _parse_encryption_keys(encryption_key, enc) # verify authentication tag expected_tag = _generate_authentication_tag(mac_key, json_encode(header), ciphertext, iv, enc) if not const_compare(expected_tag, authentication_tag): raise Error('Mismatched authentication tags') # decrypt body ((_, decipher), _), _ = JWA[enc] # http://tools.ietf.org/html/rfc7516#section-5.1 step 11 M = decipher(ciphertext, enc_key, iv) if HEADER_ZIP in header: try: (_, decompress) = COMPRESSION[header[HEADER_ZIP]] except KeyError: raise Error('Unsupported compression algorithm: {}'.format( header[HEADER_ZIP])) plaintext = decompress(M) else: plaintext = M claims = json_decode(plaintext) _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def decrypt(jwe, jwk, adata='', validate_claims=True, expiry_seconds=None): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param adata: Arbitrary string data used during encryption for additional authentication. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ header, encryption_key_ciphertext, iv, ciphertext, tag = map( b64decode_url, jwe) header = json_decode(header) # decrypt cek (_, decipher), _ = JWA[header['alg']] encryption_key = decipher(encryption_key_ciphertext, jwk) # decrypt body ((_, decipher), _), ((hash_fn, _), mod) = JWA[header['enc']] plaintext = decipher(ciphertext, encryption_key[:-mod.digest_size], iv) hash = hash_fn(_jwe_hash_str(plaintext, iv, adata), encryption_key[-mod.digest_size:], mod=mod) if not const_compare(auth_tag(hash), tag): raise Error('Mismatched authentication tags') if 'zip' in header: try: (_, decompress) = COMPRESSION[header['zip']] except KeyError: raise Error('Unsupported compression algorithm: {}'.format( header['zip'])) plaintext = decompress(plaintext) claims = json_decode(plaintext) _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def from_json(self, json_raw_data): """ Get the settings from a JSON encoded dictionary. :param json_raw_data: JSON raw data. :type json_raw_data: str """ # Lazy import of the JSON decoder function. global json_decode if json_decode is None: try: # The fastest JSON parser available for Python. from cjson import decode as json_decode except ImportError: try: # Faster than the built-in module, usually found. from simplejson import loads as json_decode except ImportError: # Built-in module since Python 2.6, very very slow! from json import loads as json_decode # Converts the JSON data into a dictionary. args = json_decode(json_raw_data) if not isinstance(args, dict): raise TypeError("Invalid JSON data") # Extract the settings from the dictionary. self.from_dictionary(args)
def test_select_descendants_normal(self): ret = url_access(self.base + "/node/test/table/a?method=descendants").read() data = json_decode(ret) self.assertEqual(data, ['test.table.a.b', 'test.table.a.c', 'test.table.a.c.d'])
def test_select_table_empty_node(self): try: ret = url_access(self.base + "/node/test/table/empty").read() except urllib2.HTTPError as e: ret = e.read() data = json_decode(ret) self.assertEqual(len(data.keys()), 0)
def test_select_children_collection(self): ret = url_access(self.base + "/node/test/table?method=children").read() data = json_decode(ret) self.assertEqual(data, ['test.table.a', 'test.table.empty'] )
def test_select_node_override(self): ret = url_access(self.base + "/node/test/table/a/b?method=override").read() data = json_decode(ret) self.assertEqual(data["key1"], "value1-3") self.assertEqual(data["key2"], "value2-2") self.assertEqual(data["key3"], "value3") self.assertEqual(data["key4"], "value4-2") self.assertEqual(data["key5"], "value5") self.assertEqual(data["key6"], u"中文测试")
def verify(jws, jwk): """ Verifies the given :class:`~jose.JWS` :param jws: The :class:`~jose.JWS` to be verified. :param jwk: A `dict` representing the JWK to use for verification. This parameter is algorithm-specific. """ header, payload, sig = map(b64decode_url, jws) header = json_decode(header) (_, verify_fn), mod = JWA[header['alg']] if not verify_fn( _jws_hash_str(jws.header, jws.payload), jwk['k'], sig, mod=mod): raise ValueError('Mismatched signatures') claims = json_decode(b64decode_url(jws.payload)) _validate(claims) return JWT(header, claims)
def test_select_node_combo(self): ret = url_access(self.base + "/node/test/table/a/b?method=combo").read() data = json_decode(ret) self.assertEqual(data["key1"], ["value1-1", "value1-2", "value1-3"]) self.assertEqual(data["key2"], ["value2-1", "value2-2"]) self.assertEqual(data["key3"], ["value3"]) self.assertEqual(data["key4"], ["value4-1", "value4-2"]) self.assertEqual(data["key5"], ["value5"]) self.assertEqual(data["key6"], [u"中文测试"])
def verify(jws, jwk): """ Verifies the given :class:`~jose.JWS` :param jws: The :class:`~jose.JWS` to be verified. :param jwk: A `dict` representing the JWK to use for verification. This parameter is algorithm-specific. """ header, payload, sig = map(b64decode_url, jws) header = json_decode(header) (_, verify_fn), mod = JWA[header['alg']] if not verify_fn(_jws_hash_str(jws.header, jws.payload), jwk['k'], sig, mod=mod): raise ValueError('Mismatched signatures') claims = json_decode(b64decode_url(jws.payload)) _validate(claims) return JWT(header, claims)
def decrypt(jwe, jwk, adata=''): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param adata: Arbitrary string data used during encryption for additional authentication. :rtype: :class:`~jose.JWT` """ header, encryption_key_ciphertext, iv, ciphertext, tag = map( b64decode_url, jwe) header = json_decode(header) # decrypt cek (_, decipher), _ = JWA[header['alg']] encryption_key = decipher(encryption_key_ciphertext, jwk) # decrypt body ((_, decipher), _), ((hash_fn, _), mod) = JWA[header['enc']] plaintext = decipher(ciphertext, encryption_key[:-mod.digest_size], iv) hash = hash_fn(_jwe_hash_str(plaintext, iv, adata), encryption_key[-mod.digest_size:], mod=mod) if not const_compare(auth_tag(hash), tag): raise ValueError('Mismatched authentication tags') if 'zip' in header: try: (_, decompress) = COMPRESSION[header['zip']] except KeyError: raise ValueError('Unsupported compression algorithm: {}'.format( header['zip'])) plaintext = decompress(plaintext) claims = json_decode(plaintext) _validate(claims) return JWT(header, claims)
def unserialize(cls, file, length=-1, charset=None): # return (list args, dict params) if not charset: charset = cls.charset st = json_decode(file.read(length).decode(charset)) if isinstance(st, dict): return (None, st) elif isinstance(st, list): return (st, None) else: return ((st,), None)
def from_json(self, json_raw_data): """ Get the settings from a JSON encoded dictionary. :param json_raw_data: JSON raw data. :type json_raw_data: str """ # Converts the JSON data into a dictionary. args = json_decode(json_raw_data) if not isinstance(args, dict): raise TypeError("Invalid JSON data") # Extract the settings from the dictionary. self.from_dictionary(args)
def from_json(self, json_raw_data): """ Get the settings from a JSON encoded dictionary. :param json_raw_data: JSON raw data. :type json_raw_data: str """ # Converts the JSON data into a dictionary. args = json_decode(json_raw_data) if not isinstance(args, dict): raise TypeError("Invalid JSON data") # Extract the settings from the dictionary. if args: self.from_dictionary(args)
def decrypt(jwe, jwk, adata='', validate_claims=True, expiry_seconds=None): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param adata: Arbitrary string data used during encryption for additional authentication. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ header, encryption_key_ciphertext, iv, ciphertext, tag = map( b64decode_url, jwe) header = json_decode(header) # decrypt cek (_, decipher), _ = JWA[header['alg']] encryption_key = decipher(encryption_key_ciphertext, jwk) # decrypt body ((_, decipher), _), ((hash_fn, _), mod) = JWA[header['enc']] version = header.get(_TEMP_VER_KEY) if version: plaintext = decipher(ciphertext, encryption_key[-mod.digest_size / 2:], iv) hash = hash_fn(_jwe_hash_str(ciphertext, iv, adata, version), encryption_key[:-mod.digest_size / 2], mod=mod) else: plaintext = decipher(ciphertext, encryption_key[:-mod.digest_size], iv) hash = hash_fn(_jwe_hash_str(ciphertext, iv, adata, version), encryption_key[-mod.digest_size:], mod=mod) if not const_compare(auth_tag(hash), tag): raise Error('Mismatched authentication tags') if 'zip' in header: try: (_, decompress) = COMPRESSION[header['zip']] except KeyError: raise Error('Unsupported compression algorithm: {}'.format( header['zip'])) plaintext = decompress(plaintext) claims = json_decode(plaintext) try: del claims[_TEMP_VER_KEY] except KeyError: # expected when decrypting legacy tokens pass _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def test_select_node_normal(self): ret = url_access(self.base + "/node/test/table/a/b").read() data = json_decode(ret) self.assertEqual(data["key1"], "value1-3") self.assertEqual(data["key2"], "value2-2") self.assertEqual(data["key3"], "value3")
def legacy_decrypt(jwe, jwk, adata='', validate_claims=True, expiry_seconds=None): """ Decrypts a deserialized :class:`~jose.JWE` :param jwe: An instance of :class:`~jose.JWE` :param jwk: A `dict` representing the JWK required to decrypt the content of the :class:`~jose.JWE`. :param adata: Arbitrary string data used during encryption for additional authentication. :param validate_claims: A `bool` indicating whether or not the `exp`, `iat` and `nbf` claims should be validated. Defaults to `True`. :param expiry_seconds: An `int` containing the JWT expiry in seconds, used when evaluating the `iat` claim. Defaults to `None`, which disables `iat` claim validation. :rtype: :class:`~jose.JWT` :raises: :class:`~jose.Expired` if the JWT has expired :raises: :class:`~jose.NotYetValid` if the JWT is not yet valid :raises: :class:`~jose.Error` if there is an error decrypting the JWE """ protected_header, encrypted_key, iv, ciphertext, authentication_tag = map( b64decode_url, jwe) header = json_decode(protected_header) alg = header[HEADER_ALG] enc = header[HEADER_ENC] # decrypt cek encryption_key = _decrypt_key(encrypted_key, jwk, alg) # decrypt body ((_, decipher), _), ((hash_fn, _), mod) = JWA[enc] version = header.get(_TEMP_VER_KEY) if version: plaintext = decipher(ciphertext, encryption_key[-mod.digest_size/2:], iv) hash = hash_fn(_jwe_hash_str(ciphertext, iv, adata, version), encryption_key[:-mod.digest_size/2], mod=mod) else: plaintext = decipher(ciphertext, encryption_key[:-mod.digest_size], iv) hash = hash_fn(_jwe_hash_str(ciphertext, iv, adata, version), encryption_key[-mod.digest_size:], mod=mod) if not const_compare(auth_tag(hash), authentication_tag): raise Error('Mismatched authentication tags') if HEADER_ZIP in header: try: (_, decompress) = COMPRESSION[header[HEADER_ZIP]] except KeyError: raise Error('Unsupported compression algorithm: {}'.format( header[HEADER_ZIP])) plaintext = decompress(plaintext) claims = json_decode(plaintext) try: del claims[_TEMP_VER_KEY] except KeyError: # expected when decrypting legacy tokens pass _validate(claims, validate_claims, expiry_seconds) return JWT(header, claims)
def test_select_children_normal(self): ret = url_access(self.base + "/node/test/table/a?method=children").read() data = json_decode(ret) self.assertEqual(data, ["test.table.a.b", "test.table.a.c"])
def test_select_ancestors_normal(self): ret = url_access(self.base + "/node/test/table/a/b?method=ancestors").read() data = json_decode(ret) self.assertEqual(data, ["test.table", "test.table.a"])