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