Esempio n. 1
0
    def check_request_signature(self, server_pk, message, revealed_attributes,
                                signature):
        """

        Args:
            server_pk (byte[]): the server's public key (serialized)
            message (byte[]): The message to sign
            revealed_attributes (string): revealed attributes
            signature (bytes[]): user's autorization (serialized)

            Note: You can use JSON to encode revealed_attributes in the string.

        Returns:
            valid (boolean): is signature valid
        """
        signature = jsonpickle.decode(signature)
        pk = jsonpickle.decode(server_pk)

        #Sanitization in case revealed_info is empty
        public_attrs = revealed_attributes.split(',')
        while '' in public_attrs:
            public_attrs.remove('')

        #Check if attributes revealed are valid
        for attr in public_attrs:
            if attr not in pk[1]:
                raise RuntimeError("Revealed attributes are not valid")

        return signature.verify(pk[0], public_attrs, message)
Esempio n. 2
0
    def register(self, server_sk, issuance_request, username, attributes):
        """ Registers a new account on the server.

        Args:
            server_sk (byte []): the server's secret key (serialized)
            issuance_request (bytes[]): The issuance request (serialized)
            username (string): username
            attributes (string): attributes

            Note: You can use JSON to encode attributes in the string.

        Return:
            response (bytes[]): the client should be able to build a credential
            with this response.
        """
        sk = jsonpickle.decode(server_sk)
        attributes = attributes.split(',')

        #Check if attributes chosen are valid
        for attr in attributes:
            if attr not in sk[2]:
                raise RuntimeError("Revealed attributes are not valid")

        response = Issuer.issue(sk, jsonpickle.decode(issuance_request),
                                username, attributes)
        return jsonpickle.encode(response).encode()
Esempio n. 3
0
    def register(self, server_sk, issuance_request, username, attributes):
        """ Registers a new account on the server.

        Args:
            server_sk (byte []): the server's secret key (serialized)
            issuance_request (bytes[]): The issuance request (serialized)
            username (string): username
            attributes (string): attributes

            Note: You can use JSON to encode attributes in the string.

        Return:
            response (bytes[]): the client should be able to build a credential
            with this response.
        """

        #Reconstructing the secret key
        sk = jsonpickle.decode(server_sk)
        #Decoding the request
        decoded_request = jsonpickle.decode(issuance_request)
        C = decoded_request["C"]

        #Verifying the value for C
        s_sk = decoded_request["s_sk"]
        s_t = decoded_request["s_t"]
        R = decoded_request["R"]
        c = int.from_bytes(
            sha256((username + attributes).encode()).digest(),
            "big") % G1.order()  # hashing

        if (sk["Ys_G1"][0]**s_sk) * (G1.generator()**s_t) * C**c != R:
            raise Exception("Invalid register !")

        #Generating a random u
        u = G1.order().random()
        g_pow_u = G1.generator()**u
        X = sk[
            "X_G1"]  #Note : I decided to have X in the secret key, rather than recompute it everytime

        #Building the Ys
        Ys = sk["Ys_G1"]

        sigma_2 = X * C
        #The subscription attributes
        for att in attributes.split(","):
            if att not in sk["validAttributes"]:
                raise ValueError("Non-recognized attribute")
            else:
                index_of_att = sk["validAttributes"].index(att)
                y_i = Ys[index_of_att + 1]  #+1 because of the hidden attribute
                sigma_2 = sigma_2 * y_i
        json_res = {"sigma1": g_pow_u, "sigma2": sigma_2**u}
        return jsonpickle.encode(json_res).encode()
Esempio n. 4
0
    def check_request_signature(self, server_pk, message, revealed_attributes,
                                signature):
        """

        Args:
            server_pk (byte[]): the server's public key (serialized)
            message (byte[]): The message to sign
            revealed_attributes (string): revealed attributes
            signature (bytes[]): user's autorization (serialized)

            Note: You can use JSON to encode revealed_attributes in the string.

        Returns:
            valid (boolean): is signature valid
        """
        sig = jsonpickle.decode(signature)
        att = revealed_attributes.split(",")
        pk = jsonpickle.decode(server_pk)
        valid_attributes = pk["validAttributes"]

        R = sig["R"]
        c = sig["c"]
        s_is = sig["s_is"]
        sigma1 = sig["sigma"][0]
        sigma2 = sig["sigma"][1]
        if sigma1 == G1.generator()**G1.order():  #Checking that sigma1 != 1
            return False

        # Verifying the hash was legit
        c_us = int.from_bytes(sha256(message).digest(), "big") % G1.order()
        if (c_us != c):
            return False

        # Need to recreate the value the proof of knowledge is showing
        acc = sigma2.pair(G2.generator()) / sigma1.pair(pk["X"])
        for i in range(len(att)):
            acc = acc / (sigma1).pair(
                pk["Ys"][valid_attributes.index(att[i]) + 1])

        values_to_prove = [
        ]  # Storing the values used in the proof of knowledge
        values_to_prove.append((sigma1).pair(G2.generator()))
        values_to_prove.append(sigma1.pair(pk["Ys"][0]))
        for att in valid_attributes:
            if att not in revealed_attributes.split(","):
                values_to_prove.append(
                    sigma1.pair(pk["Ys"][valid_attributes.index(att) + 1]))
        thing_to_add_to_r = acc**c_us
        for v, exp in zip(values_to_prove, s_is):
            thing_to_add_to_r = thing_to_add_to_r * (v**exp)
        return R == thing_to_add_to_r
Esempio n. 5
0
def test_tampered_credential():
    '''
    Test if a user can have a response to a request if the credential is wrong
    '''

    attributes = "a,b,c,d,e"
    chosen_attr = "d,e"
    revealed_attr = "e"
    username = "******"
    message = "46.5 6.6".encode()

    pk, sk = Server.generate_ca(attributes)

    #Registration process
    issue_request, private_state = Client().prepare_registration(pk, username, chosen_attr)
    response = Server().register(sk, issue_request, username, chosen_attr)
    credential = Client().proceed_registration_response(pk, response, private_state)

    #Tampering the credential
    credential = jsonpickle.decode(credential)
    credential.credential = (credential.credential[0] ** 2, credential.credential[1])
    credential = jsonpickle.encode(credential).encode()

    #Request a service
    signature = Client().sign_request(pk, credential, message, revealed_attr)
    
    assert(not Server().check_request_signature(pk, message, revealed_attr, signature))
Esempio n. 6
0
    def sign_request(self, server_pk, credential, message, revealed_info):
        """Signs the request with the clients credential.

        Arg:
            server_pk (byte[]): a server's public key (serialized)
            credential (byte[]): client's credential (serialized)
            message (byte[]): message to sign
            revealed_info (string): attributes which need to be authorized

            Note: You can use JSON to encode revealed_info.

        Returns:
            byte []: message's signature (serialized)
        """
        revealed_attr = revealed_info.split(',')
        credential = jsonpickle.decode(credential)

        #Sanitization in case revealed_info is empty
        while '' in revealed_attr:
            revealed_attr.remove('')

        #Check if attributes revealed are valid
        for attr in revealed_attr:
            if attr not in credential.attributes:
                raise RuntimeError(
                    "Revealed attributes are not in the credential")

        signature = credential.sign(message, revealed_attr)

        return signature.serialize()
Esempio n. 7
0
    def proceed_registration_response(self, server_pk, server_response,
                                      private_state):
        """Process the response from the server.

        Args:
            server_pk (byte[]): a server's public key (serialized)
            server_response (byte[]): the response from the server (serialized)
            private_state (private_state): state from the prepare_registration
            request corresponding to this response

        Return:
            credential (byte []): create an attribute-based credential for the user
        """
        credential = AnonCredential.receive_issue_response(
            jsonpickle.decode(server_pk)[0],
            jsonpickle.decode(server_response), private_state)
        return jsonpickle.encode(credential).encode()
Esempio n. 8
0
def test_generate_ca():
    '''
    General test for key parameters
    '''
    attributes = "a,b,c,d,e"
    nb_attributes = len(attributes.split(','))

    pk, sk = Server.generate_ca(attributes)
    sk = jsonpickle.decode(sk)
    pk = jsonpickle.decode(pk)

    #key length check
    assert(len(pk[0]) == nb_attributes * 2 + 3)
    assert(len(pk[1]) == nb_attributes)
    assert(len(sk) == 3)
    assert(isinstance(sk[0], petrelic.multiplicative.pairing.G1Element))
    assert(len(sk[1]) == len(pk[0]))
    assert(len(sk[2]) == nb_attributes)
Esempio n. 9
0
    def deserialize(data):
        """Deserializes the object from a byte array.

        Args: 
            data (byte[]): a byte array 

        Returns:
            Signature
        """
        return jsonpickle.decode(data)
Esempio n. 10
0
    def prepare_registration(self, server_pk, username, attributes):
        """Prepare a request to register a new account on the server.

        Args:
            server_pk (byte[]): a server's public key (serialized)
            username (string): username
            attributes (string): user's attributes

            Note: You can use JSON to encode attributes in the string.

        Return:
            tuple:
                byte[]: an issuance request
                (private_state): You can use state to store and transfer information
                from prepare_registration to proceed_registration_response.
                You need to design the state yourself.
        """

        t = G1.order().random()
        pk = jsonpickle.decode(server_pk)
        Ys_in_G1 = pk["Ys_G1"]

        random_sk = G1.order().random()  # Some secret key as asked
        C = (G1.generator()**t) * (Ys_in_G1[0]**random_sk)
        for att in attributes.split(","):
            if att not in pk["validAttributes"]:
                raise ValueError(
                    "Attribute not in list of accepted attribute by the server"
                )

        issuance_request = {}
        issuance_request["C"] = C
        r_sk = G1.order().random()
        r_t = G1.order().random()
        c = int.from_bytes(
            sha256((username + attributes).encode()).digest(),
            "big") % G1.order()  # hashing

        s_sk = ((r_sk - random_sk * c) + G1.order()) % G1.order()
        s_t = ((r_t - t * c) + G1.order()) % G1.order()

        R = (Ys_in_G1[0]**r_sk) * (G1.generator()**r_t)
        if (Ys_in_G1[0]**s_sk) * (G1.generator()**s_t) * C**c != R:
            raise Exception("Invalid signature !")

        issuance_request["s_t"] = s_t
        issuance_request["s_sk"] = s_sk
        issuance_request["R"] = R

        return jsonpickle.encode(issuance_request).encode(), (
            random_sk, t
        )  #t is the inner state, we only need to remember that (since the key as secret attribute is completely useless)
Esempio n. 11
0
    def proceed_registration_response(self, server_pk, server_response,
                                      private_state):
        """Process the response from the server.

        Args:
            server_pk (byte[]): a server's public key (serialized)
            server_response (byte[]): the response from the server (serialized)
            private_state (private_state): state from the prepare_registration
            request corresponding to this response

        Return:
            credential (byte []): create an attribute-based credential for the user
        """

        sigma = jsonpickle.decode(server_response)
        (random_sk, t) = private_state
        sigma_bis = (sigma["sigma1"], sigma["sigma2"] / (sigma["sigma1"]**t))

        #Verifying the received signature
        pk = jsonpickle.decode(server_pk)
        Y_s = pk["Ys"]
        acc = G2.neutral_element()
        for (i, y_i) in zip(range(len(Y_s)), Y_s):
            if i == 0:
                acc = acc * (y_i**random_sk)
            else:
                acc = acc * y_i
        #Checking that the signature is valid
        if not (sigma_bis[0].pair(acc * pk["X"]) == sigma_bis[1].pair(
                G2.generator())):
            raise Exception("Invalid signature !")

        return jsonpickle.encode({
            "sigma": (sigma_bis[0], sigma_bis[1]),
            "random_sk": random_sk
        }).encode()
Esempio n. 12
0
    def prepare_registration(self, server_pk, username, attributes):
        """Prepare a request to register a new account on the server.

        Args:
            server_pk (byte[]): a server's public key (serialized)
            username (string): username
            attributes (string): user's attributes

            Note: You can use JSON to encode attributes in the string.

        Return:
            tuple:
                byte[]: an issuance request
                (private_state): You can use state to store and transfer information
                from prepare_registration to proceed_registration_response.
                You need to design the state yourself.
        """
        pk = jsonpickle.decode(server_pk)
        attributes = attributes.split(',')
        request, t = AnonCredential.create_issue_request(pk[0], attributes)

        return request.serialize(), (t, attributes)
Esempio n. 13
0
 def deserialize(data):
     return jsonpickle.decode(data)
Esempio n. 14
0
    def sign_request(self, server_pk, credential, message, revealed_info):
        """Signs the request with the clients credential.

        Arg:
            server_pk (byte[]): a server's public key (serialized)
            credential (byte[]): client's credential (serialized)
            message (byte[]): message to sign
            revealed_info (string): attributes which need to be authorized

            Note: You can use JSON to encode revealed_info.

        Returns:
            byte []: message's signature (serialized)
        """
        # Generating r,t
        r = G1.order().random()
        t = G1.order().random()

        #Decoding the public key
        pk = jsonpickle.decode(server_pk)
        valid_attributes = pk["validAttributes"]

        decoded_credential = jsonpickle.decode(credential)
        sigma = decoded_credential["sigma"]
        random_sk = decoded_credential["random_sk"]

        sigma_bis = (sigma[0]**r, ((sigma[0]**t) * sigma[1])**r)

        values_to_prove = [
        ]  # Storing the values used in the proof of knowledge

        com = (sigma_bis[0]).pair(G2.generator())**t
        values_to_prove.append((sigma_bis[0]).pair(G2.generator()))
        # The secret part of the multiplication
        com = com * sigma_bis[0].pair(pk["Ys"][0]**random_sk)
        values_to_prove.append(sigma_bis[0].pair(pk["Ys"][0]))
        # Attributes
        for att in valid_attributes:
            if att not in revealed_info.split(","):
                #raise ValueError("Attribute not in the possible ones !")
                com = com * sigma_bis[0].pair(
                    pk["Ys"][valid_attributes.index(att) + 1])
                values_to_prove.append(sigma_bis[0].pair(
                    pk["Ys"][valid_attributes.index(att) + 1]))
        c = int.from_bytes(sha256(message).digest(),
                           "big") % G1.order()  # hashing

        #Adding the signature
        r_is = []
        R = GT.generator()**GT.order()  # The neutral element of the group
        for value in values_to_prove:
            r_i = G1.order().random()
            r_is.append(r_i)
            R = R * (value**r_i)  # creating the R part of the protocol

        s_is = []
        for (i, r_i) in zip(range(len(r_is)), r_is):
            tmp = r_i - c % G1.order()
            if i == 0:
                tmp = (r_i - c * t) % G1.order()
            if i == 1:
                tmp = (r_i - c * random_sk) % G1.order()

            if tmp < 0:
                tmp += G1.order()
            s_is.append(tmp)

        proof = {"c": c, "R": R, "s_is": s_is, "sigma": sigma_bis}
        return jsonpickle.encode(proof).encode()