Example #1
0
    def Demo_Ping(self, request, context):
        common.authenticate(context, must_be_one_of=(b"PEP3 demonstrator", ))
        if request.cause_message:
            self._dispatch_message(
                pep3_pb2.Message(text="Pong", code=pep3_pb2.Message.INFO))

        return pep3_pb2.PingResponse(uptime=int(time.time() - self._starttime))
Example #2
0
    def Query(self, query, context):
        common.authenticate(context,
                must_be_one_of=[b"PEP3 researcher", b"PEP3 investigator"])

        secret_local_key = self.pep.private_keys["pseudonym"]

        names = []

        # decrypt pseudonymizable parameters
        for parameter in query.parameters.values():
            if parameter.WhichOneof('kind')=='pseudonymizable_value':
                names.append(parameter.pseudonymizable_value)

        self.pep.decrypt(names, secret_local_key)

        for chunk in self.pep.connect_to("database").Query(query):

            # encrypt pseudonymizable cells
            names.clear() 
            for row in chunk.rows:
                for cell in row.cells:
                    if cell.WhichOneof('kind')=='pseudonymizable_value':
                        names.append(cell.pseudonymizable_value)

            self.pep.encrypt(names)

            yield chunk
Example #3
0
    def Store(self, request_it, context):
        common.authenticate(context, 
                must_be_one_of=[b"PEP3 collector"])
        # the flowrecords are stored asynchronously, using the self.queue
        # the feedback is returned asynchronously too, via the following
        # feedback queue.  We use the expected_responses counter to
        # see when we all responses we expected.
        expected_responses = 0
        request_it_done = False
        feedback_queue = xqueue.Queue()
        self.feedback_queues.add(feedback_queue)

        fut = self.sf.pep._executor.submit(
                self.Store_process_request_it, request_it, context,
                    feedback_queue)

        while expected_responses > 0 or not request_it_done:
            store_feedback, stopped = feedback_queue.get()
            if stopped:
                return
            if store_feedback==None: 
                # Signal that Store_processs_request_it has completed
                request_it_done = True
                e = fut.exception()
                if e!=None:
                    raise e
                expected_responses += fut.result()
                continue
            expected_responses -= 1
            yield store_feedback

        self.feedback_queues.remove(feedback_queue)
Example #4
0
    def Query(self, query, context):
        common.authenticate(
            context,
            must_be_one_of=[b"PEP3 " + self.pep.my_type_name.encode('utf-8')])
        # \_ so we can call Query from Investigator

        secret_local_key = self.pep.private_keys['pseudonym']

        sf_name = b"PEP3 storage_facility"
        my_name = b"PEP3 researcher"

        # gather pseudonymizable parameters to the query
        names = []
        for parameter in query.parameters.values():
            if parameter.WhichOneof("kind") == 'pseudonymizable_value':
                names.append(parameter.pseudonymizable_value)

        # encrypt, and localize from researcher to sf
        self.pep.encrypt(names)
        self.pep.relocalize(names, self.pep.config.warrants.from_me_to_sf)

        for chunk in self.pep.connect_to("storage_facility").Query(query):

            # localize from sf to researcher, and decrypt
            names.clear()
            for row in chunk.rows:
                for value in row.cells:
                    if value.WhichOneof("kind") == 'pseudonymizable_value':
                        names.append(value.pseudonymizable_value)

            self.pep.relocalize(names, self.pep.config.warrants.from_sf_to_me)
            self.pep.decrypt(names, secret_local_key)

            yield chunk
Example #5
0
    def Demo_SetMode(self, mode, context):
        common.authenticate(context, must_be_one_of=(b"PEP3 demonstrator", ))

        self._mode = mode.mode
        self._dispatch_message(
            pep3_pb2.Message(text="Set mode", code=pep3_pb2.Message.OK))

        return pep3_pb2.Void()
Example #6
0
    def Depseudonymize(self, request, context):
        common.authenticate(
            context,
            must_be_one_of=[b"PEP3 " + self.pep.my_type_name.encode('utf-8')])

        result = pep3_pb2.Pseudonymizable()

        self.pep.depseudonymize(request, result)

        return result
Example #7
0
    def Demo_Monitor(self, void, context):
        common.authenticate(context, must_be_one_of=(b"PEP3 demonstrator", ))

        q = queue.SimpleQueue()

        with self.messages_lock:
            self.messages_queues.append(q)

        try:
            while True:
                yield q.get()
        finally:
            with self.messages_lock:
                self.messages_queues.remove(q)
Example #8
0
    def Store(self, request_it, context):
        common.authenticate(context, must_be_one_of=[b"PEP3 storage_facility"])

        for request in request_it:
            local_session = self.Session()
            local_session.bulk_insert_mappings(PepedFlow, [
                dict(start_time=record.anonymous_part.start_time,
                     end_time=record.anonymous_part.end_time,
                     p_src_ip=record.source_ip.data,
                     p_dst_ip=record.destination_ip.data,
                     src_port=record.anonymous_part.source_port,
                     dst_port=record.anonymous_part.destination_port,
                     protocol=record.anonymous_part.protocol,
                     packets=record.anonymous_part.number_of_packets,
                     bytes=record.anonymous_part.number_of_bytes)
                for record in request.records
            ])
            local_session.commit()
            yield pep3_pb2.StoreFeedback(stored_id=request.id)
Example #9
0
def get_device(uid, psk):
    if not request.headers.get('X-Auth-Token'):
        abort(401)
    if common.authenticate(uid, request.remote_addr,
                           request.headers.get('X-Auth-Token')) is not True:
        abort(401)

    result = common.psk_lookup(uid, psk)
    if len(result) == 0:
        abort(404)
    return jsonify({'device': result[0]})
Example #10
0
    def Enroll(self, request, context):
        common_name = common.authenticate(context)

        # TODO: have a smarter check
        return_components = (common_name == b"PEP3 investigator"
                             or common_name == b"PEP3 researcher")

        response = pep3_pb2.EnrollmentResponse()

        # 1. [ REMOVED ]

        # 2. set response.by_shard[...].private_local_keys
        #        and response.components[...].keys

        e = ed25519.scalar_unpack(common.sha256(common_name))
        # "e" is the exponent used to compute the key/pseudonym components

        for shard, shard_secrets in self.pep.secrets.by_shard.items():
            for domain, domain_secrets in shard_secrets.by_domain.items():
                x = ed25519.scalar_unpack(domain_secrets.private_master_key)
                k = ed25519.scalar_unpack(domain_secrets.key_component_secret)

                k_local = pow(k, e, ed25519.l)

                if return_components:
                    self.pep._cryptopu.certified_component_create(
                            response.components[shard].keys[domain],
                            self.pep.global_config.\
                                    components[shard].keys[domain].\
                                    base_times_two_to_the_power_of,
                            k, e)

                x_local = (k_local * x) % ed25519.l

                response.by_shard[shard].private_local_keys[domain]\
                        = ed25519.scalar_pack(x_local)

        # 3. set response.components[...].pseudonym

        if return_components:
            for shard in self.pep.config.shards:
                s = ed25519.scalar_unpack(
                        self.pep.secrets.by_shard[shard]\
                                .pseudonym_component_secret)

                self.pep._cryptopu.certified_component_create(
                        response.components[shard].pseudonym,
                        self.pep.global_config.\
                                components[shard].pseudonym.\
                                base_times_two_to_the_power_of,
                        s, e)

        return response
Example #11
0
    def Store(self, request_it, context):
        common.authenticate(context, must_be_one_of=[b"PEP3 collector"])

        # the flowrecords are stored asynchronously, using the self.queue
        # the feedback is returned asynchronously too, via the following
        # feedback queue.  We use the expected_responses counter to
        # see when we all responses we expected.
        expected_responses = 0
        feedback_queue = queue.SimpleQueue()

        for request in request_it:

            if request.id in self.request_id_to_feedback_queue:
                raise ValueError("request id already in use")

            self.request_id_to_feedback_queue[request.id] = feedback_queue
            expected_responses += 1

            raw_ips = []

            for flowrecord in request.records:
                common.check_is_plaintext(flowrecord.source_ip, context)
                common.check_is_plaintext(flowrecord.destination_ip, context)

                raw_ips.append(flowrecord.source_ip.data)
                raw_ips.append(flowrecord.destination_ip.data)

            self.cache.request(
                raw_ips,
                functools.partial(self._handle_request_with_cached_ips,
                                  request))

        self.cache.flush()
        self.queue.put(None)  # flush storage facility too

        while expected_responses > 0:
            store_feedback = feedback_queue.get()
            expected_responses -= 1
            yield store_feedback
Example #12
0
    def Query(self, query, context):
        common.authenticate(context, must_be_one_of=[b"PEP3 storage_facility"])

        local_session = self.Session()

        params = {}
        param_desc = {}

        for name, value in query.parameters.items():
            params[name], param_desc[name] \
                    = common.value_to_object_and_type(value)

        try:
            result_desc = sql.check_query(self.db_desc, param_desc,
                                          query.query)
        except sql.InvalidQuery as e:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          f"invalid query: {e}")

        sql_rows = local_session.execute(query.query, params)

        pb_rows = pep3_pb2.Rows()

        for sql_row in sql_rows:
            assert (len(sql_row) == len(result_desc))

            pb_row = pb_rows.rows.add()

            for i in range(len(result_desc)):
                pb_cell = pb_row.cells.add()
                common.object_and_type_to_value(pb_cell, sql_row[i],
                                                result_desc[i])

            if len(pb_rows.rows) == 32:
                yield pb_rows
                pb_rows.Clear()
        if len(pb_rows.rows) > 0:
            yield pb_rows
Example #13
0
def play_game():
    if not common.authenticate():
        return

    currentvideo_id = vars.params.get("video_id")
    currentvideo_type = vars.params.get("video_type")
    start_time = vars.params.get("start_time")
    duration = vars.params.get("duration")
    currentvideo_ishomefeed = vars.params.get("video_ishomefeed", "1")
    currentvideo_ishomefeed = currentvideo_ishomefeed == "1"

    # Authentication is needed over this point!
    game = get_game(currentvideo_id, currentvideo_type, currentvideo_ishomefeed, start_time, duration)
    if game is not None:
        common.play(game)
Example #14
0
    def cmh_auth(self, module, message, additional_data, cm):
        if common.authenticate(message[len(common.CONTROL_AUTH):]):
            module.setup_authenticated_client(
                message[len(common.CONTROL_AUTH):], additional_data)

            common.internal_print("Client authenticated", 1, module.verbosity,
                                  common.DEBUG)

            return module.cmh_struct[cm][3]
        else:
            module.send(common.CONTROL_CHANNEL_BYTE, common.CONTROL_AUTH_NOTOK,
                        additional_data)
            common.internal_print("Client authentication failed", -1,
                                  module.verbosity, common.DEBUG)

        return module.cmh_struct[cm][4]
Example #15
0
    def get_episode(start_timestamp, duration):
        if not common.authenticate():
            return None

        url = vars.config['publish_endpoint']
        headers = {
            'Cookie':
            vars.cookies,
            'Content-Type':
            'application/x-www-form-urlencoded',
            'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
        }
        body = {
            'type': 'channel',
            'id': 1,
            'drmtoken': True,
            'token': vars.access_token,
            'deviceid': xbmc.getInfoLabel('Network.MacAddress'),  # TODO
            'st': start_timestamp,
            'dur': duration,
            'pcid': vars.player_id,
            'format': 'xml',
        }

        body = urllib.urlencode(body)
        utils.log('the body of publishpoint request is: %s' % body,
                  xbmc.LOGDEBUG)

        try:
            request = urllib2.Request(url, body, headers)
            response = urllib2.urlopen(request)
            content = response.read()
        except urllib2.HTTPError as err:
            utils.logHttpException(err, url)
            utils.littleErrorPopup(xbmcaddon.Addon().getLocalizedString(50020))
            return None

        xml = parseString(str(content))
        url = xml.getElementsByTagName('path')[0].childNodes[0].nodeValue
        utils.log('response URL from publishpoint: %s' % url, xbmc.LOGDEBUG)
        drm = xml.getElementsByTagName('drmToken')[0].childNodes[0].nodeValue
        utils.log(drm, xbmc.LOGDEBUG)

        return {'url': url, 'drm': drm}
Example #16
0
    def RegisterComponents(self, request, context):
        common_name = common.authenticate(context)
        e = ed25519.scalar_unpack(common.sha256(common_name))

        response = pep3_pb2.ComponentsRegistrationResponse()

        for shard, by_shard in request.components.items():
            if not self.pep._cryptopu.certified_component_is_valid_for(
                    by_shard.pseudonym,
                    self.pep.global_config.components[shard].pseudonym.\
                            base_times_two_to_the_power_of,
                    e):
                context.abort(
                    grpc.StatusCode.INVALID_ARGUMENT,
                    f'pseudonym component for shard {shard} '
                    'could not be verified')

            reminder = response.reminders.add()
            reminder.component = by_shard.pseudonym.component
            reminder.shard = shard
            reminder.pseudonym.SetInParent()  # this sets reminder.pseudonym
            common.sign_protobuf(reminder,
                                 self.pep.secrets.reminders_hmac_secret)

            for domain, cc_msg in by_shard.keys.items():
                if not self.pep._cryptopu.certified_component_is_valid_for(
                        cc_msg,
                        self.pep.global_config.components[shard].\
                                keys[domain].base_times_two_to_the_power_of,
                        e):
                    context.abort(
                        grpc.StatusCode.INVALID_ARGUMENT,
                        f'{domain} key component for shard {shard} '
                        'could not be verified')

                reminder = response.reminders.add()
                reminder.component = cc_msg.component
                reminder.shard = shard
                reminder.key.domain = domain
                common.sign_protobuf(reminder,
                                     self.pep.secrets.reminders_hmac_secret)

        return response
Example #17
0
def update_mac(uid, id):
    if not request.headers.get('X-Auth-Token'):
        abort(401)
    if common.authenticate(uid, request.remote_addr,
                           request.headers.get('X-Auth-Token')) is not True:
        abort(401)

    result = common.dev_lookup(uid, id)
    if len(result) == 0:
        abort(404)
    if not request.json:
        abort(400)
    if 'mac_add' in request.json and type(
            request.json['mac_add']) is not unicode:
        abort(400)
    # Confirm a valid mac exists in the request using regex
    mac_parse = re.compile(ur'(?:[0-9a-fA-F]:?){12}')
    mac_list = re.findall(mac_parse, request.json['mac_add'])
    # If there is not exactly 1 mac address matched, abort
    if len(mac_list) is not 1:
        abort(400)

    return jsonify({"status": common.update_mac(id, mac_list[0])})
Example #18
0
 def get_serie_episode():
     video_id = vars.params.get("url")
     if not common.authenticate():
         return None
     url = vars.config['publish_endpoint']
     headers = {
         'Cookie': vars.cookies,
         'Content-Type': 'application/x-www-form-urlencoded',
         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
     }
     body = {
         'type': 'video',
         'id': video_id,
         'drmtoken': True,
         'token': vars.access_token,
         'deviceid': 'web-%s' % vars.player_id,
         'pcid': vars.player_id,
         'format': 'json',
     }
     body = urlencode(body).encode()
     utils.log('the body of publishpoint request is: %s' % body, xbmc.LOGDEBUG)
     try:
         request = urllib2.Request(url, body, headers)
         response = urllib2.urlopen(request, timeout=30)
         content = response.read()
     except urllib2.HTTPError as err:
         utils.logHttpException(err, url)
         utils.littleErrorPopup(xbmcaddon.Addon().getLocalizedString(50020))
         return None
     content_json = json.loads(content)
     url = content_json['path']
     drm = content_json['drmToken']
     utils.log('response URL from publishpoint: %s' % url, xbmc.LOGDEBUG)
     utils.log(drm, xbmc.LOGDEBUG)
     
     return {'url': url, 'drm': drm}
Example #19
0
parser.add_argument('-i',
                    '--db-dir',
                    type=str,
                    default="db",
                    help='Folder where we store all of the information')
args = parser.parse_args()
# -----------------------------------------------------------------------------

assert args.depth in [
    0, 1
], "for now depth should be either 0 or 1. Anything else is likely to take way too long."

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

api = authenticate()
db = LOLDB(args.db_dir)


def download_user(user):
    if args.cache and user in db:
        return  # nothing to be done
    # hit the Twitter API to get the information
    friends = api_iter(api.friends, user, args.max_friends)
    tweets = api_iter(api.user_timeline, user, args.max_tweets)
    blob = {'time': time.time(), 'friends': friends, 'tweets': tweets}
    # back the information up in database for later
    db[user] = blob


logging.info("fetching user %s" % (args.user, ))
Example #20
0
      try:
        common.log('INFO', 'Below Threshold - Scaling Down')
        scale_policy = sg.get_policy(config.get(group, 'scale_down_policy'))
        scale_policy.execute()
      except:
        common.log('ERROR', 'Cannot execute scale down policy')
    else:
      common.log('INFO', 'Cluster within target paramters')
    
    common.log('OK', 'Policy execution completed')

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--region', required=False,
    help='The region to build the servers',
    choices=['SYD', 'HKG', 'DFW', 'ORD', 'IAD', 'LON'],
    default=pyrax.default_region)
  parser.add_argument('--as-group', required=True,
    help='The autoscale group config ID')
  parser.add_argument('--cluster', required=False, default=False, action='store_true')

  args = vars(parser.parse_args())
  common.authenticate(args['region'])

  try:
    config = common.get_config(args['as_group'])
  except:
    common.log('ERROR', 'Unknown config section ' + args['as_group'])
  
  autoscale(args['as_group'], config, args['cluster'])
Example #21
0
    def Depseudonymize(self, request, context):
        common_name = common.authenticate(context)
        e = ed25519.scalar_unpack(common.sha256(common_name))

        self._dispatch_message(
            pep3_pb2.Message(text="Depseudonymizing",
                             code=pep3_pb2.Message.OK))

        # catch trivial errors
        if len(request.warrant.signature) == 0:
            context.abort(grpc.StatusCode.PERMISSION_DENIED,
                          "warrant has empty signature")

        if len(request.which_shards) == 0:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          "request.which_shards is empty")

        # verify warrant
        if common_name != request.warrant.act.actor:
            context.abort(
                grpc.StatusCode.PERMISSION_DENIED,
                f"you, {common_name}, presented a warrant that "
                f"was issued to {request.warrant.act.actor}")

        try:
            crypto.verify(
                crypto.load_certificate(
                    crypto.FILETYPE_PEM,
                    self.pep.global_config.root_certificates.warrants),
                request.warrant.signature,
                request.warrant.act.SerializeToString(), 'sha256')
        except crypto.Error as e:
            context.abort(grpc.StatusCode.PERMISSION_DENIED,
                          "the warrant's signature appears to be invalid")

        # verify reminders
        for i, reminder in enumerate(request.reminders):
            if not common.verify_protobuf_signature(
                    reminder, self.pep.secrets.reminders_hmac_secret):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              f"could not verify reminder #{i}.")

        # verify chain
        name = request.warrant.act.name
        name_unpacked = elgamal.Triple.unpack(name.data)

        for i, link in enumerate(request.chain):
            if link.peer not in self.pep.global_config.peers:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              f"unknown peer '{link.peer}' in link #{i}")

            for shard in link.which_shards:
                if shard not in self.pep.global_config\
                        .peers[link.peer].shards:
                    context.abort(
                        grpc.StatusCode.PERMISSION_DENIED,
                        f"the peer {link.peer} of link #{i} "
                        f"doesn't hold the shard {shard}!")

            rs_p = schnorr.RSProof.unpack(link.peer_response.rs_proof)
            sB_p = schnorr.DHTProof.unpack(link.peer_response.sB_proof)
            sB = ed25519.Point.unpack(link.peer_response.sB)
            kB = ed25519.Point.B_times(1)
            s_inv_B = ed25519.Point.unpack(link.peer_response.s_inv_B)

            link_name_unpacked = elgamal.Triple.unpack(
                link.peer_response.name.data)

            # check that s_inv_B is the inverse of sB
            if not sB_p.is_valid_proof_for(sB, s_inv_B,
                                           ed25519.Point.B_times(1)):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              f"could not verify the sB proof of link #{i}.")

            # check the rs-operation was performed correctly
            if not rs_p.is_valid_proof_for(name_unpacked, sB,
                                           link_name_unpacked):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              f"could not verify the rs proof of link #{i}.")

            # check that s_inv_B is indeed the product of their factors
            s_inv_B_factors = [
                ed25519.Point.unpack(pp)
                for pp in link.peer_response.s_inv_B_factors
            ]

            s_inv_B_p = schnorr.ProductProof.from_protobuf(
                link.peer_response.s_inv_B_proof)

            if not s_inv_B_p.is_valid_proof_for(s_inv_B, s_inv_B_factors):
                context.abort(
                    grpc.StatusCode.PERMISSION_DENIED,
                    "could not verify the s_inv_B product proof "
                    f"for link #{i}.")

            # make a lookup dictionary for the reminders
            reminders = {}
            for reminder in request.reminders:
                component = reminder.component
                if component in reminders:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  "double reminder")
                reminders[component] = reminder

            # check that the provided factors are valid
            for j, shard in enumerate(link.which_shards):
                # check s_inv_B factor
                s_inv_B_factor_packed = link.peer_response.s_inv_B_factors[j]

                if shard in self.pep.config.shards:
                    # we can check s_inv_B by computing it ourselves
                    s_ = ed25519.scalar_unpack(self.pep.secrets\
                            .by_shard[shard].pseudonym_component_secret)
                    s_B = ed25519.Point.B_times(pow(s_, e, ed25519.l))
                    if s_B.pack() != s_inv_B_factor_packed:
                        context.abort(
                            grpc.StatusCode.PERMISSION_DENIED,
                            f"s_inv_B factor #{j} (for shard {shard}, "
                            f"and common name {common_name}, e={e})"
                            f" of link #{i} is not correct: it should be "
                            f"{s_B.pack()}, but {s_inv_B_factor_packed} "
                            "was given.")
                else:  # we need a reminder that s_inv_B is correct
                    if s_inv_B_factor_packed not in reminders:
                        context.abort(
                            grpc.StatusCode.PERMISSION_DENIED,
                            f"missing reminder that s_inv_B factor #{j} "
                            f"of link #{i} is correct.")
                    rem = reminders[s_inv_B_factor_packed]

                    assert (rem.component == s_inv_B_factor_packed)
                    error_message = None
                    if not rem.HasField("pseudonym"):
                        error_message = "reminder is for a key component"\
                                f" instead of a pseudonym component"
                    elif rem.shard != shard:
                        error_message = "reminder is for "\
                                f"the shard {rem.shard}"\
                                f" instead of the shard {shard}"
                    if error_message != None:
                        context.abort(
                            grpc.StatusCode.PERMISSION_DENIED,
                            f"s_inv_B factor #{j} of link #{i} "
                            "is not correct: " + error_message)

            name = link.peer_response.name
            name_unpacked = link_name_unpacked

        # the provided request seems to be in order;
        # let us prepare our response.

        response = pep3_pb2.DepseudonymizationResponse()

        # compute rekey and reshuffle components
        k = s_inv = 1
        s_inv_factors = []

        for shard in request.which_shards:
            s_inv_factor = pow(ed25519.scalar_unpack(self.pep.secrets\
                        .by_shard[shard].pseudonym_component_secret),
                e, ed25519.l)
            s_inv_factors.append(s_inv_factor)

            s_inv *= s_inv_factor
            s_inv %= ed25519.l

        s = ed25519.scalar_inv(s_inv)
        r = ed25519.scalar_random()

        rs_proof, name_out = schnorr.RSProof.create(name_unpacked, s, r)
        response.rs_proof = rs_proof.pack()

        response.name.data = name_out.pack()
        response.name.state \
                = pep3_pb2.Pseudonymizable.ENCRYPTED_PSEUDONYM

        # compute proofs for the reshuffle components
        s_inv_B_proof, s_inv_B_factors, s_inv_B \
                = schnorr.ProductProof.create(s_inv_factors)
        s_inv_B_proof.to_protobuf(response.s_inv_B_proof)
        for s_inv_B_factor in s_inv_B_factors:
            response.s_inv_B_factors.append(s_inv_B_factor.pack())
        response.s_inv_B = s_inv_B.pack()

        sB = ed25519.Point.B_times(s)
        sB_proof = schnorr.DHTProof.create(s,
                                           s_inv_B,
                                           A=sB,
                                           N=ed25519.Point.B_times(1))

        response.sB = sB.pack()
        response.sB_proof = sB_proof.pack()

        return response
Example #22
0
    def Relocalize(self, request, context):
        common_name = common.authenticate(context)

        self._dispatch_message(
            pep3_pb2.Message(text="Relocalizing", code=pep3_pb2.Message.OK))

        # catch trivial errors
        if len(request.warrant.signature) == 0:
            context.abort(grpc.StatusCode.PERMISSION_DENIED,
                          "warrant has empty signature")

        if len(request.which_shards) == 0:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          "request.which_shards is empty")

        if len(request.names) == 0:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          "request.names is empty")

        # verify warrant
        if common_name != request.warrant.act.actor:
            context.abort(
                grpc.StatusCode.PERMISSION_DENIED,
                f"you, {common_name}, presented a warrant that "
                f"was issued to {request.warrant.act.actor}")

        try:
            crypto.verify(
                crypto.load_certificate(
                    crypto.FILETYPE_PEM,
                    self.pep.global_config.root_certificates.warrants),
                request.warrant.signature,
                request.warrant.act.SerializeToString(), 'sha256')
        except crypto.Error as e:
            context.abort(grpc.StatusCode.PERMISSION_DENIED,
                          "the warrant's signature appears to be invalid")

        response = pep3_pb2.RelocalizationResponse()

        act = request.warrant.act

        k = s = 1
        for shard in request.which_shards:
            s *= pow(ed25519.scalar_unpack(self.pep.secrets.by_shard[shard]\
                        .pseudonym_component_secret),
                ed25519.scalar_unpack(common.sha256(act.target)), ed25519.l)
            s %= ed25519.l

        if act.encrypt_for != b"":
            for shard in request.which_shards:
                k *= pow(ed25519.scalar_unpack(self.pep.secrets.by_shard[shard]\
                            .by_domain["pseudonym"].key_component_secret),
                    ed25519.scalar_unpack(common.sha256(act.encrypt_for)),
                    ed25519.l)
                k %= ed25519.l

        k_inv_comp = 1
        encrypt_from = act.source
        if encrypt_from == b"plaintext":
            encrypt_from = act.actor
        for shard in request.which_shards:
            k_inv_comp *= \
                pow(ed25519.scalar_unpack(self.pep.secrets.by_shard[shard]\
                        .by_domain["pseudonym"].key_component_secret),
                ed25519.scalar_unpack(common.sha256(encrypt_from)),
                ed25519.l)
            k_inv_comp %= ed25519.l
        k = (k * ed25519.scalar_inv(k_inv_comp)) % ed25519.l

        if act.source != b"plaintext":
            for shard in request.which_shards:
                s *= ed25519.scalar_inv(pow(ed25519.scalar_unpack(
                    self.pep.secrets.by_shard[shard]\
                            .pseudonym_component_secret),
                    ed25519.scalar_unpack(common.sha256(act.source)),
                    ed25519.l))
                s %= ed25519.l

        names = request.names

        # reshuffle, rekey, and rerandomize
        try:
            self.pep._cryptopu.rsk(
                names, k, s,
                [ed25519.scalar_random() for i in range(len(names))])
        except cryptopu.InvalidArgument as e:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT, str(e))

        # change the state of the names if we rekeyed
        if act.encrypt_for != b"":
            for i in range(len(names)):
                names[i].state \
                        = pep3_pb2.Pseudonymizable.ENCRYPTED_PSEUDONYM

        response.names.extend(names)

        return response