Пример #1
0
    def test_rsk(self):
        N = 5

        n = ed25519.scalar_random()
        k = ed25519.scalar_random()
        r = [ed25519.scalar_random() for i in range(N)]

        target = ed25519.Point.random()

        triples = [
            elgamal.encrypt(ed25519.Point.random(), target) for i in range(N)
        ]

        pseudonyms = [pep3_pb2.Pseudonymizable() for i in range(N)]

        for i in range(N):
            pseudonyms[i].data = triples[i].pack()

        self.pu.rsk(pseudonyms, k, n, r)

        for i in range(N):
            triples[i] = triples[i].rsk(k, n, r[i])

        self.assertEqual(
            [triples[i] for i in range(N)],
            [elgamal.Triple.unpack(pseudonyms[i].data) for i in range(N)])
Пример #2
0
 def test_to_protobuf(self):
     msg = pep3_pb2.CertifiedComponent()
     k = ed25519.scalar_random()
     e = ed25519.scalar_random()
     cc = schnorr.CertifiedComponent.create(k, e)
     cc.to_protobuf(msg)
     self.assertEqual(cc, schnorr.CertifiedComponent.from_protobuf(msg))
Пример #3
0
    def test_create(self):
        M = ed25519.Point.random()
        a = ed25519.scalar_random()

        ct = schnorr.DHTProof.create(a, M)

        A = ed25519.Point.B_times(a)
        N = M * a

        self.assertTrue(ct.is_valid_proof_for(A, M, N))

        self.assertFalse(ct.is_valid_proof_for(ed25519.Point.random(), M, N))
        self.assertFalse(ct.is_valid_proof_for(A, ed25519.Point.random(), N))
        self.assertFalse(ct.is_valid_proof_for(A, M, ed25519.Point.random()))

        ct_ = copy.deepcopy(ct)
        ct_._R_M = ed25519.Point.random()
        self.assertFalse(ct_.is_valid_proof_for(A, M, N))

        ct_ = copy.deepcopy(ct)
        ct_._R_B = ed25519.Point.random()
        self.assertFalse(ct_.is_valid_proof_for(A, M, N))

        ct_ = copy.deepcopy(ct)
        ct_._s = ed25519.scalar_random()
        self.assertFalse(ct_.is_valid_proof_for(A, M, N))
Пример #4
0
    def test_dht_proof_create(self):
        cbuf = ristretto.ffi.new("unsigned char[]", 96)
        buf = ristretto.ffi.buffer(cbuf)

        for i in range(10):
            a = ed25519.scalar_random()
            m = ed25519.scalar_random()
            A = ed25519.Point.B_times(a)
            M = ed25519.Point.B_times(m)
            N = M*a

            if i%2==0:
                cm = scalar_to_c(m)
                cM = ristretto.ffi.NULL
            else:
                cm = ristretto.ffi.NULL
                cM = point_to_c(M)
            
            ristretto.lib.dht_proof_create(
                    cbuf, 
                    scalar_to_c(a), ed25519.scalar_pack(a), A.pack(),
                    cm, cM, M.pack(),
                    point_to_c(N), N.pack())

            self.assertEqual(schnorr.DHTProof.create(a,M).pack(),
                    buf[:])
Пример #5
0
 def benchmark_certified_component(self, args):
     for i in range(1):
         k = ed25519.scalar_random()
         e = ed25519.scalar_random()
         cc = schnorr.CertifiedComponent.create(k,e)
         assert(cc.is_valid_proof_for(e,
                 [ed25519.Point.B_times(pow(k,2**i,ed25519.l))
                     for i in range(253) ] ))
Пример #6
0
    def test_pack(self):
        M = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        n = ed25519.scalar_random()
        triple_in = elgamal.encrypt(M, y)
        rsp, triple_out = schnorr.RSProof.create(triple_in, n, r)

        self.assertEqual(rsp, schnorr.RSProof.unpack(rsp.pack()))
Пример #7
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)
            )       
Пример #8
0
    def test_reshuffle(self):
        m = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        n = ed25519.scalar_random()

        self.assertEqual(
                elgamal.encrypt(m,y,r).reshuffle(n),
                elgamal.encrypt(m*n,y,r*n)
            )       
Пример #9
0
 def test_rerandomization(self):
     m = ed25519.Point.random()
     y = ed25519.Point.random()
     r = ed25519.scalar_random()
     s = ed25519.scalar_random()
     
     self.assertEqual(
             elgamal.encrypt(m,y,r).rerandomize(s),
             elgamal.encrypt(m,y,r+s)
         )
Пример #10
0
    def test_certified_component_create(self):
        k = ed25519.scalar_random()
        e = ed25519.scalar_random()

        ones = schnorr.ones_of(e)
        N = len(list(ones))

        ccc = ristretto.ffi.new("certified_component*")
        cpp = ccc.product_proof

        # prepare cpp
        cpp.number_of_factors = N
        cpartial_products = ristretto.ffi.new("unsigned char[]", 
                32*max(N-2,0))
        cpp.partial_products = cpartial_products
        cdht_proofs = ristretto.ffi.new("unsigned char[]", 96*max(N-1,0))
        cpp.dht_proofs = cdht_proofs

        # prepare cbase_powers_packed
        cbase_powers_packed = ristretto.ffi.new("unsigned char[]", 32*253)
        cbase_powers = ristretto.ffi.new("group_ge[]", 253)
        ristretto.lib.component_public_part(cbase_powers, scalar_to_c(k))
        ristretto.lib.group_ges_pack(cbase_powers_packed, cbase_powers, 253)

        ristretto.lib.certified_component_create(ccc,
                cbase_powers_packed,
                scalar_to_c(k),
                scalar_to_c(e))

        cc = schnorr.CertifiedComponent.create(k, e)
        pp = cc._product_proof

        self.assertEqual(cc._component.pack(), 
                ristretto.ffi.buffer(ccc.component)[:])


        dht_proofs_buf = ristretto.ffi.buffer(cpp.dht_proofs, 96*max(N-1,0))
        partial_products_buf = ristretto.ffi.buffer(
                cpp.partial_products, 32*max(N-2,0))

        for i in range(max(N-1,0)):
            self.assertEqual(pp._dht_proofs[i].pack(),
                    dht_proofs_buf[96*i:96*(i+1)])
            if i<N-2:
                self.assertEqual(pp._partial_products[i].pack(),
                        partial_products_buf[32*i:32*(i+1)])

        self.assertTrue(ristretto.lib.certified_component_is_valid_for(
                ccc, cbase_powers_packed, scalar_to_c(e)))

        # wrong exponent
        self.assertFalse(ristretto.lib.certified_component_is_valid_for(
                ccc, cbase_powers_packed, 
                scalar_to_c(ed25519.scalar_random())))
Пример #11
0
    def test_create(self):
        M = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        n = ed25519.scalar_random()
        triple_in = elgamal.encrypt(M, y)
        rsp, triple_out = schnorr.RSProof.create(triple_in, n, r)

        self.assertEqual(triple_out, triple_in.rerandomize(r).reshuffle(n))

        self.assertTrue(
            rsp.is_valid_proof_for(triple_in, ed25519.Point.B_times(n),
                                   triple_out))
Пример #12
0
    def test_rsk(self):
        m = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        n = ed25519.scalar_random()
        k = ed25519.scalar_random()
        r2 = ed25519.scalar_random()

        triple = elgamal.encrypt(m,y,r)

        self.assertEqual(
                triple.rsk(k,n,r2),
                triple.rekey(k).reshuffle(n).rerandomize(r2)
            )
Пример #13
0
 def test_component_public_part(self):
     scalar = ed25519.scalar_random()
     y = self.pu.component_public_part(scalar)
     self.assertEqual(y, [
         ed25519.Point.B_times(pow(scalar, 2**i, ed25519.l)).pack()
         for i in range(253)
     ])
Пример #14
0
    def test_triples_pack_and_unpack(self):
        n = 5

        triples = [ elgamal.encrypt(
                    ed25519.Point.random(),
                    ed25519.Point.random(),
                    ed25519.scalar_random()) for i in range(n) ]
        
        cbuf1 = ristretto.ffi.new("unsigned char[]", n*96)

        for i in range(n):
            ristretto.ffi.memmove(cbuf1 + 96*i, triples[i].pack(), 96) 

        ctriples = ristretto.ffi.new("elgamal_triple[]", n)
        cerror_codes = ristretto.ffi.new("int[]", n)

        ristretto.lib.elgamal_triples_unpack(ctriples, cbuf1, cerror_codes, n)
        
        for i in range(n):
            self.assertEqual(cerror_codes[i], 0)

        cbuf2 = ristretto.ffi.new("unsigned char[]", n*96)

        ristretto.lib.elgamal_triples_pack(cbuf2, ctriples, n)

        self.assertEqual(
                [ cbuf1[i] for i in range(96*n) ], 
                [ cbuf2[i] for i in range(96*n) ])
Пример #15
0
 def encrypt(self, names, key=None):
     if key==None:
         key = self.public_keys['pseudonym']
     for name in names:
         assert(name.state==pep3_pb2.Pseudonymizable.UNENCRYPTED_PSEUDONYM)
         name.state = pep3_pb2.Pseudonymizable.ENCRYPTED_PSEUDONYM
     self._cryptopu.encrypt(names, key, [ed25519.scalar_random() 
         for i in range(len(names))])
Пример #16
0
 def test_component_public_part(self):
     x = ed25519.scalar_random()
     cy = ristretto.ffi.new('group_ge[]',253)
     ristretto.lib.component_public_part(cy, scalar_to_c(x))
     y = points_from_c(cy, 253)
     for i in range(253):
         self.assertEqual(y[i],
                 ed25519.Point.B_times(pow(x,2**i,ed25519.l)))
Пример #17
0
 def pseudonymize(self, names):
     for name in names:
         assert(name.state==pep3_pb2.Pseudonymizable.UNENCRYPTED_NAME)
         name.state = pep3_pb2.Pseudonymizable.ENCRYPTED_PSEUDONYM
         name.data = ed25519.lizard_without_elligator(name.data)
     self._cryptopu.elligator(names)
     self._cryptopu.encrypt(names,
             self.public_keys['pseudonym'],
             [ed25519.scalar_random() for i in range(len(names))])
Пример #18
0
    def test_certified_component_create(self):
        k = ed25519.scalar_random()
        e = ed25519.scalar_random()

        cc_protobuf = pep3_pb2.CertifiedComponent()
        self.pu.certified_component_create(cc_protobuf,
                                           self.pu.component_public_part(k), k,
                                           e)

        cc = schnorr.CertifiedComponent.create(k, e)
        cc_protobuf2 = pep3_pb2.CertifiedComponent()
        cc.to_protobuf(cc_protobuf2)

        self.assertEqual(cc_protobuf2, cc_protobuf)

        self.assertTrue(
            self.pu.certified_component_is_valid_for(
                cc_protobuf, self.pu.component_public_part(k), e))
Пример #19
0
 def test_group_scalar_tstbit(self):
     s = ed25519.scalar_random()
     ones = set(schnorr.ones_of(s))
     cs = scalar_to_c(s)
     for i in range(253):
         result, = ristretto.lib.scalar_tstbit(cs, i),
         if i in ones:
             self.assertEqual(result, 1)
         else:
             self.assertEqual(result, 0)
Пример #20
0
    def test_create(self):
        # N = 0
        dht_proof, factors, product = schnorr.ProductProof.create(())
        self.assertEqual(len(factors), 0)
        self.assertEqual(product, ed25519.Point.B_times(1))
        self.assertTrue(dht_proof.is_valid_proof_for(product, factors))

        # N = 1
        a = ed25519.scalar_random()
        dht_proof, factors, product = schnorr.ProductProof.create((a, ))
        self.assertEqual(len(factors), 1)
        self.assertEqual(factors[0], product)
        self.assertEqual(product, ed25519.Point.B_times(a))
        self.assertTrue(dht_proof.is_valid_proof_for(product, factors))

        self.assertFalse(dht_proof.is_valid_proof_for(product, ()))
        factors[0] = ed25519.Point.random()
        self.assertFalse(dht_proof.is_valid_proof_for(product, factors))

        N = 10  ##
        factors_scalars = [ed25519.scalar_random() for i in range(N)]
        dht_proof, factors, product = \
                schnorr.ProductProof.create(factors_scalars)
        self.assertTrue(dht_proof.is_valid_proof_for(product, factors))

        product_scalar = 1
        for factor in factors_scalars:
            product_scalar *= factor

        self.assertEqual(product, ed25519.Point.B_times(product_scalar))

        self.assertFalse(
            dht_proof.is_valid_proof_for(ed25519.Point.random(), factors))

        i = random.choice(range(N))
        self.assertFalse(
            dht_proof.is_valid_proof_for(product,
                                         factors[:i] + factors[i + 1:]))
        self.assertFalse(
            dht_proof.is_valid_proof_for(
                product, factors[:i] + [ed25519.Point.random()] + factors[i:]))
Пример #21
0
    def test_triple_rsk(self):
        m = ed25519.Point.random()
        y = ed25519.Point.random()
        r = ed25519.scalar_random()
        s = ed25519.scalar_random()
        k = ed25519.scalar_random()
        r2 = ed25519.scalar_random()

        triple = elgamal.encrypt(m,y,r2)
        
        ctriple = ristretto.ffi.new("elgamal_triple*")
        ck = ristretto.ffi.new("group_scalar*")
        cs = ristretto.ffi.new("group_scalar*")
        cr = ristretto.ffi.new("group_scalar*")

        ristretto.lib.elgamal_triple_unpack(ctriple, 
                triple.blinding.pack() + 
                triple.core.pack() + 
                triple.target.pack())
        ristretto.lib.group_scalar_unpack(ck, ed25519.scalar_pack(k))
        ristretto.lib.group_scalar_unpack(cs, ed25519.scalar_pack(s))
        ristretto.lib.group_scalar_unpack(cr, ed25519.scalar_pack(r))

        ristretto.lib.elgamal_triple_rsk(ctriple, ctriple, ck, cs, cr)

        cbuf = ristretto.ffi.new("unsigned char []", 96)
        ristretto.lib.elgamal_triple_pack(cbuf, ctriple)
        
        buf = ristretto.ffi.buffer(cbuf)

        triple2 = elgamal.Triple(
                ed25519.Point.unpack(buf[0:32]),
                ed25519.Point.unpack(buf[32:64]),
                ed25519.Point.unpack(buf[64:96]))
        
        triple = triple.rsk(k,s,r)
        
        self.assertEqual(triple.blinding, triple2.blinding)
        self.assertEqual(triple.core, triple2.core)
        self.assertEqual(triple.target, triple2.target)
Пример #22
0
    def test_create(self):
        k = ed25519.scalar_random()
        k_powers = [
            ed25519.Point.B_times(pow(k, 2**i, ed25519.l)) for i in range(253)
        ]

        e = 0
        cc = schnorr.CertifiedComponent.create(k, e)
        self.assertTrue(cc.is_valid_proof_for(e, k_powers))

        i = random.choice(range(253))
        e = 2**i
        cc = schnorr.CertifiedComponent.create(k, e)
        self.assertTrue(cc.is_valid_proof_for(e, k_powers))

        e = ed25519.scalar_random()
        cc = schnorr.CertifiedComponent.create(k, e)
        self.assertTrue(cc.is_valid_proof_for(e, k_powers))

        cc_ = copy.deepcopy(cc)
        cc_._component = ed25519.Point.random()
        self.assertFalse(cc_.is_valid_proof_for(e, k_powers))
Пример #23
0
    def test_triple_decrypt(self):
        key = ed25519.scalar_random()

        t = elgamal.encrypt( ed25519.Point.random(), ed25519.Point.B_times(key))

        ckey = scalar_to_c(key)
        ct = triple_to_c(t)
        cresult = point_to_c(ed25519.Point.Zero())
        
        ristretto.lib.elgamal_triple_decrypt(cresult, ct, ckey)

        result = point_from_c(cresult)

        self.assertEqual(result, t.decrypt(key))
Пример #24
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
            )
Пример #25
0
    def test_triple_encrypt(self):
        a = ed25519.Point.random()
        t = ed25519.Point.random()
        r = ed25519.scalar_random()

        ca = point_to_c(a)
        ct = point_to_c(t)
        cr = scalar_to_c(r)

        ctriple = ristretto.ffi.new("elgamal_triple*")
        
        ristretto.lib.elgamal_triple_encrypt(ctriple, ca, ct, cr)

        triple = triple_from_c(ctriple)

        self.assertEqual(triple, elgamal.encrypt(a,t,r))
Пример #26
0
    def test_dht_proof_is_valid(self):
        M = ed25519.Point.random()
        a = ed25519.scalar_random()

        ct = schnorr.DHTProof.create(a, M)

        A = ed25519.Point.B_times(a)
        N = M*a

        cA = point_to_c(A)
        cM = point_to_c(M)
        cN = point_to_c(N)

        A_packed = A.pack()
        M_packed = M.pack()
        N_packed = N.pack()

        ct_packed = ct.pack()

        self.assertTrue(ristretto.lib.dht_proof_is_valid_for(
                ct_packed, cA, cM, cN, A_packed, M_packed, N_packed))

        R = ed25519.Point.random()
        cR = point_to_c(R)
        R_packed = R.pack()

        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                ct_packed, cR, cM, cN, R_packed, M_packed, N_packed))
        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                ct_packed, cA, cR, cN, A_packed, R_packed, N_packed))
        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                ct_packed, cA, cM, cR, A_packed, M_packed, R_packed))

        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                os.urandom(32)+ct_packed[32:], 
                cA, cM, cN, A_packed, M_packed, N_packed))

        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                ct_packed[:32] + os.urandom(32) + ct_packed[64:],
                cA, cM, cN, A_packed, M_packed, N_packed))

        self.assertFalse(ristretto.lib.dht_proof_is_valid_for(
                ct_packed[:64] + os.urandom(32),
                cA, cM, cN, A_packed, M_packed, N_packed))
Пример #27
0
 def test_invalid_decryption(self):
     m = ed25519.Point.random()
     x = ed25519.scalar_random()
     y = ed25519.Point.B() * x
     with self.assertRaises(elgamal.WrongPrivateKey):
         elgamal.encrypt(m,y).decrypt(x+1)
Пример #28
0
 def test_encryption(self):
     m = ed25519.Point.random()
     x = ed25519.scalar_random()
     y = ed25519.Point.B() * x
     self.assertEqual(m, elgamal.encrypt(m, y).decrypt(x))
Пример #29
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
Пример #30
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