def generate_vault(xyt_input_path, minutiae_points_amount, chaff_points_amount, poly_degree, secret, crc_length, gf_exp, log_dict, echo=False): # extract minutiae from template nbis_minutiae_extractor = MinutiaeExtractor() minutiae_list = nbis_minutiae_extractor.extract_minutiae_from_xyt(xyt_input_path) if len(minutiae_list) < minutiae_points_amount: if echo: print('Not enough minutiae in template to proceed for generation of vault...') log_dict['too_few_minutiae_gallery'] = True return None vault = Vault() m2b = MinutiaConverter() # Cut low quality minutiae and convert all minutiae to uint and add to vault genuine_minutiae_list = [] for candidate in minutiae_list: if len(genuine_minutiae_list) == minutiae_points_amount: break too_close = False for minutia in genuine_minutiae_list: if candidate.distance_to(minutia) <= POINTS_DISTANCE: too_close = True break if not too_close: genuine_minutiae_list.append(candidate) for minutia in genuine_minutiae_list: vault.add_minutia_rep(m2b.get_uint_from_minutia(minutia)) # create chaff points and add to vault chaff_points_list = ChaffPointsGenerator.generate_chaff_points_randomly(chaff_points_amount, genuine_minutiae_list, vault.get_smallest_original_minutia(), m2b) for chaff_point in chaff_points_list: vault.add_chaff_point_rep(m2b.get_uint_from_minutia(chaff_point)) # generate secret polynomial secret_poly_generator = PolynomialGenerator(secret, poly_degree, crc_length, gf_exp) if echo: print('Coefficients of secret polynomial: {}'.format(secret_poly_generator.coefficients)) # evaluate polynomial at all vault minutiae points (not at chaff points) vault.evaluate_polynomial_on_minutiae(secret_poly_generator, echo=echo) # generate random evaluation for chaff points vault.evaluate_random_on_chaff_points(secret_poly_generator, gf_exp) # finalize vault (delete information on vault creation except vault_final_elements_pairs) vault.finalize_vault() return vault
def unlock_vault_geom(vault: Vault, probe_minutiae, poly_degree, gf_exp, crc_length, secret_length, log_dict, echo=False): """ Given vault, find candidate minutiae according to probe minutiae (list of Minutia) using geometric hashing. Afterwards, run interpolation on candidate minutiae geom_table needs to exist in vault :returns True if match found in polynomial after interpolation, else False """ def exit_false(): """ :returns False for vault not unlocked """ log_dict['amount_geom_table'] = len(vault_geom_table) log_dict['evaluated_subsets'] = -1 log_dict['minutiae_candidates'] = 0 log_dict['time_geom'] = time.time() - t_geom log_dict['geom_gallery_basis'] = None log_dict['geom_probe_basis'] = None vault.vault_original_minutiae_rep.clear() vault.vault_function_points_rep.clear() vault.vault_chaff_points_rep.clear() return False def get_geom_table_basis_threshold(probe_minutiae_gh): """ Removes basis in geom_table of vault that correspond to no probe_minutiae orientation :param probe_minutiae_gh: list of probe minutiae as MinutiaNBIS_GH :return: changes vault.geom_table, no return value """ geom_table = vault.geom_table.copy() for element_enroll in geom_table.copy(): in_threshold = False for m in probe_minutiae_gh: if abs(element_enroll.basis.theta - m.theta) <= Constants.BASIS_THETA_THRESHOLD: # not removing element from geom_table in_threshold = True break # remove element from geom_table if there was no match if not in_threshold: geom_table.remove(element_enroll) return geom_table assert vault.geom_table log_dict['thresholds'] = '({}/[{}/{}/{}/{}]/{})'.format( Constants.POINTS_DISTANCE, Constants.X_THRESHOLD, Constants.Y_THRESHOLD, Constants.THETA_THRESHOLD, Constants.TOTAL_THRESHOLD, Constants.BASIS_THETA_THRESHOLD) # start time geometric hashing t_geom = time.time() # create polynomial extractor poly_extractor = PolynomialExtractor(gf_exp) # convert probe minutia to GH form, iterate through probe_minutiae, taking random probe minutia as basis probe_minutiae_GH = GHTransformer.convert_list_to_MinutiaNBIS_GH(probe_minutiae) random.shuffle(probe_minutiae_GH) # remove all basis in geom_table that are not within threshold of probe_minutiae orientation vault_geom_table = get_geom_table_basis_threshold(probe_minutiae_GH) for cnt_basis, basis in enumerate(probe_minutiae_GH): # take random basis and try matching element_verification = GHTransformer.generate_verification_table_element(basis, probe_minutiae_GH.copy()) for cnt_enroll, element_enrollment in enumerate(vault_geom_table): # check if basis in element_enrollment has similar orientation to current basis in probe if not (abs(element_verification.basis.theta - element_enrollment.basis.theta) <= Constants.BASIS_THETA_THRESHOLD): continue # clear lists in vault to be populated in decoding for each element in geom_table vault.vault_original_minutiae_rep.clear() vault.vault_function_points_rep.clear() vault.vault_chaff_points_rep.clear() assert len(element_enrollment.transformed_minutiae_list) == len(vault.vault_final_elements_pairs) # cnt_m_enr is representing the same indices also in vault_final_element_pairs match = 0 candidates_verification = [] candidates_enrollment = [] candidate_minutiae_verification = element_verification.transformed_minutiae_list.copy() for cnt_m_enr, minutia_enrollment in enumerate(element_enrollment.transformed_minutiae_list): if not candidate_minutiae_verification: break for minutia_verification in candidate_minutiae_verification: if fuzzy_compare(minutia_enrollment, minutia_verification): log_dict['geom_single_match'] += 1 # Only add element if not already in list if not vault.vault_final_elements_pairs[ cnt_m_enr].x_rep in vault.vault_original_minutiae_rep: match += 1 # add representation (uint) to candidate minutiae # first element corresponding to x value of vault tuple vault.add_minutia_rep(vault.vault_final_elements_pairs[cnt_m_enr].x_rep) # second element corresponding to y value of vault tuple vault.add_function_point_rep(vault.vault_final_elements_pairs[cnt_m_enr].y_rep) # candidate minutiae for logging purposes candidates_verification.append(minutia_verification) candidates_enrollment.append(minutia_enrollment) assert match == len(vault.vault_original_minutiae_rep) else: # add to chaff points (but not relevant as minutia can not be matched in different basis) chaff_candidate = vault.vault_final_elements_pairs[cnt_m_enr].x_rep if chaff_candidate not in vault.vault_chaff_points_rep: vault.add_chaff_point_rep(chaff_candidate) log_dict['geom_iteration'] += 1 if match >= Constants.MATCH_THRESHOLD: assert match == len(vault.vault_original_minutiae_rep) assert len(candidates_verification) == len(candidates_enrollment) assert len(vault.vault_original_minutiae_rep) == len(vault.vault_function_points_rep) assert len(vault.vault_function_points_rep) == len(candidates_enrollment) # log iterations in geometric hashing, minutiae candidates. tries to interpolate and basis log_dict['amount_geom_table'] += cnt_enroll log_dict['minutiae_candidates'] = len(vault.vault_original_minutiae_rep) log_dict['geom_match_tries'] += 1 log_dict['geom_gallery_basis'] = element_enrollment.basis log_dict['geom_probe_basis'] = element_verification.basis # time geometric hashing log_dict['time_geom'] = time.time() - t_geom # polynomial interpolation on candidate set function points and test CRC in extracted polynomials t_interpol = time.time() success = poly_extractor.interpolate_and_check_crc(vault, poly_degree, crc_length, secret_length, log_dict, echo=echo) log_dict['time_interpolation'] += time.time() - t_interpol if success: # log candidate minutiae if Constants.LOG_CANDIDATE_MINUTIAE: log_candidates_minutia(Constants.LOG_CANDIDATES_PATH_PREFIX, Constants.LOG_CANDIDATES_PATH_SUFFIX, candidates_verification, candidates_enrollment, element_verification.basis, element_enrollment.basis, vault, number=log_dict['exp_number']) return True # break if max threshold is reached if log_dict['geom_iteration'] > Constants.MAX_ITERATION_THRESHOLD: print("Max iteration threshold reached!") return exit_false() # unfortunately, no sets found return exit_false()