mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-15 15:15:06 -05:00
start with something simple
This commit is contained in:
150
new_scripts.py
Normal file
150
new_scripts.py
Normal file
@@ -0,0 +1,150 @@
|
||||
## for now, run using sage new_scripts.py
|
||||
from estimator_new import *
|
||||
from math import log2
|
||||
|
||||
def estimate_lwe_nocrash(params):
|
||||
"""
|
||||
Retrieve an estimate using the Lattice Estimator, for a given set of input parameters
|
||||
:param params: the input LWE parameters
|
||||
"""
|
||||
try:
|
||||
estimate = LWE.estimate(params)
|
||||
except:
|
||||
estimate = 0
|
||||
return estimate
|
||||
|
||||
def get_security_level(estimate, dp = 2):
|
||||
"""
|
||||
Get the security level lambda from a Lattice Estimator output
|
||||
:param estimate: the Lattice Estimator output
|
||||
:param dp : the number of decimal places to consider
|
||||
"""
|
||||
attack_costs = []
|
||||
for key in estimate.keys():
|
||||
attack_costs.append(estimate[key]["rop"])
|
||||
# get the security level correct to 'dp' decimal places
|
||||
security_level = round(log2(min(attack_costs)), dp)
|
||||
return security_level
|
||||
|
||||
def inequality(x, y):
|
||||
""" A utility function which compresses the conditions x < y and x > y into a single condition via a multiplier
|
||||
:param x: the LHS of the inequality
|
||||
:param y: the RHS of the inequality
|
||||
"""
|
||||
if x <= y:
|
||||
return 1
|
||||
|
||||
if x > y:
|
||||
return -1
|
||||
|
||||
def automated_param_select_n(params, target_security=128):
|
||||
""" A function used to generate the smallest value of n which allows for
|
||||
target_security bits of security, for the input values of (params.Xe.stddev,params.q)
|
||||
:param params: the standard deviation of the error
|
||||
:param secret_distribution: the LWE secret distribution
|
||||
:param target_security: the target number of bits of security, 128 is default
|
||||
|
||||
EXAMPLE:
|
||||
sage: X = automated_param_select_n(Kyber512, target_security = 128)
|
||||
sage: X
|
||||
456
|
||||
"""
|
||||
|
||||
# get an initial estimate
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
# determine if we are above or below the target security level
|
||||
z = inequality(security_level, target_security)
|
||||
|
||||
while z * security_level < z * target_security and params.n > 80:
|
||||
params = params.updated(n = params.n + z * 8)
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
|
||||
if (-1 * params.Xe.stddev > 0):
|
||||
print("target security level is unatainable")
|
||||
break
|
||||
|
||||
# final estimate (we went too far in the above loop)
|
||||
if security_level < target_security:
|
||||
params = params.updated(n = params.n - z * 8)
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
|
||||
print("the finalised parameters are n = {}, log2(sd) = {}, log2(q) = {}, with a security level of {}-bits".format(params.n,
|
||||
params.Xe.stddev,
|
||||
log2(params.q),
|
||||
security_level))
|
||||
|
||||
# final sanity check so we don't return insecure (or inf) parameters
|
||||
# TODO: figure out inf in new estimator
|
||||
if security_level < target_security: #or security_level == oo:
|
||||
params.update(n = None)
|
||||
|
||||
return params
|
||||
|
||||
def automated_param_select_sd(params, target_security=128):
|
||||
""" A function used to generate the smallest value of sd which allows for
|
||||
target_security bits of security, for the input values of (params.Xe.stddev,params.q)
|
||||
:param params: the standard deviation of the error
|
||||
:param secret_distribution: the LWE secret distribution
|
||||
:param target_security: the target number of bits of security, 128 is default
|
||||
|
||||
EXAMPLE:
|
||||
sage: X = automated_param_select_n(Kyber512, target_security = 128)
|
||||
sage: X
|
||||
456
|
||||
"""
|
||||
|
||||
#if sd is None:
|
||||
# pick some random sd which gets us close (based on concrete_LWE_params)
|
||||
# sd = round(n * 80 / (target_security * (-25)))
|
||||
|
||||
# make sure sd satisfies q * sd > 1
|
||||
# sd = max(sd, -(log(q,2) - 2))
|
||||
|
||||
#sd_ = (2 ** sd) * q
|
||||
#alpha = sqrt(2 * pi) * sd_ / RR(q)
|
||||
|
||||
# get an initial estimate
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
# determine if we are above or below the target security level
|
||||
z = inequality(security_level, target_security)
|
||||
|
||||
while z * security_level < z * target_security: #and sd > -log(q,2):
|
||||
|
||||
Xe_new = nd.NoiseDistribution.DiscreteGaussian(params.Xe.stddev + z * (0.5))
|
||||
params.updated(Xe = Xe_new)
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
|
||||
if (params.Xe.stddev > log2(params.q)):
|
||||
print("target security level is unatainable")
|
||||
return None
|
||||
|
||||
# final estimate (we went too far in the above loop)
|
||||
if security_level < target_security:
|
||||
Xe_new = nd.NoiseDistribution.DiscreteGaussian(params.Xe.stddev - z * (0.5))
|
||||
params.updated(Xe = Xe_new)
|
||||
costs = estimate_lwe_nocrash(params)
|
||||
security_level = get_security_level(costs, 2)
|
||||
|
||||
print("the finalised parameters are n = {}, log2(sd) = {}, log2(q) = {}, with a security level of {}-bits".format(params.n,
|
||||
params.Xe.stddev,
|
||||
log2(params.q),
|
||||
security_level))
|
||||
|
||||
return params
|
||||
|
||||
|
||||
|
||||
params = Kyber512
|
||||
|
||||
#x = estimate_lwe_nocrash(params)
|
||||
#y = get_security_level(x, 2)
|
||||
#print(y)
|
||||
#z1 = automated_param_select_n(Kyber512, 128)
|
||||
#print(z1)
|
||||
#z2 = automated_param_select_sd(Kyber512, 128)
|
||||
#print(z2)
|
||||
Reference in New Issue
Block a user