mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-06 21:34:05 -05:00
126 lines
4.5 KiB
Python
Executable File
126 lines
4.5 KiB
Python
Executable File
"""
|
|
lattice_estimator
|
|
-----------------
|
|
|
|
Test cryptographic parameters set against several attacks to estimate their security level.
|
|
"""
|
|
|
|
import pathlib
|
|
import sys
|
|
|
|
sys.path.insert(1, "lattice-estimator")
|
|
from estimator import *
|
|
|
|
|
|
model = RC.MATZOV
|
|
|
|
# Minimum level of security thresholds for parameters set in bits
|
|
SECURITY_LEVEL_THRESHOLD_SOFT = 132
|
|
SECURITY_LEVEL_THRESHOLD_HARD = 128
|
|
|
|
|
|
def check_security(filepath):
|
|
"""
|
|
Run lattice estimator to determine if a parameters set is secure or not.
|
|
|
|
:param filepath: path of the file containing parameters set
|
|
|
|
:return: :class:`list` of parameters to update
|
|
"""
|
|
print(f"Parsing parameters in {filepath}")
|
|
load(filepath)
|
|
|
|
to_update = []
|
|
to_watch = []
|
|
|
|
for group_index, param in enumerate(all_params):
|
|
if "TFHE_LIB_PARAMETERS_lwe" in param.tag or "TFHE_LIB_PARAMETERS_glwe" in param.tag:
|
|
# This third-party parameters set is known to be less secure, just skip the analysis.
|
|
continue
|
|
|
|
print(f"\tParameters group #{group_index}:")
|
|
for param_name in sorted(param.tag):
|
|
print(
|
|
f"\t\t{param_name}\t",
|
|
)
|
|
print(f"\tParameters group #{group_index}...\t", end="")
|
|
|
|
is_n_size_too_low = param.n <= 450
|
|
is_noise_level_too_low = param.Xe.stddev < 4.0
|
|
if is_n_size_too_low:
|
|
reason = f"n size is too low {param.n} minimum is 450"
|
|
elif is_noise_level_too_low:
|
|
reason = f"noise level is too low {round(param.Xe.stddev,3)} minimum is 4.0"
|
|
|
|
if is_n_size_too_low or is_noise_level_too_low:
|
|
print(f"FAIL\t{reason}")
|
|
to_update.append((param, reason))
|
|
continue
|
|
|
|
try:
|
|
# The lattice estimator is not able to manage such large dimension.
|
|
# If we have the security for smaller `n` then we have security for larger ones.
|
|
if param.n > 16384:
|
|
param = param.updated(n=16384)
|
|
|
|
usvp_level = LWE.primal_usvp(param, red_cost_model=model)
|
|
dual_level = LWE.dual_hybrid(param, red_cost_model=model)
|
|
|
|
estimator_level = log(min(usvp_level["rop"], dual_level["rop"]), 2).n()
|
|
security_level = f"security level = {estimator_level} bits"
|
|
if estimator_level < SECURITY_LEVEL_THRESHOLD_HARD:
|
|
print(f"FAIL\t({security_level})")
|
|
reason = f"attained {security_level} target is {SECURITY_LEVEL_THRESHOLD_HARD} bits"
|
|
to_update.append((param, reason))
|
|
continue
|
|
elif estimator_level < SECURITY_LEVEL_THRESHOLD_SOFT:
|
|
print(f"WARNING\t({security_level})")
|
|
reason = f"attained {security_level} target is {SECURITY_LEVEL_THRESHOLD_SOFT} bits"
|
|
to_watch.append((param, reason))
|
|
continue
|
|
except Exception as err:
|
|
print("FAIL")
|
|
to_update.append((param, f"{repr(err)}"))
|
|
else:
|
|
print(f"OK\t({security_level})")
|
|
|
|
return to_update, to_watch
|
|
|
|
|
|
if __name__ == "__main__":
|
|
params_to_update = []
|
|
params_to_watch = []
|
|
|
|
this_file = pathlib.Path(__file__).resolve()
|
|
this_file_sage_source = this_file if this_file.suffix == ".sage" else this_file.with_suffix("")
|
|
parent_dir = this_file.parent
|
|
parameter_files = sorted(list(parent_dir.glob("*.sage")))
|
|
parameter_files.remove(this_file_sage_source)
|
|
|
|
for params_file in parameter_files:
|
|
to_update, to_watch = check_security(params_file)
|
|
params_to_update.extend(to_update)
|
|
params_to_watch.extend(to_watch)
|
|
|
|
if params_to_watch:
|
|
print("Some parameters need attention")
|
|
print("------------------------------")
|
|
for param, reason in params_to_watch:
|
|
params = ",\n\t".join(param.tag)
|
|
print("[\n\t", params, "\n]", sep="")
|
|
print(f"--> reason: {reason} (param: {param})\n")
|
|
|
|
if params_to_update:
|
|
if params_to_watch:
|
|
# Add a visual separator.
|
|
print("\n\n ################################### \n\n")
|
|
print("Some parameters need update")
|
|
print("---------------------------")
|
|
for param, reason in params_to_update:
|
|
params = ",\n\t".join(param.tag)
|
|
print("[\n\t", params, "\n]", sep="")
|
|
print(f"--> reason: {reason} (param: {param})\n")
|
|
sys.exit(int(1)) # Explicit conversion is needed to make this call work
|
|
else:
|
|
print("All parameters passed the security check")
|