Example #1
0
    def get_timestamp_response(self, request: TimestampRequest,
                               callback) -> Signature:
        """
        Send a timestamp response for a given request, check if the fields of TimestampRequest object are valid.
        :param request: The request to answer to
        :type request: TimestampRequest
        :param callback: The function to callback once the TimestampResponse is computed.
            This callback have the following signature: callback(response: TimestampResponse) -> Signature
        :return: The Signature object returned by the callback
        :rtype: Signature
        """
        assert isinstance(request, TimestampRequest)

        self.logger.info("Received timestamp request: %s", str(request))
        t = datetime.utcnow().replace(
            microsecond=0)  # We take the time at the reception of the request
        status_code = self.__client_certificate_is_valid__(request.ID_C, t)
        response = TimestampResponse(request.x, self.ID_S, request.ID_C, t,
                                     status_code)

        if status_code is KSIErrorCodes.NO_ERROR:
            msg, response = self.signer.sign(response)
            assert self.dao.publish_signed_request(msg, response)

        self.logger.info("Responding with St: %s", str(response))

        return callback(response)
Example #2
0
    def sign(self, message: bytes, use_rest_api=False) -> Signature:
        """
        Ask the server to sign the message.
        At the end of this function self.requests will contain an entry at x for self.sign_callback().
        :param message: The message to sign
        :type message: bytes
        :param use_rest_api: Set to True if you want to use the remote REST API, False otherwise (e.g. travis)
        :type use_rest_api: bool
        :return: The signature returned by the self.sign_callback()
        :rtype: Signature
        """
        assert isinstance(message, bytes) and isinstance(use_rest_api, bool)

        current_time = datetime.utcnow().replace(microsecond=0)
        self.logger.debug("Sign request at %s for message: %s",
                          current_time.isoformat(), message)

        # Assert we have a z_i to sign this message
        if not (current_time <
                self.certificate.t_0 + timedelta(seconds=self.keys.l)):
            self.logger.error("Attempt to sign with an outdated certificate!")
            raise ValueError

        # Compute the time difference between now and t_0 of the certificate
        time_delta = current_time - self.certificate.t_0  # type: timedelta
        # time_delta + 1 is meant to correct the index
        time_delta_offset = int(time_delta.total_seconds()) + 1

        if time_delta_offset < 0:
            self.logger.error(
                "Attempt to sign with a certificate beginning in the future!")
            raise ValueError

        # Take the appropriate z_i from the list (exclude the first item being z_0)
        z_i = self.keys.keys[time_delta_offset]  # type: Node
        self.logger.debug("\tz_i used to sign: %s", z_i.hash.hex())

        # x = hash(message || z_i)
        x = hash_factory(data=bytes(message) + z_i.hash)
        self.logger.debug("\tx computed: %s", x.hexdigest())
        # Insert x in self.requests
        self.requests[x.hexdigest()] = (z_i, time_delta_offset, x, message)
        request = TimestampRequest(x.digest(), self.certificate.id_client)

        # Create the request and send it to the server to get S_t
        if use_rest_api:
            assert self.api_user != "" and self.api_password != ""
            r = requests.post(API_HOST_PORT + API_ROUTE_BASE + 'sign',
                              data=request.to_json(),
                              auth=(self.api_user, self.api_password),
                              headers={'Content-Type': 'application/json'})
            response = TimestampResponse.from_json_dict(r.json())
            return self.sign_callback(response)

        else:
            return self.server.get_timestamp_response(
                request, lambda _response: self.sign_callback(_response))
Example #3
0
    def sign(self, message: bytes, use_rest_api=False) -> Signature:
        """
        Ask the server to sign the message.
        At the end of this function self.requests will contain an entry at x for self.sign_callback().
        :param message: The message to sign
        :type message: bytes
        :param use_rest_api: Set to True if you want to use the remote REST API, False otherwise (e.g. travis)
        :type use_rest_api: bool
        :return: The signature returned by the self.sign_callback()
        :rtype: Signature
        """
        assert isinstance(message, bytes) and isinstance(use_rest_api, bool)

        current_time = datetime.utcnow().replace(microsecond=0)
        self.logger.debug("Sign request at %s for message: %s", current_time.isoformat(), message)

        # Assert we have a z_i to sign this message
        if not (current_time < self.certificate.t_0 + timedelta(seconds=self.keys.l)):
            self.logger.error("Attempt to sign with an outdated certificate!")
            raise ValueError

        # Compute the time difference between now and t_0 of the certificate
        time_delta = current_time - self.certificate.t_0  # type: timedelta
        # time_delta + 1 is meant to correct the index
        time_delta_offset = int(time_delta.total_seconds()) + 1

        if time_delta_offset < 0:
            self.logger.error("Attempt to sign with a certificate beginning in the future!")
            raise ValueError

        # Take the appropriate z_i from the list (exclude the first item being z_0)
        z_i = self.keys.keys[time_delta_offset]  # type: Node
        self.logger.debug("\tz_i used to sign: %s", z_i.hash.hex())

        # x = hash(message || z_i)
        x = hash_factory(data=bytes(message) + z_i.hash)
        self.logger.debug("\tx computed: %s", x.hexdigest())
        # Insert x in self.requests
        self.requests[x.hexdigest()] = (z_i, time_delta_offset, x, message)
        request = TimestampRequest(x.digest(), self.certificate.id_client)

        # Create the request and send it to the server to get S_t
        if use_rest_api:
            assert self.api_user != "" and self.api_password != ""
            r = requests.post(
                API_HOST_PORT + API_ROUTE_BASE + "sign",
                data=request.to_json(),
                auth=(self.api_user, self.api_password),
                headers={"Content-Type": "application/json"},
            )
            response = TimestampResponse.from_json_dict(r.json())
            return self.sign_callback(response)

        else:
            return self.server.get_timestamp_response(request, lambda _response: self.sign_callback(_response))
Example #4
0
    def sign(self, sig: TimestampResponse, base64_encode: bool=True) -> (bytes, TimestampResponse):
        """
        Fill the field sig.signature by signing the message.
        This is a proxy method for self._sign().
        :param sig: The TimestampResponse object to fill
        :type sig: TimestampResponse
        :param base64_encode: True to encode the signature in base64 (standard)
        :type base64_encode: bool
        :return: (message, filled TimestampResponse)
        """
        assert isinstance(sig, TimestampResponse)

        msg = self.msg(sig)
        sig.signature = self._sign(msg, base64_encode)

        return msg, sig
Example #5
0
    def from_json(json_obj: dict):
        """
        :param json_obj: A JSON representation of the Signature object
        :type json_obj: dict
        :return: A new Signature built from the json_obj parameter
        :rtype: Signature
        """
        assert 'ID_C' in json_obj
        assert 'i' in json_obj
        assert 'z_i' in json_obj
        assert 'c_i' in json_obj
        assert 'msg' in json_obj
        assert 'S_t' in json_obj

        ID_C = Identifier(json_obj['ID_C'][len(IDENTIFIER_BASE_NAME):])
        i = json_obj['i']
        z_i = standard_b64decode(json_obj['z_i'])
        c_i = pickle.loads(standard_b64decode(json_obj['c_i']))
        msg = standard_b64decode(json_obj['msg'])
        S_t = TimestampResponse.from_json_dict(json_obj['S_t'])

        return Signature(ID_C, i, z_i, c_i, S_t, msg)
Example #6
0
LOGGER_DEFAULT_OUTFILE = LOGGER_DIR + LOGGER_NAME + '.log'
LOGGER_SAVE_OUTFILE = LOGGER_DIR + 'benchmark-{}-{}-{}.log'

if __name__ == '__main__':
    assert PERFORM_BENCHMARKS is True  # This switch need to be enabled!
    assert BENCHMARK_MOTIF == "ksi.signverify"

    add_logger()
    logging.basicConfig(level=logging.INFO)
    hash = hash_factory(data=b'ABCD')

    for i in [1024, 2048, 4096]:
        open(LOGGER_DEFAULT_OUTFILE, 'w+').close()
        signer = SignVerify()
        signer.generate_keys(i)
        resp = TimestampResponse(hash, Identifier('server'), Identifier('client'), datetime.utcnow(),
                                 KSIErrorCodes.NO_ERROR)
        # Benchmark start
        m, sig = signer.sign(resp)
        assert signer.verify(m, sig) is True
        # Benchmark end

        logger = logging.getLogger(LOGGER_NAME)

        for h in logger.handlers:
            h.flush()
            logger.removeHandler(h)

        os.rename(LOGGER_DEFAULT_OUTFILE, LOGGER_SAVE_OUTFILE.format('Sign', '', 'key-len_' + str(i)))