Exemplo n.º 1
0
def get_id():
    parsed_qs = dict(parse_qsl(request.query_string.decode()))
    try:
        jwt = parsed_qs["jwt"]
    except KeyError:
        abort(400)

    try:
        params = jws.factory(jwt).verify_compact(jwt, current_app.al.trusted_keys)
    except jwkest.Invalid as e:
        logger.debug("received invalid id request: %s", jwt)
        abort(400)

    try:
        data = IdRequest(params)
    except ValueError:
        logger.debug("received invalid id request: %s", params)
        abort(400)

    try:
        uuid = current_app.al.get_uuid(data.key)
        return uuid, 200
    except ALserviceNoSuchKey:
        logger.debug("no key found for request: ", data)
        ticket = current_app.al.create_ticket(data)
        return ticket, 404
Exemplo n.º 2
0
def test_make_signed_metadata_statements():
    mds = MetaDataStore('mds')
    liss = list(FO.values())
    liss.extend(list(OA.values()))

    key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS,
                                     './')

    operator = {}

    for entity, _keyjar in key_bundle.items():
        operator[entity] = Operator(iss=entity, keyjar=_keyjar)

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']]
    ms = make_signed_metadata_statement(_spec,
                                        operator,
                                        mds=mds,
                                        base_uri='https:/example.org/ms')
    assert ms

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['edugain']]
    res = make_signed_metadata_statement(_spec,
                                         operator,
                                         mds=mds,
                                         base_uri='https:/example.org/ms')
    assert list(res['ms_uri'].keys()) == [FO['edugain']]

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['example']]
    res = make_signed_metadata_statement(_spec,
                                         operator,
                                         mds=mds,
                                         base_uri='https:/example.org/ms')
    assert list(res['ms'].keys()) == [FO['example']]
    _jws = factory(res['ms'][FO['example']])
    assert _jws
Exemplo n.º 3
0
    def unpack(self, token):
        """
        Unpack a received signed or signed and encrypted Json Web Token

        :param token: The Json Web Token
        :return: If decryption and signature verification work the payload
            will be returned as a Message instance.
        """
        if not token:
            raise KeyError

        _rj = jwe.factory(token)
        if _rj:
            token = self._decrypt(_rj, token)

        _rj = jws.factory(token)
        if _rj:
            info = self._verify(_rj, token)
        else:
            raise Exception()

        if self.message_type:
            return self.message_type(**info)
        else:
            return info
Exemplo n.º 4
0
def test_create_fo_keys_bundle():
    jb = JWKSBundle(ORGOP.iss, ORGOP.keyjar)
    jb[FOP.iss] = FOP.keyjar
    jb[FO1P.iss] = FO1P.keyjar
    sb = jb.create_signed_bundle()
    _jw = jws.factory(sb)
    assert _jw
Exemplo n.º 5
0
 def test_no_kid_multiple_keys(self):
     """ This is extremely strict """
     _jwt = factory(self.sjwt_a)
     # remove kid reference
     _jwt.jwt.headers['kid'] = ''
     keys = self.keyjar.get_jwt_verify_keys(_jwt.jwt)
     assert len(keys) == 0
Exemplo n.º 6
0
def verify_self_signed_jwks(sjwt):
    """
    Verify the signature of a signed JWT containing a JWKS.
    The JWT is signed by one of the keys in the JWKS. 
    In the JWT the JWKS is stored using this format ::
    
        'jwks': {
            'keys': [ ]
        }

    :param sjwt: Signed Jason Web Token
    :return: Dictionary containing 'jwks' (the JWKS) and 'iss' (the issuer of 
        the JWT)
    """

    _jws = factory(sjwt)
    _json = _jws.jwt.part[1]
    _body = json.loads(as_unicode(_json))
    iss = _body['iss']
    _jwks = _body['jwks']

    _kj = jwks_to_keyjar(_jwks, iss)

    try:
        _kid = _jws.jwt.headers['kid']
    except KeyError:
        _keys = _kj.get_signing_key(owner=iss)
    else:
        _keys = _kj.get_signing_key(owner=iss, kid=_kid)

    _ver = _jws.verify_compact(sjwt, _keys)
    return {'jwks': _ver['jwks'], 'iss': iss}
Exemplo n.º 7
0
 def _verify_signature(self, txt=None):
     if not txt:
         txt = self.sws_jwt
     _jw = jws.factory(txt)
     if not _jw:
         raise BadSignature("SWS message not signed")
     _jw.verify_compact(txt, self._get_cert_key(self._dict["iss"]))
Exemplo n.º 8
0
    def _parse_remote_response(self, response):
        """
        Parse simple JWKS or signed JWKS from the HTTP response.

        :param response: HTTP response from the 'jwks_uri' or 'signed_jwks_uri'
            endpoint
        :return: response parsed as JSON
        """
        # Check if the content type is the right one.
        try:
            if response.headers["Content-Type"] == 'application/json':
                logger.debug("Loaded JWKS: %s from %s" %
                             (response.text, self.source))
                try:
                    return json.loads(response.text)
                except ValueError:
                    return None
            elif response.headers["Content-Type"] == 'application/jose':
                logger.debug("Signed JWKS: %s from %s" %
                             (response.text, self.source))
                _jws = factory(response.text)
                _resp = _jws.verify_compact(
                    response.text, keys=self.verify_keys.get_signing_key())
                return _resp
            else:
                logger.error('Wrong content type: {}'.format(
                    response.headers['Content-Type']))
                return None
        except KeyError:
            pass
Exemplo n.º 9
0
    def verify(self, signature, **kwargs):
        _jw = jws.factory(signature)
        if not _jw:
            raise ValidationError("Not a signed request")

        try:
            unpacked_req = _jw.verify_compact(signature, keys=[self.key])
        except JWKESTException:
            raise ValidationError("Could not verify signature")

        _header = _jw.jwt.headers
        if "typ" not in _header or _header["typ"] != "pop":
            raise ValidationError("Incorrect JWS header 'typ', must be 'pop'")

        hash_size = get_hash_size(_header["alg"])

        for arg, (key, func) in SIMPLE_OPER.items():
            if arg == "time_stamp":
                continue
            try:
                if func is None:
                    _val = kwargs[arg]
                else:
                    _val = func(kwargs[arg])
                _equals(unpacked_req[key], _val)
            except KeyError:
                pass

        for arg, (key, format) in PARAM_ARGS.items():
            try:
                _attr = "strict_{}_verification".format(arg)
                _strict_verify = kwargs[_attr]
            except KeyError:
                _strict_verify = False

            try:
                _verify_params(
                    kwargs[arg],
                    unpacked_req[key],
                    format,
                    hash_size,
                    _strict_verify,
                    key,
                )
            except KeyError:
                pass

        if "b" not in unpacked_req and "body" not in kwargs:
            pass
        elif "b" in unpacked_req and "body" in kwargs:
            _equals(b64_hash(kwargs.get("body", ""), hash_size),
                    unpacked_req.get("b", ""))
        else:
            if "b" in unpacked_req:
                raise ValidationError("Body sent but not received!!")
            else:
                raise ValidationError("Body received but not sent!!")

        return unpacked_req
Exemplo n.º 10
0
def check_key_availability(inst, jwt):
    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemplo n.º 11
0
 def _decrypt(self, rj, token):
     keys = self.keyjar.get_verify_key(owner='')
     msg = rj.decrypt(token, keys)
     _rj = jws.factory(msg)
     if not _rj:
         raise KeyError()
     else:
         return self._verify(_rj, msg)
Exemplo n.º 12
0
 def _decrypt(self, rj, token):
     keys = self.keyjar.get_verify_key(owner='')
     msg = rj.decrypt(token, keys)
     _rj = jws.factory(msg)
     if not _rj:
         raise KeyError()
     else:
         return self._verify(_rj, msg)
Exemplo n.º 13
0
def test_dj_usage():
    key_string = open(full_path("./size2048.key"), 'r').read()
    key = RSA.importKey(key_string)
    payload = "Please take a moment to register today"
    keys = [RSAKey(key=key, kid=md5(key_string.encode('utf-8')).hexdigest())]
    _jws = JWS(payload, alg='RS256')
    sjwt = _jws.sign_compact(keys)
    _jwt = factory(sjwt)
    assert _jwt.jwt.headers['alg'] == 'RS256'
Exemplo n.º 14
0
 def _verify_jwt(jwt: str, keys: list):
     """
     Verify teh signature of the jwt
     :type keys: list[str]
     :param jwt: A signed jwt
     :param keys: A list of keys to use when verifying the signature
     """
     _jw = jws.factory(jwt)
     _jw.verify_compact(jwt, keys)
Exemplo n.º 15
0
def print_metadata_statement(txt, sms):
    _jwt = factory(sms)
    _sos = json.loads(_jwt.jwt.part[1].decode('utf8'))

    print(70 * "=")
    print(txt)
    print(70 * "=")
    print_lines(
        json.dumps(_sos, sort_keys=True, indent=2, separators=(',', ': ')))
Exemplo n.º 16
0
def test_dj_usage():
    key_string = open(full_path("./size2048.key"), 'r').read()
    key = RSA.importKey(key_string)
    payload = "Please take a moment to register today"
    keys = [RSAKey(key=key, kid=md5(key_string.encode('utf-8')).hexdigest())]
    _jws = JWS(payload, alg='RS256')
    sjwt = _jws.sign_compact(keys)
    _jwt = factory(sjwt)
    assert _jwt.jwt.headers['alg'] == 'RS256'
Exemplo n.º 17
0
 def _verify_jwt(jwt: str, keys: list):
     """
     Verify teh signature of the jwt
     :type keys: list[str]
     :param jwt: A signed jwt
     :param keys: A list of keys to use when verifying the signature
     """
     _jw = jws.factory(jwt)
     _jw.verify_compact(jwt, keys)
Exemplo n.º 18
0
def unfurl(jwt):
    """
    Return the body of a signed JWT, without verifying the signature.
    
    :param jwt: A signed JWT 
    :return: The body of the JWT as a 'UTF-8' string
    """

    _rp_jwt = factory(jwt)
    return json.loads(_rp_jwt.jwt.part[1].decode('utf8'))
Exemplo n.º 19
0
def resign_bundle(iss, signed_bundle, sign_key):
    _jw = jws.factory(signed_bundle)
    _jwt = _jw.jwt.payload()
    _bundle = json.loads(_jwt['bundle'])

    jb = JWKSBundle(iss, sign_key)
    for iss, jwks in _bundle.items():
        jb[iss] = jwks

    return jb
Exemplo n.º 20
0
def test_signer_ps512():
    payload = "Please take a moment to register today"
    # Key has to be big enough  > 512+512+2
    keys = [RSAKey(key=import_rsa_key_from_file(full_path("./size2048.key")))]
    #keys[0]._keytype = "private"
    _jws = JWS(payload, alg="PS521")
    _jwt = _jws.sign_compact(keys)

    _rj = factory(_jwt)
    info = _rj.verify_compact(_jwt, keys)
    assert info == payload
    def verify(self, signature, **kwargs):
        _jw = jws.factory(signature)
        if not _jw:
            raise ValidationError("Not a signed request")

        try:
            unpacked_req = _jw.verify_compact(signature, keys=[self.key])
        except JWKESTException:
            raise ValidationError("Could not verify signature")

        _header = _jw.jwt.headers
        if "typ" not in _header or _header["typ"] != "pop":
            raise ValidationError("Incorrect JWS header 'typ', must be 'pop'")

        hash_size = get_hash_size(_header["alg"])

        for arg, (key, func) in SIMPLE_OPER.items():
            if arg == 'time_stamp':
                continue
            try:
                if func is None:
                    _val = kwargs[arg]
                else:
                    _val = func(kwargs[arg])
                _equals(unpacked_req[key], _val)
            except KeyError:
                pass

        for arg, (key, format) in PARAM_ARGS.items():
            try:
                _attr = 'strict_{}_verification'.format(arg)
                _strict_verify = kwargs[_attr]
            except KeyError:
                _strict_verify = False

            try:
                _verify_params(kwargs[arg], unpacked_req[key], format,
                               hash_size, _strict_verify, key)
            except KeyError:
                pass

        if 'b' not in unpacked_req and 'body' not in kwargs:
            pass
        elif 'b' in unpacked_req and 'body' in kwargs:

            _equals(b64_hash(kwargs.get("body", ""), hash_size),
                    unpacked_req.get("b", ""))
        else:
            if 'b' in unpacked_req:
                raise ValidationError('Body sent but not received!!')
            else:
                raise ValidationError('Body received but not sent!!')

        return unpacked_req
Exemplo n.º 22
0
def test_signer_ps512():
    payload = "Please take a moment to register today"
    # Key has to be big enough  > 512+512+2
    keys = [RSAKey(key=import_rsa_key_from_file(full_path("./size2048.key")))]
    #keys[0]._keytype = "private"
    _jws = JWS(payload, alg="PS512")
    _jwt = _jws.sign_compact(keys)

    _rj = factory(_jwt)
    info = _rj.verify_compact(_jwt, keys)
    assert info == payload
Exemplo n.º 23
0
def test_pack_metadata_statement_other_alg():
    _keyjar = build_keyjar(KEYDEFS)[1]
    op = Operator(keyjar=_keyjar, iss='https://example.com/')
    req = MetadataStatement(issuer='https://example.org/op')
    sms = op.pack_metadata_statement(req, alg='ES256')
    assert sms  # Should be a signed JWT
    _jwt = factory(sms)
    _body = json.loads(as_unicode(_jwt.jwt.part[1]))
    assert _body['iss'] == 'https://example.com/'
    # verify signature
    r = _jwt.verify_compact(sms, _keyjar.get_signing_key())
    assert r
Exemplo n.º 24
0
 def test_no_kid_multiple_keys_no_kid_issuer_lim(self):
     a_kids = [
         k.kid
         for k in self.keyjar.get_verify_key(owner='A', key_type='RSA')
     ]
     no_kid_issuer = {'A': []}
     _jwt = factory(self.sjwt_a)
     _jwt.jwt.headers['kid'] = ''
     keys = self.keyjar.get_jwt_verify_keys(_jwt.jwt,
                                            no_kid_issuer=no_kid_issuer)
     assert len(keys) == 3
     assert set([k.kid for k in keys]) == set(a_kids)
Exemplo n.º 25
0
    def _get_client_public_key(self, access_token):
        _jws = jws.factory(access_token)
        if _jws:
            data = _jws.verify_compact(access_token,
                                       self.keyjar.get_verify_key(owner=""))
            try:
                return keyrep(data["cnf"]["jwk"])
            except KeyError:
                raise NonPoPTokenError(
                    "Could not extract public key as JWK from access token")

        raise NonPoPTokenError("Unsigned access token, maybe not PoP?")
Exemplo n.º 26
0
    def _get_client_public_key(self, access_token):
        _jws = jws.factory(access_token)
        if _jws:
            data = _jws.verify_compact(access_token,
                                       self.keyjar.get_verify_key(owner=""))
            try:
                return keyrep(data["cnf"]["jwk"])
            except KeyError:
                raise NonPoPTokenError(
                    "Could not extract public key as JWK from access token")

        raise NonPoPTokenError("Unsigned access token, maybe not PoP?")
Exemplo n.º 27
0
    def test_create_fed_provider_info(self):
        fedpi = self.op.create_fed_providerinfo()

        assert 'signing_keys' not in fedpi

        assert len(fedpi['metadata_statements']) == 1
        _js = jws.factory(fedpi['metadata_statements'][FO['swamid']])
        assert _js
        assert _js.jwt.headers['alg'] == 'RS256'
        _body = json.loads(as_unicode(_js.jwt.part[1]))
        assert _body[
            'iss'] == self.op.federation_entity.signer.signing_service.iss
Exemplo n.º 28
0
    def _func(self, conv):
        # returns a list, should only be one item in the list
        response = get_protocol_response(conv, AccessTokenResponse)[0]

        res = {}
        _tok = response['access_token']
        _jwt = jws.factory(_tok)
        if _jwt:
            _keys = conv.entity.keyjar.get_issuer_keys(
                conv.entity.provider_info['issuer'])
            _json = _jwt.verify_compact(_tok, _keys)
            missing = []
            for x in ['iss', 'azp', 'sub', 'kid', 'exp', 'jti']:
                if x not in _json:
                    missing.append(x)
            if missing:
                self._message = "The following claims are missing from the " \
                                "access token: {}".format(missing)
                self._status = WARNING
        try:
            _tok = response['refresh_token']
        except KeyError:
            pass
        else:
            _jwt = jws.factory(_tok)
            if _jwt:
                missing = []
                _keys = conv.entity.keyjar.get_issuer_keys(
                    conv.entity.provider_info['issuer'])
                _json = _jwt.verify_compact(_tok, _keys)
                for x in ['iss', 'azp', 'sub', 'kid', 'exp', 'jti']:
                    if x not in _json:
                        missing.append(x)
                if missing:
                    self._message = "The following claims are missing from " \
                                    "the refresh token: {}".format(missing)
                    self._status = WARNING

        return res
Exemplo n.º 29
0
    def test_provider_endpoint(self):
        pi_resp = self.op.providerinfo_endpoint()

        assert isinstance(pi_resp, Response)
        assert pi_resp.status == "200 OK"
        _info = json.loads(pi_resp.message)
        assert list(_info['metadata_statements'].keys()) == [FO['swamid']]
        _js = jws.factory(_info['metadata_statements'][FO['swamid']])
        assert _js
        assert _js.jwt.headers['alg'] == 'RS256'
        _body = json.loads(as_unicode(_js.jwt.part[1]))
        assert _body[
            'iss'] == self.op.federation_entity.signer.signing_service.iss
Exemplo n.º 30
0
    def test_aud(self):
        self.keyjar.import_jwks(JWK1, issuer='D')

        _jws = JWS('{"iss": "D", "aud": "A"}', alg='HS256')
        sig_key = self.keyjar.get_signing_key('oct', owner='D')[0]
        _sjwt = _jws.sign_compact([sig_key])

        no_kid_issuer = {'D': []}

        _jwt = factory(_sjwt)

        keys = self.keyjar.get_jwt_verify_keys(_jwt.jwt,
                                               no_kid_issuer=no_kid_issuer)
        assert len(keys) == 1
Exemplo n.º 31
0
def test_pack_metadata_statement():
    jb = FSJWKSBundle('', None, 'fo_jwks',
                      key_conv={'to': quote_plus, 'from': unquote_plus})
    _keyjar = build_keyjar(KEYDEFS)[1]
    op = Operator(keyjar=_keyjar, jwks_bundle=jb, iss='https://example.com/')
    req = MetadataStatement(issuer='https://example.org/op')
    sms = op.pack_metadata_statement(req)
    assert sms  # Should be a signed JWT
    _jwt = factory(sms)
    assert _jwt
    assert _jwt.jwt.headers['alg'] == 'RS256'
    _body = json.loads(as_unicode(_jwt.jwt.part[1]))
    assert _body['iss'] == op.iss
    assert _body['issuer'] == 'https://example.org/op'
    # verify signature
    r = _jwt.verify_compact(sms, _keyjar.get_signing_key())
    assert r
Exemplo n.º 32
0
    def unpack(self, token):
        if not token:
            raise KeyError

        _rj = jws.factory(token)
        if _rj:
            info = self._verify(_rj, token)
        else:
            _rj = jwe.factory(token)
            if not _rj:
                raise KeyError()
            info = self._decrypt(_rj, token)

        if self.message_type:
            return self.message_type(**info)
        else:
            return info
Exemplo n.º 33
0
def check_key_availability(inst, jwt):
    """
    If the server is restarted it will NOT load keys from jwks_uris for
    all the clients that has been registered. So this function is there
    to get a clients keys when needed.

    :param inst: OP instance
    :param jwt: A JWT that has to be verified or decrypted
    """

    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemplo n.º 34
0
    def unpack(self, token):
        if not token:
            raise KeyError

        _rj = jws.factory(token)
        if _rj:
            info = self._verify(_rj, token)
        else:
            _rj = jwe.factory(token)
            if not _rj:
                raise KeyError()
            info = self._decrypt(_rj, token)

        if self.message_type:
            return self.message_type(**info)
        else:
            return info
Exemplo n.º 35
0
def check_key_availability(inst, jwt):
    """
    If the server is restarted it will NOT load keys from jwks_uris for
    all the clients that has been registered. So this function is there
    to get a clients keys when needed.

    :param inst: OP instance
    :param jwt: A JWT that has to be verified or decrypted
    """

    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemplo n.º 36
0
def test_rpt():
    kb = KeyBundle(JWKS["keys"])
    kj = KeyJar()
    kj.issuer_keys[''] = [kb]

    token_factory = JWT(kj, lifetime=3600, iss=issuer)

    client_id = 'https://example.com/client'
    ressrv_id = 'https://rs.example.org/'

    rpt = token_factory.pack(kid='sign1', aud=[client_id, ressrv_id],
                             azp=ressrv_id, type='rpt')

    _rj = jws.factory(rpt)
    jti = json.loads(_rj.jwt.part[1].decode('utf8'))['jti']

    info = token_factory.unpack(rpt)
    assert set(info.keys()), {'aud', 'azp', 'ext', 'iat', 'iss', 'jti', 'kid',
                              'type'}
Exemplo n.º 37
0
    def __call__(self, req, **kwargs):
        r = requests.post(self.url, json=req, verify=False)
        if 200 <= r.status_code < 300:
            _jw = factory(r.text)

            # First Just checking the issuer ID *not* verifying the Signature
            body = json.loads(as_unicode(_jw.jwt.part[1]))
            assert body['iss'] == self.iss

            # Now verifying the signature
            try:
                _jw.verify_compact(r.text,
                                   self.keyjar.get_verify_key(owner=self.iss))
            except AssertionError:
                raise JWSException('JWS signature verification error')

            return r.text
        else:
            raise SigningServiceError("{}: {}".format(r.status_code, r.text))
Exemplo n.º 38
0
    def verify(self, signature, **kwargs):
        _jw = jws.factory(signature)
        if not _jw:
            raise ValidationError("Not a signed request")

        try:
            unpacked_req = _jw.verify_compact(signature, keys=[self.key])
            _header = _jw.jwt.headers
            hash_size = _get_hash_size(_header["alg"])
        except BadSignature:
            raise ValidationError("Could not verify signature")

        for arg, (key, func) in SIMPLE_OPER.items():
            if arg == 'time_stamp':
                continue
            try:
                if func is None:
                    _val = kwargs[arg]
                else:
                    _val = func(kwargs[arg])
                _equals(unpacked_req[key], _val)
            except KeyError:
                pass

        for arg, (key, format) in PARAM_ARGS.items():
            try:
                _attr = 'strict_{}_verification'.format(arg)
                _strict_verify = kwargs[_attr]
            except KeyError:
                _strict_verify = False

            try:
                _verify_params(kwargs[arg], unpacked_req[key], format,
                               hash_size, _strict_verify, key)
            except KeyError:
                pass

        try:
            _equals(b64_hash(kwargs['body'], hash_size), unpacked_req["b"])
        except KeyError:
            pass

        return unpacked_req
Exemplo n.º 39
0
    def get_signed_keys(self, uri, signing_keys):
        """

        :param uri: Where the signed JWKS can be found
        :param signing_keys: Dictionary representation of a JWKS
        :return: list of KeyBundle instances or None
        """
        r = self.server.http_request(uri, allow_redirects=True)
        if r.status_code == 200:
            _skj = KeyJar()
            _skj.import_jwks(signing_keys, '')

            _jws = factory(r.text)
            _jwks = _jws.verify_compact(r.text, Keys=_skj.get_signing_key())
            _kj = KeyJar()
            _kj.import_jwks(json.loads(_jwks), '')
            return _kj.issuer_keys['']
        else:
            return None
Exemplo n.º 40
0
    def assert_registstration_req(self, request, sign_key_str):
        split_path = request.path_url.lstrip("/").split("/")
        assert len(split_path) == 2

        jwks = split_path[1]

        # Verify signature
        public_key = import_rsa_key(private_to_public_key(sign_key_str))
        sign_key = RSAKey().load_key(public_key)
        sign_key.use = "sig"
        _jw = jws.factory(jwks)
        _jw.verify_compact(jwks, [sign_key])

        # Verify JWT
        _jwt = JWT().unpack(jwks)
        consent_args = _jwt.payload()

        assert "attr" in consent_args
        assert "redirect_endpoint" in consent_args
        assert "id" in consent_args
Exemplo n.º 41
0
    def test_use_signing_service(self):
        _fe = self.op.federation_entity
        statement = self.op.create_providerinfo()
        req = _fe.add_signing_keys(statement)

        sjwt = _fe.signer.create_signed_metadata_statement(
            req,
            'discovery',
            fos=_fe.signer.metadata_statements.keys(),
            single=True)

        assert sjwt

        # should be a signed JWT

        _js = jws.factory(sjwt)
        assert _js
        assert _js.jwt.headers['alg'] == 'RS256'
        _req = json.loads(as_unicode(_js.jwt.part[1]))
        assert _req['iss'] == OA['sunet']
Exemplo n.º 42
0
    def save_consent_request(self, jwt: str):
        """
        Saves a consent request, in the form of a JWT.
        :param jwt: JWT represented as a string
        """
        try:
            request = jws.factory(jwt).verify_compact(jwt, self.trusted_keys)
        except jwkest.Invalid as e:
            logger.debug('invalid signature: %s', str(e))
            raise InvalidConsentRequestError('Invalid signature') from e

        try:
            data = ConsentRequest(request)
        except ValueError:
            logger.debug('invalid consent request: %s', json.dumps(request))
            raise InvalidConsentRequestError('Invalid consent request')

        ticket = hashlib.sha256((jwt + str(mktime(gmtime()))).encode("UTF-8")).hexdigest()
        self.ticket_db.save_consent_request(ticket, data)
        return ticket
Exemplo n.º 43
0
    def assert_registstration_req(self, request, sign_key_str):
        split_path = request.path_url.lstrip("/").split("/")
        assert len(split_path) == 2

        jwks = split_path[1]

        # Verify signature
        public_key = import_rsa_key(private_to_public_key(sign_key_str))
        sign_key = RSAKey().load_key(public_key)
        sign_key.use = "sig"
        _jw = jws.factory(jwks)
        _jw.verify_compact(jwks, [sign_key])

        # Verify JWT
        _jwt = JWT().unpack(jwks)
        consent_args = _jwt.payload()

        assert "attr" in consent_args
        assert "redirect_endpoint" in consent_args
        assert "id" in consent_args
Exemplo n.º 44
0
def check_key_availability(inst, jwt):
    """
    Try to refresh keys.

    If the server is restarted it will NOT load keys from jwks_uris for
    all the clients that has been registered. So this function is there
    to get a clients keys when needed.

    :param inst: OP instance
    :param jwt: A JWT that has to be verified or decrypted
    """
    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload["iss"]
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo["client_secret"], ["enc", "sig"])
        if cinfo.get("jwks_uri") is not None:
            inst.keyjar.add(_cid, cinfo["jwks_uri"])
        elif cinfo.get("jwks") is not None:
            inst.keyjar.import_jwks(cinfo["jwks"], _cid)
Exemplo n.º 45
0
    def _unpack_jwt(self, token, only_info=False):
        if not token:
            raise KeyError

        _rj = factory(token)
        _msg = json.loads(_rj.jwt.part[1].decode('utf8'))
        if _msg['iss'] == self.iss:
            owner = ''
        else:
            owner = _msg['iss']

        keys = self.keyjar.get_signing_key(alg2keytype(_rj.jwt.headers['alg']),
                                           owner=owner)
        info = _rj.verify_compact(token, keys)
        if only_info:
            return info

        try:
            sid = self.db[info['jti']]
        except KeyError:
            raise

        return sid, info
Exemplo n.º 46
0
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = _jw.decrypt(txt, dkeys)
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = json.loads(_jwt.part[1])
                _header = _jwt.headers

                logger.debug("Raw JSON: %s" % jso)
                if _header["alg"] == "none":
                    pass
                else:
                    if keyjar:
                        if "jku" in _header:
                            if not keyjar.find(_header["jku"], jso["iss"]):
                                # This is really questionable
                                try:
                                    if kwargs["trusting"]:
                                        keyjar.add(jso["iss"], _header["jku"])
                                except KeyError:
                                    pass

                        if "kid" in _header and _header["kid"]:
                            _jw["kid"] = _header["kid"]
                            try:
                                _key = keyjar.get_key_by_kid(_header["kid"],
                                                             jso["iss"])
                                if _key:
                                    key.append(_key)
                            except KeyError:
                                pass

                        try:
                            self._add_key(keyjar, kwargs["opponent_id"], key)
                        except KeyError:
                            pass

                    if verify:
                        if keyjar:
                            for ent in ["iss", "aud", "client_id"]:
                                if ent not in jso:
                                    continue
                                if ent == "aud":
                                    # list or basestring
                                    if isinstance(jso["aud"], basestring):
                                        _aud = [jso["aud"]]
                                    else:
                                        _aud = jso["aud"]
                                    for _e in _aud:
                                        self._add_key(keyjar, _e, key)
                                else:
                                    self._add_key(keyjar, jso[ent], key)

                        if "alg" in _header and _header["alg"] != "none":
                            if not key:
                                raise MissingSigningKey(
                                    "alg=%s" % _header["alg"])

                        _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)
print_lines(json.dumps(ssreq.to_dict(), sort_keys=True, indent=2,
                       separators=(',', ': ')))

# -----------------------------------------------------------------------------
# The SWAMID FO constructs Software statement
# -----------------------------------------------------------------------------

ssreq.update({
    "response_types": ["code", "code id_token", "token"],
    "token_endpoint_auth_method": "private_key_jwt",
    "scopes": ['openid', 'email', 'phone']
})

dev_swamid_sost = make_software_statement(swamid_keyjar, swamid_issuer,
                                          **ssreq.to_dict())
_jwt = factory(dev_swamid_sost)
_sos = json.loads(_jwt.jwt.part[1].decode('utf8'))

print(70 * "-")
print('SWAMID extended software statement')
print(70 * "-")
print_lines(json.dumps(_sos, sort_keys=True, indent=2, separators=(',', ': ')))

# -----------------------------------------------------------------------------
# -- construct JSON document to be signed by InCommon
# -----------------------------------------------------------------------------

ssreq = SoftwareStatement(
    contacts=['*****@*****.**'],
    policy_uri='https://example.com/policy.html',
    tos_uri='https://example.com/tos.html',
Exemplo n.º 48
0
print_lines(json.dumps(ssreq.to_dict(), sort_keys=True, indent=2, separators=(",", ": ")))

# -----------------------------------------------------------------------------
# The FO constructs Software statement
# -----------------------------------------------------------------------------

ssreq.update(
    {
        "response_types": ["code", "token"],
        "token_endpoint_auth_method": "private_key_jwt",
        "scopes_allowed": ["openid", "email", "phone"],
    }
)

sost = make_software_statement(fo_keyjar, "https://fo.example.com/", **ssreq.to_dict())
_jwt = factory(sost)
_sos = json.loads(_jwt.jwt.part[1].decode("utf8"))

print(70 * "-")
print("FO extended software statement")
print(70 * "-")
print_lines(json.dumps(_sos, sort_keys=True, indent=2, separators=(",", ": ")))
print()
print_lines(sost)

# -----------------------------------------------------------------------------
# Create intermediate key pair
# -----------------------------------------------------------------------------

im_jwks, im_keyjar = build_keyjar(key_conf)[:-1]
Exemplo n.º 49
0
def unfurl(jwt):
    _rp_jwt = factory(jwt)
    return json.loads(_rp_jwt.jwt.part[1].decode('utf8'))
Exemplo n.º 50
0
def verify_http_request(key, signature, method="", host="", path="",
                        query_params=None, headers=None, body=None,
                        strict_query_param_verification=False,
                        strict_headers_verification=False):
    """

    :param key: verification key
    :param signature: signature of the request
    :param method: HTTP method
    :param host: url host
    :param path: url path
    :param query_params: query parameters
    :param headers: HTTP headers
    :param body: request body
    :param strict_query_param_verification:
    :param strict_headers_verification:
    :return:
    """
    _jw = jws.factory(signature)
    if not _jw:
        raise ValidationError("Not a signed request")

    try:
        unpacked_req = _jw.verify_compact(signature, keys=[key])
        _header = _jw.jwt.headers
        hash_size = _get_hash_size(_header["alg"])
    except BadSignature:
        raise ValidationError("Could not verify signature")

    if "m" in unpacked_req:
        _equals(unpacked_req["m"], method)
    if "u" in unpacked_req:
        _equals(unpacked_req["u"], host)
    if "p" in unpacked_req:
        _equals(unpacked_req["p"], path)

    if "q" in unpacked_req:
        param_keys, param_hash = unpacked_req["q"]
        cmp_hash_str = "".join(
            [QUERY_PARAM_FORMAT.format(k, query_params[k]) for k in
             param_keys])
        cmp_hash = urlsafe_b64encode(
            _hash_value(hash_size, cmp_hash_str)).decode("utf-8")
        _equals(cmp_hash, param_hash)
        if strict_query_param_verification and len(param_keys) != len(
                query_params):
            raise ValidationError("Too many or too few query params")

    if "h" in unpacked_req:
        header_keys, header_hash = unpacked_req["h"]
        cmp_hash_str = "".join(
            [REQUEST_HEADER_FORMAT.format(k, headers[k]) for k in
             header_keys])
        cmp_hash = urlsafe_b64encode(
            _hash_value(hash_size, cmp_hash_str)).decode("utf-8")
        _equals(cmp_hash, header_hash)
        if strict_headers_verification and len(header_keys) != len(headers):
            raise ValidationError("Too many or too few headers")

    if "b" in unpacked_req:
        cmp_body = urlsafe_b64encode(_hash_value(hash_size, body)).decode("utf-8")
        _equals(cmp_body, unpacked_req["b"])

    return unpacked_req
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = as_unicode(_jw.decrypt(txt, dkeys))
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = _jwt.payload()
                _header = _jwt.headers

                logger.debug("Raw JSON: {}".format(jso))
                logger.debug("header: {}".format(_header))
                if _header["alg"] == "none":
                    pass
                elif verify:
                    if keyjar:
                        key = self.get_verify_keys(keyjar, key, jso, _header,
                                                   _jw, **kwargs)

                    if "alg" in _header and _header["alg"] != "none":
                        if not key:
                            raise MissingSigningKey(
                                "alg=%s" % _header["alg"])

                    logger.debug("Verify keys: {}".format(key))
                    try:
                        _jw.verify_compact(txt, key)
                    except NoSuitableSigningKeys:
                        if keyjar:
                            update_keyjar(keyjar)
                            key = self.get_verify_keys(keyjar, key, jso,
                                                       _header, _jw, **kwargs)
                            _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)
Exemplo n.º 52
0
#!/usr/bin/env python
import sys
from jwkest import jwe
from jwkest import jws

__author__ = 'roland'

jwt = open(sys.argv[1]).read()

_jw = jwe.factory(jwt)
if _jw:
    print("jwe")
else:
    _jw = jws.factory(jwt)
    if _jw:
        print("jws")
        print(_jw.jwt.headers)
        print(_jw.jwt.part[1])