Skip to content

Commit

Permalink
Merge pull request #151 from Nashtare/security-estimate
Browse files Browse the repository at this point in the history
Security estimate
  • Loading branch information
irakliyk committed Mar 20, 2023
2 parents a705179 + 6dbadd6 commit c99530d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 14 deletions.
62 changes: 57 additions & 5 deletions air/src/proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,16 @@ impl StarkProof {
get_conjectured_security(
self.context.options(),
self.context.num_modulus_bits(),
self.lde_domain_size() as u64,
self.trace_length() as u64,
H::COLLISION_RESISTANCE,
)
} else {
// TODO: implement provable security estimation
unimplemented!("proven security estimation has not been implement yet")
get_proven_security(
self.context.options(),
self.context.num_modulus_bits(),
self.lde_domain_size() as u64,
H::COLLISION_RESISTANCE,
)
}
}

Expand Down Expand Up @@ -177,12 +181,12 @@ impl StarkProof {
fn get_conjectured_security(
options: &ProofOptions,
base_field_bits: u32,
lde_domain_size: u64,
trace_domain_size: u64,
collision_resistance: u32,
) -> u32 {
// compute max security we can get for a given field size
let field_size = base_field_bits * options.field_extension().degree();
let field_security = field_size - lde_domain_size.trailing_zeros();
let field_security = field_size - trace_domain_size.trailing_zeros();

// compute security we get by executing multiple query rounds
let security_per_query = log2(options.blowup_factor());
Expand All @@ -198,3 +202,51 @@ fn get_conjectured_security(
collision_resistance,
)
}

/// Estimates proven security level for the specified proof parameters.
fn get_proven_security(
options: &ProofOptions,
base_field_bits: u32,
lde_domain_size: u64,
collision_resistance: u32,
) -> u32 {
let extension_field_bits = (base_field_bits * options.field_extension().degree()) as f64;
let blowup_bits = log2(options.blowup_factor()) as f64;
let num_fri_queries = options.num_queries() as f64;
let lde_size_bits = lde_domain_size.trailing_zeros() as f64;

// m is a parameter greater or equal to 3.
// A larger m gives a worse field security bound but a better query security bound.
// An optimal value of m is then a value that would balance field and query security
// but there is no simple closed form solution.
// This sets m so that field security is equal to the best query security for any value
// of m, unless the calculated value is less than 3 in which case it gets rounded up to 3.
let mut m = extension_field_bits + 1.0;
m -= options.grinding_factor() as f64;
m -= (num_fri_queries + 3.0) / 2.0 * blowup_bits;
m -= 2.0 * lde_size_bits;
m /= 7.0;
m = 2.0_f64.powf(m);
m -= 0.5;
m = m.max(3.0);

// compute pre-FRI query security
// this considers only the third component given in the corresponding part of eq. 20
// in https://eprint.iacr.org/2021/582, i.e. (m+1/2)^7.n^2 / (2\rho^1.5.q) as all
// other terms are negligible in comparison.
let pre_query_security = (extension_field_bits + 1.0
- 3.0 / 2.0 * blowup_bits
- 2.0 * lde_size_bits
- 7.0 * (m + 0.5).log2()) as u32;

// compute security we get by executing multiple query rounds
let security_per_query = 0.5 * blowup_bits - (1.0 + 1.0 / (2.0 * m)).log2();
let mut query_security = (security_per_query * num_fri_queries) as u32;

query_security += options.grinding_factor();

cmp::min(
cmp::min(pre_query_security, query_security) - 1,
collision_resistance,
)
}
14 changes: 7 additions & 7 deletions examples/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ impl ExampleOptions {
}

/// Returns security level of the input proof in bits.
pub fn get_proof_security_level(&self, proof: &StarkProof) -> usize {
pub fn get_proof_security_level(&self, proof: &StarkProof, conjectured: bool) -> usize {
let security_level = match self.hash_fn.as_str() {
"blake3_192" => proof.security_level::<Blake3_192>(true),
"blake3_256" => proof.security_level::<Blake3_256>(true),
"sha3_256" => proof.security_level::<Sha3_256>(true),
"rp64_256" => proof.security_level::<Rp64_256>(true),
"rp_jive64_256" => proof.security_level::<RpJive64_256>(true),
"griffin_jive64_256" => proof.security_level::<GriffinJive64_256>(true),
"blake3_192" => proof.security_level::<Blake3_192>(conjectured),
"blake3_256" => proof.security_level::<Blake3_256>(conjectured),
"sha3_256" => proof.security_level::<Sha3_256>(conjectured),
"rp64_256" => proof.security_level::<Rp64_256>(conjectured),
"rp_jive64_256" => proof.security_level::<RpJive64_256>(conjectured),
"griffin_jive64_256" => proof.security_level::<GriffinJive64_256>(conjectured),
val => panic!("'{val}' is not a valid hash function option"),
};

Expand Down
8 changes: 6 additions & 2 deletions examples/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ fn main() {

let proof_bytes = proof.to_bytes();
debug!("Proof size: {:.1} KB", proof_bytes.len() as f64 / 1024f64);
let security_level = options.get_proof_security_level(&proof);
debug!("Proof security: {} bits", security_level);
let conjectured_security_level = options.get_proof_security_level(&proof, true);
let proven_security_level = options.get_proof_security_level(&proof, false);
debug!(
"Proof security: {} bits ({} proven)",
conjectured_security_level, proven_security_level,
);
#[cfg(feature = "std")]
debug!(
"Proof hash: {}",
Expand Down

0 comments on commit c99530d

Please sign in to comment.