예제 #1
0
    def test_localization_of_pseudonym(self):
        name = b" a 16 byte name "
        target = b"PEP3 storage_facility"

        pp = pep3_pb2.Pseudonymizable(
            data=name, state=pep3_pb2.Pseudonymizable.UNENCRYPTED_NAME)

        self.collector.pseudonymize([pp])
        self.collector.relocalize([pp], self.config.collector.warrants.to_sf)

        sfp = elgamal.Triple.unpack(pp.data)\
                .decrypt(self.sf.private_keys['pseudonym'])

        pseudonym_secrets = {}
        for peer_secrets in self.secrets.peers.values():
            for shard, shard_secrets in peer_secrets.by_shard.items():
                pseudonym_secrets[shard] \
                        = shard_secrets.pseudonym_component_secret

        s = 1
        e = ed25519.scalar_unpack(common.sha256(target))
        for secret in pseudonym_secrets.values():
            s *= pow(ed25519.scalar_unpack(secret), e, ed25519.l)
            s %= ed25519.l

        self.assertEqual(sfp * ed25519.scalar_inv(s),
                         ed25519.Point.lizard(name))
예제 #2
0
    def create(triple, k, n, r):
        c = triple.core
        b = triple.blinding
        y = triple.target

        nkinv = ( n * ed25519.scalar_inv(k) ) % ed25519.l
        nkinvB = ed25519.Point.B_times(nkinv)
        
        R_B = ed25519.Point.B_times(r)
        R_y = y * r

        K_B = ed25519.Point.B_times(k)

        beta_ = b+R_B
        gamma_ = c+R_y

        beta = beta_*nkinv
        gamma = gamma_*n
        tau = y*k

        return ( RSKProof(R_B, R_y, nkinvB, beta_, gamma_,
                DHTProof.create(r, y, A=R_B, N=R_y),
                DHTProof.create(k, y, A=K_B, N=tau),
                DHTProof.create(k, nkinvB, A=K_B),
                DHTProof.create(nkinv, beta_, A=nkinvB, N=beta),
                DHTProof.create(n, gamma_, N=gamma) ),
                elgamal.Triple( beta, gamma, tau ) )
예제 #3
0
    def test_rekey(self):
        m = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        k = ed25519.scalar_random()

        self.assertEqual(
                elgamal.encrypt(m,y,r).rekey(k),
                elgamal.encrypt(m,y*k,ed25519.scalar_inv(k)*r)
            )       
예제 #4
0
    def rsk(self, rekey_scalar, reshuffle_scalar, rerandomization_scalar=None):
        if rerandomization_scalar == None:
            rerandomization_scalar = ed25519.scalar_random()

        return Triple(
                blinding = self.blinding \
                        * (ed25519.scalar_inv(rekey_scalar) * reshuffle_scalar)
                + ed25519.Point.B_times(rerandomization_scalar),

                core = self.core * reshuffle_scalar
                    + self.target * (rekey_scalar * rerandomization_scalar),

                target = self.target * rekey_scalar
            )
예제 #5
0
파일: peer.py 프로젝트: vwdata-p3/webdemo
    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
예제 #6
0
파일: peer.py 프로젝트: vwdata-p3/webdemo
    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
예제 #7
0
 def rekey(self, component):
     return Triple(self.blinding * ed25519.scalar_inv(component), self.core,
                   self.target * component)