예제 #1
0
    def _verify_derivation(signature: Signature, z_0: bytes) -> bool:
        """
        Verify that by using zi and computing the hash recursively we reach z_0.
        :param signature: Signature to be verified
        :type signature: Signature
        :param z_0: The z_0 element of the certificate
        :type z_0: bytes
        :return: True if the correct z_0 is reached by derivation
        :rtype: bool
        """
        assert isinstance(z_0, bytes) and isinstance(signature, Signature)

        z_hash = hash_factory(data=signature.z_i).digest()

        for i in range(0, signature.i):
            z_hash = hash_factory(data=z_hash).digest()

        return z_0 == z_hash
예제 #2
0
    def test_5_sign(self):
        global signed_resp, signed_msg
        TestSignVerify.signverify.import_private_keys(filename_private_key)

        x = hash_factory(data=b'ABCD')
        t_resp = TimestampResponse(x, Identifier("server"), Identifier("client"), datetime.utcnow(),
                                   KSIErrorCodes.NO_ERROR)

        signed_msg, signed_resp = TestSignVerify.signverify.sign(t_resp)
예제 #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))
예제 #4
0
    def _verify_derivation(signature: Signature, z_0: bytes) -> bool:
        """
        Verify that by using zi and computing the hash recursively we reach z_0.
        :param signature: Signature to be verified
        :type signature: Signature
        :param z_0: The z_0 element of the certificate
        :type z_0: bytes
        :return: True if the correct z_0 is reached by derivation
        :rtype: bool
        """
        assert isinstance(z_0, bytes) and isinstance(signature, Signature)

        z_hash = hash_factory(data=signature.z_i).digest()

        for i in range(0, signature.i):
            z_hash = hash_factory(data=z_hash).digest()

        return z_0 == z_hash
예제 #5
0
    def test_5_sign(self):
        global signed_resp, signed_msg
        TestSignVerify.signverify.import_private_keys(filename_private_key)

        x = hash_factory(data=b'ABCD')
        t_resp = TimestampResponse(x,
                                   Identifier("server"), Identifier("client"),
                                   datetime.utcnow(), KSIErrorCodes.NO_ERROR)

        signed_msg, signed_resp = TestSignVerify.signverify.sign(t_resp)
예제 #6
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))
예제 #7
0
    def test_all(self):
        dao_factory = factory(DAOMongoFactory)
        server = KSIServer(Identifier('server'), dao_factory.get_server())
        keys = Keys(l=256, seed=b'SEED')
        client = KSIClient(server, dao_factory.get_client(), keys=keys)
        ref_cert = client.certificate

        mongo_cert = server.dao.get_user_certificate(client.certificate.id_client)
        self.assertTrue(ref_cert == mongo_cert)

        ref_msg = hash_factory(data=b'DATA').digest()
        sig = client.sign(ref_msg)
        client.verify(sig, client.certificate, ref_msg)
예제 #8
0
    def test_all(self):
        dao_factory = factory(DAOMongoFactory)
        server = KSIServer(Identifier('server'), dao_factory.get_server())
        keys = Keys(l=256, seed=b'SEED')
        client = KSIClient(server, dao_factory.get_client(), keys=keys)
        ref_cert = client.certificate

        mongo_cert = server.dao.get_user_certificate(
            client.certificate.id_client)
        self.assertTrue(ref_cert == mongo_cert)

        ref_msg = hash_factory(data=b'DATA').digest()
        sig = client.sign(ref_msg)
        client.verify(sig, client.certificate, ref_msg)
예제 #9
0
#

MAX_L_POW = 20
LOGGER_DEFAULT_OUTFILE = LOGGER_DIR + LOGGER_NAME + '.log'
LOGGER_SAVE_OUTFILE = LOGGER_DIR + 'benchmark-{}-{}-{}.log'
KEY_SHELVE_INPUT_FILE = LOGGER_SAVE_OUTFILE[:-4] + '.shelve'

if __name__ == '__main__':
    add_logger()
    logging.basicConfig(level=logging.INFO)
    assert PERFORM_BENCHMARKS is True  # This switch need to be enabled!
    assert BENCHMARK_MOTIF == "ksi.ksi_client"

    l_nums = list(map(lambda i: 2**i, [i for i in range(2, MAX_L_POW + 1)]))
    _max_l = 2**MAX_L_POW
    msg_to_sign = hash_factory(data=b'ABCDEFGHIJKLMNOPQRSTUVWXYZ').digest()

    # We don't generate a private/public key pair here:
    # ln -s /home/user/ksi_git/tests/output/private.pem /tmp/private.pem
    # ln -s /home/user/ksi_git/tests/output/public.pem /tmp/public.pem

    for l in l_nums:
        keys = None

        # Importing saved keys from Keys benchmark
        with shelve.open(KEY_SHELVE_INPUT_FILE.format("Keys", HASH_ALGO,
                                                      "l_" + str(l)),
                         flag='r') as save:
            keys = save['keys']  # type: Keys

        assert keys is not None
예제 #10
0
MAX_L_POW = 20
LOGGER_DEFAULT_OUTFILE = LOGGER_DIR + LOGGER_NAME + '.log'
LOGGER_SAVE_OUTFILE = LOGGER_DIR + 'benchmark-{}-{}-{}.log'
KEY_SHELVE_INPUT_FILE = LOGGER_SAVE_OUTFILE[:-4] + '.shelve'


if __name__ == '__main__':
    add_logger()
    logging.basicConfig(level=logging.INFO)
    assert PERFORM_BENCHMARKS is True  # This switch need to be enabled!
    assert BENCHMARK_MOTIF == "ksi.ksi_client"

    l_nums = list(map(lambda i: 2 ** i, [i for i in range(2, MAX_L_POW+1)]))
    _max_l = 2 ** MAX_L_POW
    msg_to_sign = hash_factory(data=b'ABCDEFGHIJKLMNOPQRSTUVWXYZ').digest()

    # We don't generate a private/public key pair here:
    # ln -s /home/user/ksi_git/tests/output/private.pem /tmp/private.pem
    # ln -s /home/user/ksi_git/tests/output/public.pem /tmp/public.pem

    for l in l_nums:
        keys = None

        # Importing saved keys from Keys benchmark
        with shelve.open(KEY_SHELVE_INPUT_FILE.format("Keys", HASH_ALGO, "l_" + str(l)), flag='r') as save:
            keys = save['keys']  # type: Keys

        assert keys is not None

        open(LOGGER_DEFAULT_OUTFILE, 'w+').close()
예제 #11
0
from ksi import PERFORM_BENCHMARKS, BENCHMARK_MOTIF

#
# Observe the time spent signing (signverify.sign()) for different key sizes.
#

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:
예제 #12
0
def hash_salt(s: str) -> bytes:
    return hash_factory(data=bytes(s, encoding='ascii') + SALT).digest()