def test_cmp_rsa_ec(): _key1 = RSAKey() _key1.load_key(pem_cert2rsa(CERT)) _key2 = ECKey(**ECKEY) assert _key1 != _key2
def __init__(self, public_key=None, keyset_url=None): """ Instance message validator Import a public key from the tool by either using a keyset url or a combination of public key + key id. Keyset URL takes precedence because it makes key rotation easier to do. """ # Only store keyset URL to avoid blocking the class # instancing on an external url, which is only used # when validating a token. self.keyset_url = keyset_url self.public_key = None # Import from public key if public_key: try: new_key = RSAKey(use='sig') # Unescape key before importing it raw_key = codecs.decode(public_key, 'unicode_escape') # Import Key and save to internal state new_key.load_key(RSA.import_key(raw_key)) self.public_key = new_key except ValueError as err: raise exceptions.InvalidRsaKey() from err
def test_extract_rsa_from_cert_2(): _ckey = pem_cert2rsa(CERT) _key = RSAKey() _key.load_key(_ckey) print(_key) assert _ckey.n == _key.get_key().n
def test_cmp_rsa(): _key1 = RSAKey() _key1.load_key(pem_cert2rsa(CERT)) _key2 = RSAKey() _key2.load_key(pem_cert2rsa(CERT)) assert _key1 == _key2
def test_kspec(): _ckey = pem_cert2rsa(CERT) _key = RSAKey() _key.load_key(_ckey) print(_key) jwk = _key.serialize() assert jwk["kty"] == "RSA" assert jwk["e"] == JWK["keys"][0]["e"] assert jwk["n"] == JWK["keys"][0]["n"]
def test_kspec(): _ckey = pem_cert2rsa(CERT) _key = RSAKey() _key.load_key(_ckey) print(_key) jwk = _key.serialize() assert jwk["kty"] == "RSA" assert jwk["e"] == JWK["keys"][0]["e"].encode("utf-8") assert jwk["n"] == JWK["keys"][0]["n"].encode("utf-8")
def test_cmp_rsa_ec(): _key1 = RSAKey() _key1.load_key(pem_cert2rsa(CERT)) _key2 = ECKey(**ECKEY) try: assert _key1 == _key2 except AssertionError: pass else: assert False
def keybundle_from_local_file(filename, typ, usage, kid): if typ.upper() == "RSA": kb = KeyBundle() k = RSAKey(kid=kid) k.load(filename) k.use = usage[0] kb.append(k) for use in usage[1:]: _k = RSAKey(kid=kid + "1") _k.use = use _k.load_key(k.key) kb.append(_k) elif typ.lower() == "jwk": kb = KeyBundle(source=filename, fileformat="jwk", keyusage=usage) else: raise UnknownKeyType("Unsupported key type") return kb
def test_verify_2(): _key = RSAKey() _key.load_key(pem_cert2rsa(CERT)) assert _key.verify()
def vetting_result(): if not current_app.config.get('FREJA_CALLBACK_X5T_CERT'): current_app.logger.info('Configuration error: FREJA_CALLBACK_X5T_CERT is not set') return make_response('Configuration error', 500) _freja_callback_x5t_cert = current_app.config.get('FREJA_CALLBACK_X5T_CERT') _freja_callback_x5t_pub_key = RSA.importKey(_freja_callback_x5t_cert) _freja_callback_rsa_pub_key = RSAKey() _freja_callback_rsa_pub_key.load_key(_freja_callback_x5t_pub_key) current_app.logger.debug('flask.request.headers: \'{!s}\''.format(flask.request.headers)) current_app.logger.debug('flask.request.data: \'{!s}\''.format(flask.request.get_data())) try: if flask.request.headers['Content-Type'] == 'application/jose': current_app.logger.info('Received a callback with MIME application/jose') else: current_app.logger.info('Received a callback with an invalid MIME: \'{!s}\'' .format(flask.request.headers['Content-Type'])) return make_response('Invalid MIME', 400) except KeyError: current_app.logger.info('Received a callback without a MIME') return make_response('No MIME specified', 400) try: data = flask.request.get_json(force=True) except: current_app.logger.info('Invalid verisec callback: missing or invalid JSON') return make_response('missing or invalid JSON', 400) if not data: current_app.logger.info('Invalid verisec callback: no JSON data provided') return make_response('Missing JSON data', 400) ia_response_data = data.get('iaResponseData') if not ia_response_data: current_app.logger.info('Missing iaResponseData in verisec callback: \'{!s}\''.format(data)) return make_response('Missing iaResponseData', 400) current_app.logger.info('Received verisec iaResponseData: \'{!s}\''.format(ia_response_data)) jws_parts = ia_response_data.split('.') # A correctly formatted JWS is made up of 3 parts if len(jws_parts) != 3: current_app.logger.info('iaResponseData response doesn\'t seems to be a JWS') return make_response('iaResponseData is not a JWS', 400) # This is for testing only and therefore we do not verify the JWS yet unverified_header = jws_parts[0] unverified_payload = jws_parts[1] # It should be possible to base64 decode the header and payload try: # urlsafe_b64decode returns bytes object so we decode to get str aka utf8 unverified_header_decoded = urlsafe_b64decode(unverified_header + '=' * (4 - (len(unverified_header) % 4))).decode('utf8') unverified_payload_decoded = urlsafe_b64decode(unverified_payload + '=' * (4 - (len(unverified_payload) % 4))).decode('utf8') except UnicodeDecodeError: current_app.logger.info('Couldn\'t urlsafe_b64decode iaResponseData because it contains invalid UTF-8') return make_response('Incorrect UTF-8 in iaResponseData', 400) except binascii.Error: current_app.logger.info('Couldn\'t urlsafe_b64decode iaResponseData because non-base64 digit found') return make_response('Incorrect UTF-8 in iaResponseData', 400) except TypeError: current_app.logger.info('Couldn\'t urlsafe_b64decode iaResponseData') return make_response('Incorrect base64 encoded iaResponseData', 400) try: json.loads(unverified_header_decoded) json.loads(unverified_payload_decoded) except JSONDecodeError: current_app.logger.info('Incorrect UTF-8 BOM or invalid JSON data from base64 decoded iaResponseData') return make_response('Incorrectly encoded JSON in base64 decoded iaResponseData', 400) except TypeError: current_app.logger.info('JSON in base64 decoded iaResponseData is not str') return make_response('Incorrectly encoded JSON in base64 decoded iaResponseData', 400) try: verified_payload = JWS().verify_compact(ia_response_data, keys=[_freja_callback_rsa_pub_key], sigalg='RS256') except BadSignature as e: current_app.logger.info('The JWS was not properly signed') return make_response('Invalid signature', 400) except Exception as e: current_app.logger.info(str(e)) return make_response('Invalid JWS', 400) try: verified_payload_country = verified_payload.pop('country') verified_payload_opaque = verified_payload.pop('opaque') # The opaque contains nonce and token verified_payload_ref = verified_payload.pop('ref') verified_payload_ssn = verified_payload.pop('ssn') except KeyError: current_app.logger.info('The verified JWS payload is missing some required claims') return make_response('The verified JWS payload is missing some required claims', 400) # Make sure that we have processed all claims in the payload if len(verified_payload) == 0: try: verified_opaque_deserialized = parse_opaque_data(verified_payload_opaque) except InvalidOpaqueDataError as e: # This is by design since we want the message from this exception return make_response(str(e), 400) if verified_opaque_deserialized['nonce'] == current_app.config.get('FREJA_TEST_NONCE', None): current_app.logger.info('Received a valid callback-test') return make_response('OK', 200) auth_req_data = current_app.authn_requests.pop(verified_opaque_deserialized['nonce'], None) if not auth_req_data: current_app.logger.info('Unknown nonce in verified JWS payload: \'{!s}\''.format(verified_opaque_deserialized['nonce'])) return make_response('Unknown nonce in verified JWS payload', 400) user_id = str(uuid.uuid4()) current_app.users[user_id] = { 'results': { 'freja_eid': { 'vetting_time': time.time(), 'country': verified_payload_country, 'opaque': verified_payload_opaque, 'ref': verified_payload_ref, 'ssn': verified_payload_ssn, } } } auth_req = AuthorizationRequest(**auth_req_data) authn_response = create_authentication_response(auth_req=auth_req, user_id=user_id, extra_userinfo=extra_userinfo) response_url = authn_response.request(auth_req['redirect_uri'], should_fragment_encode(auth_req)) headers = {'Authorization': 'Bearer {}'.format(verified_opaque_deserialized['token'])} current_app.authn_response_queue.enqueue(deliver_response_task, response_url, headers=headers) return make_response('OK', 200) current_app.logger.info('Received an invalid verisec callback') return make_response('Invalid request', 400)