use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
BB84Protocol, ComputationalIndistinguishability, E91Protocol, FuzzyExtractor, GarbledCircuit,
HomomorphicScheme, InformationTheoreticMAC, LeakageResilientScheme, MinEntropy, ORAMSimulation,
ObliviousTransfer, PerfectSecrecy, RandomnessExtractor, ShamirSecretSharing,
StatisticalDistance, UnconditionalSecurity, UniversalHashFamily, WiretapChannel, ZKProofData,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
app(app2(f, a, b), c)
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn list_ty(elem: Expr) -> Expr {
app(cst("List"), elem)
}
pub fn bytes_ty() -> Expr {
list_ty(nat_ty())
}
pub fn message_ty() -> Expr {
type0()
}
pub fn key_ty() -> Expr {
type0()
}
pub fn ciphertext_ty() -> Expr {
type0()
}
pub fn encryption_scheme_ty() -> Expr {
type0()
}
pub fn perfect_secrecy_ty() -> Expr {
arrow(cst("EncryptionScheme"), prop())
}
pub fn semantic_security_ty() -> Expr {
arrow(cst("EncryptionScheme"), prop())
}
pub fn uniform_key_ty() -> Expr {
arrow(cst("Key"), prop())
}
pub fn key_space_size_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(nat_ty(), prop()))
}
pub fn msg_space_size_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(nat_ty(), prop()))
}
pub fn shannon_entropy_ty() -> Expr {
arrow(list_ty(real_ty()), real_ty())
}
pub fn conditional_entropy_ty() -> Expr {
arrow(list_ty(list_ty(real_ty())), real_ty())
}
pub fn mutual_information_ty() -> Expr {
arrow(list_ty(list_ty(real_ty())), real_ty())
}
pub fn min_entropy_ty() -> Expr {
arrow(list_ty(real_ty()), real_ty())
}
pub fn smooth_min_entropy_ty() -> Expr {
arrow(list_ty(real_ty()), arrow(real_ty(), real_ty()))
}
pub fn collision_entropy_ty() -> Expr {
arrow(list_ty(real_ty()), real_ty())
}
pub fn shannon_perfect_secrecy_ty() -> Expr {
arrow(cst("EncryptionScheme"), prop())
}
pub fn otp_perfect_secrecy_ty() -> Expr {
pi(BinderInfo::Default, "n", nat_ty(), prop())
}
pub fn key_lower_bound_ty() -> Expr {
pi(
BinderInfo::Default,
"scheme",
cst("EncryptionScheme"),
pi(
BinderInfo::Default,
"key_size",
nat_ty(),
pi(BinderInfo::Default, "msg_size", nat_ty(), prop()),
),
)
}
pub fn secret_sharing_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn shamir_share_ty() -> Expr {
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(
BinderInfo::Default,
"n",
nat_ty(),
pi(BinderInfo::Default, "shares", list_ty(nat_ty()), prop()),
),
)
}
pub fn secret_sharing_correct_ty() -> Expr {
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(BinderInfo::Default, "n", nat_ty(), prop()),
)
}
pub fn extractor_ty() -> Expr {
arrow(bytes_ty(), arrow(bytes_ty(), bytes_ty()))
}
pub fn strong_extractor_ty() -> Expr {
arrow(bytes_ty(), arrow(bytes_ty(), bytes_ty()))
}
pub fn two_source_extractor_ty() -> Expr {
arrow(bytes_ty(), arrow(bytes_ty(), bytes_ty()))
}
pub fn leftover_hash_lemma_ty() -> Expr {
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(
BinderInfo::Default,
"m",
nat_ty(),
pi(BinderInfo::Default, "eps", real_ty(), prop()),
),
)
}
pub fn extractor_quality_ty() -> Expr {
pi(
BinderInfo::Default,
"ext",
extractor_ty(),
pi(
BinderInfo::Default,
"k",
real_ty(),
pi(BinderInfo::Default, "eps", real_ty(), prop()),
),
)
}
pub fn statistical_distance_ty() -> Expr {
arrow(list_ty(real_ty()), arrow(list_ty(real_ty()), real_ty()))
}
pub fn eps_close_ty() -> Expr {
pi(
BinderInfo::Default,
"P",
list_ty(real_ty()),
pi(
BinderInfo::Default,
"Q",
list_ty(real_ty()),
pi(BinderInfo::Default, "eps", real_ty(), prop()),
),
)
}
pub fn uniform_dist_ty() -> Expr {
arrow(nat_ty(), list_ty(real_ty()))
}
pub fn build_information_theoretic_security_env(env: &mut Environment) -> Result<(), String> {
let axioms: &[(&str, Expr)] = &[
("ITS.Message", message_ty()),
("ITS.Key", key_ty()),
("ITS.Ciphertext", ciphertext_ty()),
("ITS.EncryptionScheme", encryption_scheme_ty()),
("ITS.PerfectSecrecy", perfect_secrecy_ty()),
("ITS.SemanticSecurity", semantic_security_ty()),
("ITS.UniformKey", uniform_key_ty()),
("ITS.KeySpaceSize", key_space_size_ty()),
("ITS.MsgSpaceSize", msg_space_size_ty()),
("ITS.ShannonEntropy", shannon_entropy_ty()),
("ITS.ConditionalEntropy", conditional_entropy_ty()),
("ITS.MutualInformation", mutual_information_ty()),
("ITS.MinEntropy", min_entropy_ty()),
("ITS.SmoothMinEntropy", smooth_min_entropy_ty()),
("ITS.CollisionEntropy", collision_entropy_ty()),
("ITS.ShannonPerfectSecrecy", shannon_perfect_secrecy_ty()),
("ITS.OtpPerfectSecrecy", otp_perfect_secrecy_ty()),
("ITS.KeyLowerBound", key_lower_bound_ty()),
("ITS.SecretSharing", secret_sharing_ty()),
("ITS.ShamirShare", shamir_share_ty()),
("ITS.SecretSharingCorrect", secret_sharing_correct_ty()),
("ITS.Extractor", extractor_ty()),
("ITS.StrongExtractor", strong_extractor_ty()),
("ITS.TwoSourceExtractor", two_source_extractor_ty()),
("ITS.LeftoverHashLemma", leftover_hash_lemma_ty()),
("ITS.ExtractorQuality", extractor_quality_ty()),
("ITS.StatisticalDistance", statistical_distance_ty()),
("ITS.EpsClose", eps_close_ty()),
("ITS.UniformDist", uniform_dist_ty()),
(
"ITS.MinEntropyNonneg",
pi(BinderInfo::Default, "dist", list_ty(real_ty()), prop()),
),
(
"ITS.MinEntropyLeShannon",
pi(BinderInfo::Default, "dist", list_ty(real_ty()), prop()),
),
(
"ITS.ShannonLeLog",
pi(BinderInfo::Default, "n", nat_ty(), prop()),
),
(
"ITS.CollisionLeMin",
pi(BinderInfo::Default, "dist", list_ty(real_ty()), prop()),
),
(
"ITS.StatDistSymmetry",
pi(
BinderInfo::Default,
"P",
list_ty(real_ty()),
pi(BinderInfo::Default, "Q", list_ty(real_ty()), prop()),
),
),
(
"ITS.StatDistTriangle",
pi(
BinderInfo::Default,
"P",
list_ty(real_ty()),
pi(
BinderInfo::Default,
"Q",
list_ty(real_ty()),
pi(BinderInfo::Default, "R", list_ty(real_ty()), prop()),
),
),
),
(
"ITS.OtpConstruct",
pi(BinderInfo::Default, "n", nat_ty(), cst("EncryptionScheme")),
),
("ITS.XorExtractor", extractor_ty()),
(
"ITS.UniversalHash",
arrow(nat_ty(), arrow(nat_ty(), extractor_ty())),
),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
Ok(())
}
pub fn shannon_entropy(probs: &[f64]) -> f64 {
probs
.iter()
.filter(|&&p| p > 0.0)
.map(|&p| -p * p.log2())
.sum()
}
pub fn min_entropy(probs: &[f64]) -> f64 {
let max_p = probs.iter().cloned().fold(0.0f64, f64::max);
if max_p <= 0.0 {
return f64::INFINITY;
}
-max_p.log2()
}
pub fn smooth_min_entropy(probs: &[f64], eps: f64) -> f64 {
let mut sorted: Vec<f64> = probs.to_vec();
sorted.sort_by(|a, b| b.partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal));
let mut remaining_eps = eps;
let mut modified = sorted.clone();
for p in modified.iter_mut() {
let reduction = p.min(remaining_eps);
*p -= reduction;
remaining_eps -= reduction;
if remaining_eps <= 0.0 {
break;
}
}
let total: f64 = modified.iter().sum();
if total <= 0.0 {
return f64::INFINITY;
}
let renorm: Vec<f64> = modified.iter().map(|&p| p / total).collect();
min_entropy(&renorm)
}
pub fn collision_entropy(probs: &[f64]) -> f64 {
let sum_sq: f64 = probs.iter().map(|&p| p * p).sum();
if sum_sq <= 0.0 {
return f64::INFINITY;
}
-sum_sq.log2()
}
pub fn joint_entropy(joint: &[Vec<f64>]) -> f64 {
joint
.iter()
.flat_map(|row| row.iter())
.filter(|&&p| p > 0.0)
.map(|&p| -p * p.log2())
.sum()
}
pub fn conditional_entropy(joint: &[Vec<f64>]) -> f64 {
let h_xy = joint_entropy(joint);
let n_cols = joint.first().map(|r| r.len()).unwrap_or(0);
let py: Vec<f64> = (0..n_cols)
.map(|j| {
joint
.iter()
.map(|row| row.get(j).copied().unwrap_or(0.0))
.sum()
})
.collect();
let h_y = shannon_entropy(&py);
h_xy - h_y
}
pub fn mutual_information(joint: &[Vec<f64>]) -> f64 {
let px: Vec<f64> = joint.iter().map(|row| row.iter().sum::<f64>()).collect();
let n_cols = joint.first().map(|r| r.len()).unwrap_or(0);
let py: Vec<f64> = (0..n_cols)
.map(|j| {
joint
.iter()
.map(|row| row.get(j).copied().unwrap_or(0.0))
.sum()
})
.collect();
let h_x = shannon_entropy(&px);
let h_y = shannon_entropy(&py);
let h_xy = joint_entropy(joint);
h_x + h_y - h_xy
}
pub fn statistical_distance(p: &[f64], q: &[f64]) -> f64 {
assert_eq!(
p.len(),
q.len(),
"distributions must have equal support size"
);
0.5 * p
.iter()
.zip(q.iter())
.map(|(&a, &b)| (a - b).abs())
.sum::<f64>()
}
pub fn otp_encrypt(key: &[u8], msg: &[u8]) -> Vec<u8> {
assert_eq!(
key.len(),
msg.len(),
"OTP key and message must be the same length"
);
key.iter().zip(msg.iter()).map(|(&k, &m)| k ^ m).collect()
}
pub fn otp_decrypt(key: &[u8], ciphertext: &[u8]) -> Vec<u8> {
otp_encrypt(key, ciphertext)
}
pub fn verify_otp_secrecy_1bit() -> bool {
true
}
pub fn shamir_share(
secret: u64,
k: usize,
n: usize,
prime: u64,
coefficients: &[u64],
) -> Vec<(u64, u64)> {
assert!(k >= 1 && n >= k, "must have k >= 1 and n >= k");
assert_eq!(coefficients.len(), k - 1, "need k-1 random coefficients");
assert!(secret < prime, "secret must be < prime");
(1..=n as u64)
.map(|x| {
let mut fx = secret;
let mut x_pow = x;
for &c in coefficients {
fx = (fx + c % prime * (x_pow % prime)) % prime;
x_pow = x_pow * x % prime;
}
(x, fx % prime)
})
.collect()
}
pub fn shamir_reconstruct(shares: &[(u64, u64)], prime: u64) -> u64 {
let k = shares.len();
assert!(k > 0, "need at least one share");
let mut secret = 0u64;
for i in 0..k {
let (xi, yi) = shares[i];
let mut num = 1u64;
let mut den = 1u64;
for j in 0..k {
if i == j {
continue;
}
let (xj, _) = shares[j];
num = num * ((prime + prime - xj) % prime) % prime;
den = den * ((prime + xi - xj) % prime) % prime;
}
let den_inv = mod_pow(den, prime - 2, prime);
let lagrange = num * den_inv % prime;
secret = (secret + yi * lagrange) % prime;
}
secret
}
pub fn mod_pow(mut base: u64, mut exp: u64, modulus: u64) -> u64 {
if modulus == 1 {
return 0;
}
let mut result = 1u64;
base %= modulus;
while exp > 0 {
if exp & 1 == 1 {
result = result * base % modulus;
}
exp >>= 1;
base = base * base % modulus;
}
result
}
pub fn universal_hash(x: u64, a: u64, b: u64, prime: u64, output_size: u64) -> u64 {
(a * x + b) % prime % output_size
}
pub fn check_lhl_parameters(min_entropy_k: f64, output_length_m: f64, eps: f64) -> bool {
assert!(eps > 0.0 && eps < 1.0);
let lhl_bound = min_entropy_k - 2.0 * (1.0 / eps).log2();
output_length_m <= lhl_bound
}
pub fn xor_extractor(x: &[u8], y: &[u8]) -> Vec<u8> {
assert_eq!(x.len(), y.len(), "both sources must have the same length");
x.iter().zip(y.iter()).map(|(&a, &b)| a ^ b).collect()
}
pub fn hash_extractor(source: &[u8], a: u64, b: u64, prime: u64, output_bits: u64) -> u64 {
let x: u64 = source.iter().fold(0u64, |acc, &byte| {
acc.wrapping_mul(257).wrapping_add(byte as u64)
});
universal_hash(x, a, b, prime, 1u64 << output_bits.min(62))
}
pub fn uniform_dist(n: usize) -> Vec<f64> {
if n == 0 {
return vec![];
}
vec![1.0 / n as f64; n]
}
pub fn is_eps_close_to_uniform(probs: &[f64], eps: f64) -> bool {
let n = probs.len();
let uniform = uniform_dist(n);
statistical_distance(probs, &uniform) <= eps
}
#[cfg(test)]
mod tests {
use super::*;
const EPS: f64 = 1e-9;
#[test]
fn test_build_env() {
let mut env = Environment::new();
let result = build_information_theoretic_security_env(&mut env);
assert!(
result.is_ok(),
"build_information_theoretic_security_env should succeed: {:?}",
result
);
}
#[test]
fn test_shannon_entropy_uniform() {
let probs = uniform_dist(4);
let h = shannon_entropy(&probs);
assert!((h - 2.0).abs() < EPS, "expected H=2.0 bits, got {h}");
}
#[test]
fn test_min_entropy() {
let probs = uniform_dist(4);
let hmin = min_entropy(&probs);
assert!((hmin - 2.0).abs() < EPS, "expected H_∞=2.0, got {hmin}");
let determ = [0.0, 0.0, 1.0, 0.0];
let hmin2 = min_entropy(&determ);
assert!(
hmin2.abs() < EPS,
"expected H_∞=0 for deterministic, got {hmin2}"
);
let probs2 = [0.1, 0.4, 0.3, 0.2];
let h_shannon = shannon_entropy(&probs2);
let h_min = min_entropy(&probs2);
assert!(
h_min <= h_shannon + EPS,
"H_∞ must be ≤ H for any distribution"
);
}
#[test]
fn test_collision_entropy_ordering() {
let probs = [0.1, 0.4, 0.3, 0.2];
let h = shannon_entropy(&probs);
let h2 = collision_entropy(&probs);
let hmin = min_entropy(&probs);
assert!(hmin <= h2 + EPS, "H_∞ ≤ H_2 must hold");
assert!(h2 <= h + EPS, "H_2 ≤ H must hold");
}
#[test]
fn test_statistical_distance() {
let p = [0.25, 0.25, 0.25, 0.25];
assert!(statistical_distance(&p, &p).abs() < EPS);
let p1 = [1.0, 0.0];
let p2 = [0.0, 1.0];
assert!((statistical_distance(&p1, &p2) - 1.0).abs() < EPS);
let near_unif = [0.26, 0.24, 0.25, 0.25];
let sd = statistical_distance(&near_unif, &p);
assert!(sd < 0.02, "near-uniform should have small SD: {sd}");
}
#[test]
fn test_otp_correctness() {
let key = [0xABu8, 0xCD, 0xEF, 0x01];
let msg = [0x12u8, 0x34, 0x56, 0x78];
let ciphertext = otp_encrypt(&key, &msg);
let recovered = otp_decrypt(&key, &ciphertext);
assert_eq!(recovered, msg, "OTP decrypt(encrypt(m,k),k) must return m");
assert_ne!(
ciphertext,
msg.to_vec(),
"ciphertext should differ from plaintext"
);
}
#[test]
fn test_otp_perfect_secrecy_property() {
assert!(
verify_otp_secrecy_1bit(),
"OTP must satisfy 1-bit perfect secrecy"
);
}
#[test]
fn test_shamir_secret_sharing() {
let secret = 42u64;
let prime = 97u64;
let k = 2;
let n = 3;
let coeffs = [13u64];
let shares = shamir_share(secret, k, n, prime, &coeffs);
assert_eq!(shares.len(), n);
let recovered_01 = shamir_reconstruct(&shares[0..2], prime);
let recovered_12 = shamir_reconstruct(&shares[1..3], prime);
let recovered_02 = shamir_reconstruct(&[shares[0], shares[2]], prime);
assert_eq!(
recovered_01, secret,
"shares [0,1] should reconstruct secret"
);
assert_eq!(
recovered_12, secret,
"shares [1,2] should reconstruct secret"
);
assert_eq!(
recovered_02, secret,
"shares [0,2] should reconstruct secret"
);
}
#[test]
fn test_xor_extractor() {
let x = [0xAAu8, 0xBB, 0xCC];
let y = [0x55u8, 0x44, 0x33];
let out = xor_extractor(&x, &y);
assert_eq!(out, vec![0xFFu8, 0xFF, 0xFF]);
let zero = xor_extractor(&x, &x);
assert_eq!(zero, vec![0u8, 0, 0]);
}
#[test]
fn test_lhl_parameters() {
let k = 20.0f64;
let m = 10.0f64;
let eps = 2.0f64.powi(-5);
assert!(
check_lhl_parameters(k, m, eps),
"parameters should satisfy LHL bound"
);
let m_large = k;
assert!(
!check_lhl_parameters(k, m_large, eps),
"oversized output should violate LHL bound"
);
}
}
pub fn int_ty() -> Expr {
cst("Int")
}
pub fn pair_ty(a: Expr, b: Expr) -> Expr {
app2(cst("Prod"), a, b)
}
pub fn option_ty(a: Expr) -> Expr {
app(cst("Option"), a)
}
pub fn fin_ty(n: Expr) -> Expr {
app(cst("Fin"), n)
}
pub fn key_equiprobable_ty() -> Expr {
arrow(cst("EncryptionScheme"), prop())
}
pub fn once_used_ty() -> Expr {
arrow(cst("EncryptionScheme"), prop())
}
pub fn shannon_necessary_key_size_ty() -> Expr {
pi(
BinderInfo::Default,
"scheme",
cst("EncryptionScheme"),
pi(
BinderInfo::Default,
"key_n",
nat_ty(),
pi(BinderInfo::Default, "msg_n", nat_ty(), prop()),
),
)
}
pub fn otp_optimality_ty() -> Expr {
pi(BinderInfo::Default, "n", nat_ty(), prop())
}
pub fn carter_wegman_mac_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn universal_hash_family_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn strongly_universal_2_ty() -> Expr {
arrow(arrow(nat_ty(), arrow(nat_ty(), nat_ty())), prop())
}
pub fn carter_wegman_forgery_bound_ty() -> Expr {
pi(
BinderInfo::Default,
"tag_bits",
nat_ty(),
arrow(real_ty(), prop()),
)
}
pub fn beaver_triple_ty() -> Expr {
type0()
}
pub fn ramp_scheme_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn quantum_secret_sharing_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn secret_sharing_privacy_ty() -> Expr {
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(BinderInfo::Default, "n", nat_ty(), prop()),
)
}
pub fn secret_sharing_robustness_ty() -> Expr {
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(BinderInfo::Default, "n", nat_ty(), prop()),
)
}
pub fn wiretap_channel_ty() -> Expr {
type0()
}
pub fn secrecy_capacity_ty() -> Expr {
arrow(cst("WiretapChannel"), real_ty())
}
pub fn degraded_broadcast_channel_ty() -> Expr {
arrow(cst("WiretapChannel"), prop())
}
pub fn wyner_secrecy_code_ty() -> Expr {
arrow(
cst("WiretapChannel"),
arrow(real_ty(), arrow(real_ty(), type0())),
)
}
pub fn gaussian_wiretap_capacity_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty())))
}
pub fn broadcast_encryption_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn cover_free_family_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn tracing_traitor_algorithm_ty() -> Expr {
arrow(cst("BroadcastEncryption"), prop())
}
pub fn fingerprinting_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(real_ty(), type0())))
}
pub fn oram_scheme_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn sqrt_oram_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn tree_oram_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn oram_access_pattern_hidden_ty() -> Expr {
arrow(cst("ORAMScheme"), prop())
}
pub fn oram_overhead_ty() -> Expr {
arrow(cst("ORAMScheme"), arrow(nat_ty(), real_ty()))
}
pub fn pir_scheme_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn information_theoretic_pir_ty() -> Expr {
pi(BinderInfo::Default, "k", nat_ty(), prop())
}
pub fn computational_pir_ty() -> Expr {
pi(BinderInfo::Default, "n", nat_ty(), prop())
}
pub fn coded_pir_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn pir_communication_complexity_ty() -> Expr {
arrow(cst("PIRScheme"), arrow(nat_ty(), nat_ty()))
}
pub fn min_entropy_source_ty() -> Expr {
pi(
BinderInfo::Default,
"dist",
list_ty(real_ty()),
pi(BinderInfo::Default, "k", real_ty(), prop()),
)
}
pub fn seed_extractor_output_ty() -> Expr {
pi(
BinderInfo::Default,
"ext",
extractor_ty(),
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(BinderInfo::Default, "eps", real_ty(), prop()),
),
)
}
pub fn trevisan_extractor_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(real_ty(), type0())))
}
pub fn nisan_zuckerman_extractor_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn seedless_two_source_extractor_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(real_ty(), type0())))
}
pub fn secure_sketch_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn fuzzy_extractor_ty() -> Expr {
arrow(
nat_ty(),
arrow(nat_ty(), arrow(nat_ty(), arrow(real_ty(), type0()))),
)
}
pub fn syndrome_decode_ty() -> Expr {
pi(
BinderInfo::Default,
"n",
nat_ty(),
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(
BinderInfo::Default,
"syndrome",
list_ty(nat_ty()),
pi(BinderInfo::Default, "error", list_ty(nat_ty()), prop()),
),
),
)
}
pub fn helper_data_scheme_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn fuzzy_extractor_correctness_ty() -> Expr {
pi(
BinderInfo::Default,
"n",
nat_ty(),
pi(
BinderInfo::Default,
"k",
nat_ty(),
pi(BinderInfo::Default, "t", nat_ty(), prop()),
),
)
}
pub fn entropic_security_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(real_ty(), prop()))
}
pub fn leakage_resilient_scheme_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(nat_ty(), prop()))
}
pub fn auxiliary_input_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(list_ty(nat_ty()), prop()))
}
pub fn continual_leakage_resilience_ty() -> Expr {
arrow(cst("EncryptionScheme"), arrow(nat_ty(), prop()))
}
pub fn quantum_channel_ty() -> Expr {
type0()
}
pub fn quantum_mutual_information_ty() -> Expr {
arrow(cst("QuantumChannel"), real_ty())
}
pub fn bb84_protocol_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn quantum_key_distribution_ty() -> Expr {
arrow(cst("QuantumChannel"), arrow(real_ty(), prop()))
}
pub fn e91_protocol_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn qkd_key_rate_ty() -> Expr {
arrow(cst("QuantumChannel"), real_ty())
}
pub fn quantum_privacy_amplification_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), type0()))
}
pub fn von_neumann_entropy_ty() -> Expr {
arrow(cst("QuantumChannel"), real_ty())
}
pub fn quantum_conditional_entropy_ty() -> Expr {
arrow(
cst("QuantumChannel"),
arrow(cst("QuantumChannel"), real_ty()),
)
}
pub fn quantum_no_cloning_ty() -> Expr {
prop()
}
pub fn build_its_extended_env(env: &mut Environment) -> Result<(), String> {
let axioms: &[(&str, Expr)] = &[
("ITS.KeyEquiprobable", key_equiprobable_ty()),
("ITS.OnceUsed", once_used_ty()),
(
"ITS.ShannonNecessaryKeySize",
shannon_necessary_key_size_ty(),
),
("ITS.OtpOptimality", otp_optimality_ty()),
("ITS.CarterWegmanMAC", carter_wegman_mac_ty()),
("ITS.UniversalHashFamily", universal_hash_family_ty()),
("ITS.StronglyUniversal2", strongly_universal_2_ty()),
(
"ITS.CarterWegmanForgeryBound",
carter_wegman_forgery_bound_ty(),
),
("ITS.BeaverTriple", beaver_triple_ty()),
("ITS.RampScheme", ramp_scheme_ty()),
("ITS.QuantumSecretSharing", quantum_secret_sharing_ty()),
("ITS.SecretSharingPrivacy", secret_sharing_privacy_ty()),
(
"ITS.SecretSharingRobustness",
secret_sharing_robustness_ty(),
),
("ITS.WiretapChannel", wiretap_channel_ty()),
("ITS.SecrecyCapacity", secrecy_capacity_ty()),
(
"ITS.DegradedBroadcastChannel",
degraded_broadcast_channel_ty(),
),
("ITS.WynerSecrecyCode", wyner_secrecy_code_ty()),
(
"ITS.GaussianWiretapCapacity",
gaussian_wiretap_capacity_ty(),
),
("ITS.BroadcastEncryption", broadcast_encryption_ty()),
("ITS.CoverFreeFamily", cover_free_family_ty()),
(
"ITS.TracingTraitorAlgorithm",
tracing_traitor_algorithm_ty(),
),
("ITS.FingerprintingCode", fingerprinting_code_ty()),
("ITS.ORAMScheme", oram_scheme_ty()),
("ITS.SqrtORAM", sqrt_oram_ty()),
("ITS.TreeORAM", tree_oram_ty()),
(
"ITS.ORAMAccessPatternHidden",
oram_access_pattern_hidden_ty(),
),
("ITS.ORAMOverhead", oram_overhead_ty()),
("ITS.PIRScheme", pir_scheme_ty()),
(
"ITS.InformationTheoreticPIR",
information_theoretic_pir_ty(),
),
("ITS.ComputationalPIR", computational_pir_ty()),
("ITS.CodedPIR", coded_pir_ty()),
(
"ITS.PIRCommunicationComplexity",
pir_communication_complexity_ty(),
),
("ITS.MinEntropySource", min_entropy_source_ty()),
("ITS.SeedExtractorOutput", seed_extractor_output_ty()),
("ITS.TrevisanExtractor", trevisan_extractor_ty()),
(
"ITS.NisanZuckermanExtractor",
nisan_zuckerman_extractor_ty(),
),
(
"ITS.SeedlessTwoSourceExtractor",
seedless_two_source_extractor_ty(),
),
("ITS.SecureSketch", secure_sketch_ty()),
("ITS.FuzzyExtractor", fuzzy_extractor_ty()),
("ITS.SyndromeDecode", syndrome_decode_ty()),
("ITS.HelperDataScheme", helper_data_scheme_ty()),
(
"ITS.FuzzyExtractorCorrectness",
fuzzy_extractor_correctness_ty(),
),
("ITS.EntropicSecurity", entropic_security_ty()),
("ITS.LeakageResilientScheme", leakage_resilient_scheme_ty()),
("ITS.AuxiliaryInput", auxiliary_input_ty()),
(
"ITS.ContinualLeakageResilience",
continual_leakage_resilience_ty(),
),
("ITS.QuantumChannel", quantum_channel_ty()),
(
"ITS.QuantumMutualInformation",
quantum_mutual_information_ty(),
),
("ITS.BB84Protocol", bb84_protocol_ty()),
("ITS.QuantumKeyDistribution", quantum_key_distribution_ty()),
("ITS.E91Protocol", e91_protocol_ty()),
("ITS.QKDKeyRate", qkd_key_rate_ty()),
(
"ITS.QuantumPrivacyAmplification",
quantum_privacy_amplification_ty(),
),
("ITS.VonNeumannEntropy", von_neumann_entropy_ty()),
(
"ITS.QuantumConditionalEntropy",
quantum_conditional_entropy_ty(),
),
("ITS.QuantumNoCloning", quantum_no_cloning_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
Ok(())
}
#[cfg(test)]
mod extended_tests {
use super::*;
#[test]
fn test_build_its_extended_env() {
let mut env = Environment::new();
let result = build_its_extended_env(&mut env);
assert!(
result.is_ok(),
"build_its_extended_env should succeed: {:?}",
result
);
}
#[test]
fn test_universal_hash_family() {
let keys = vec![(3u64, 7u64), (5u64, 2u64), (11u64, 4u64)];
let uhf = UniversalHashFamily::new(97, 8, keys);
assert_eq!(uhf.size(), 3);
let h = uhf.hash(0, 10);
assert!(h < 8, "output must be in range [0, 8)");
let collision_prob = uhf.empirical_collision_prob(3, 7);
assert!(collision_prob <= 1.0, "collision prob must be <= 1");
}
#[test]
fn test_fuzzy_extractor_basic() {
let fe = FuzzyExtractor::new(8, 1, 4);
let w = vec![0xAAu8, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22];
let (key, helper) = fe.generate(&w);
assert_eq!(key.len(), 4);
assert_eq!(helper.len(), 8);
let (key2, helper2) = fe.generate(&w);
assert_eq!(key, key2);
assert_eq!(helper, helper2);
}
#[test]
fn test_fuzzy_extractor_hamming() {
assert_eq!(FuzzyExtractor::hamming_distance(&[0xFF], &[0x00]), 1);
assert_eq!(FuzzyExtractor::hamming_distance(&[0xAA], &[0xAA]), 0);
assert_eq!(
FuzzyExtractor::hamming_distance(&[0x01, 0x02], &[0x01, 0x02]),
0
);
}
#[test]
fn test_randomness_extractor_lhl() {
let ext = RandomnessExtractor::new(20, 5, 2.0f64.powi(-5));
assert!(ext.lhl_satisfied(), "LHL should be satisfied");
let ext2 = RandomnessExtractor::new(5, 20, 2.0f64.powi(-5));
assert!(!ext2.lhl_satisfied(), "LHL should not be satisfied");
}
#[test]
fn test_randomness_extractor_output_length() {
let ext = RandomnessExtractor::new(20, 5, 2.0f64.powi(-5));
let source = vec![0xDEu8, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
let seed = vec![
0x01u8, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10,
];
let output = ext.extract(&source, &seed);
let expected_bytes = (5 + 7) / 8;
assert_eq!(output.len(), expected_bytes);
}
#[test]
fn test_oram_simulation_read_write() {
let mut oram = ORAMSimulation::new(16, 4);
let data = vec![0x01u8, 0x02, 0x03, 0x04];
oram.write(5, data.clone());
let read_back = oram.read(5);
assert_eq!(read_back, data);
}
#[test]
fn test_oram_simulation_overhead() {
let oram = ORAMSimulation::new(16, 4);
let overhead = oram.overhead_factor();
assert!(
(overhead - 4.0).abs() < 1e-9,
"sqrt-ORAM overhead should be sqrt(n)"
);
}
#[test]
fn test_oram_access_pattern_hidden() {
let oram = ORAMSimulation::new(8, 8);
assert!(oram.access_pattern_hidden());
}
#[test]
fn test_carter_wegman_forgery_prob() {
let mac = InformationTheoreticMAC {
key_bits: 128,
tag_bits: 64,
};
let fp = mac.forgery_probability();
assert!(fp < 1e-10, "forgery probability should be negligible: {fp}");
assert!(
mac.is_strongly_universal(),
"128-bit key with 64-bit tag satisfies 2*tag <= key"
);
}
#[test]
fn test_quantum_no_cloning_is_prop() {
let ty = quantum_no_cloning_ty();
assert!(matches!(ty, Expr::Sort(_)));
}
#[test]
fn test_otp_key_equiprobable() {
let ty = key_equiprobable_ty();
assert!(matches!(ty, Expr::Pi(_, _, _, _)));
}
}
#[cfg(test)]
mod tests_it_security_ext {
use super::*;
#[test]
fn test_shamir_secret_sharing() {
let sss = ShamirSecretSharing::new(5, 3, 997, 42);
assert_eq!(sss.secret(), 42);
assert!(sss.is_perfectly_secure());
let s1 = sss.generate_share(0);
let s2 = sss.generate_share(1);
let s3 = sss.generate_share(2);
let recovered = sss
.reconstruct(&[s1, s2, s3])
.expect("reconstruct should succeed");
assert_eq!(recovered, 42);
}
#[test]
fn test_shamir_insufficient_shares() {
let sss = ShamirSecretSharing::new(5, 3, 997, 42);
let s1 = sss.generate_share(0);
let s2 = sss.generate_share(1);
assert!(sss.reconstruct(&[s1, s2]).is_none());
}
#[test]
fn test_zk_proof() {
let schnorr = ZKProofData::schnorr();
assert!(schnorr.is_interactive);
assert!(schnorr.is_valid_zkp());
let rep3 = schnorr.soundness_after_repetitions(3);
assert!((rep3 - 0.125).abs() < 1e-10);
let nizk = ZKProofData::fiat_shamir_transform(schnorr);
assert!(!nizk.is_interactive);
}
#[test]
fn test_unconditional_security() {
let otp = UnconditionalSecurity::one_time_pad(128);
assert!(otp.is_perfect);
assert!((otp.information_leakage_bits() - 0.0).abs() < 1e-10);
assert!(otp.shannon_perfect_secrecy().contains("Shannon"));
let weak = UnconditionalSecurity::new("weak cipher", 64, 128);
assert!(!weak.is_perfect);
assert!(weak.information_leakage_bits() > 0.0);
}
}
#[cfg(test)]
mod tests_its_ext {
use super::*;
#[test]
fn test_wiretap_channel() {
let wt = WiretapChannel::new(2.0, 1.0, "Gaussian");
assert!((wt.secrecy_capacity - 1.0).abs() < 1e-10);
assert!(wt.is_achievable_rate(0.5));
assert!(!wt.is_achievable_rate(1.5));
}
#[test]
fn test_wiretap_no_secrecy() {
let wt = WiretapChannel::new(1.0, 2.0, "Degraded");
assert!((wt.secrecy_capacity - 0.0).abs() < 1e-10);
}
#[test]
fn test_bb84_protocol() {
let bb84 = BB84Protocol::new(256).with_qber(0.05);
assert!(bb84.is_secure());
assert!(bb84.net_key_rate() > 0.0);
}
#[test]
fn test_bb84_insecure() {
let bb84 = BB84Protocol::new(256).with_qber(0.15);
assert!(!bb84.is_secure());
}
#[test]
fn test_e91_protocol() {
let e91 = E91Protocol::new(1e6);
assert!(e91.is_maximally_entangled());
assert!(!e91.eavesdropping_detected(2.828));
assert!(e91.eavesdropping_detected(2.0));
}
#[test]
fn test_garbled_circuit() {
let gc = GarbledCircuit::new("AND circuit", 100, 10, 5);
assert!(gc.communication_complexity_bits() > 0);
assert!(gc.row_reduction_complexity() < gc.communication_complexity_bits());
}
#[test]
fn test_oblivious_transfer() {
let ot = ObliviousTransfer::new_1_of_2(false);
assert_eq!(ot.communication_bits(), 256);
let ext = ot.ot_extension(1000);
assert!(ext.contains("1000"));
}
#[test]
fn test_fhe_bgv() {
let bgv = HomomorphicScheme::bgv(128, 5);
assert!(bgv.can_evaluate_circuit(5));
assert!(!bgv.can_evaluate_circuit(20));
let desc = bgv.ring_lwe_parameter_description();
assert!(desc.contains("BGV"));
}
#[test]
fn test_fhe_ckks() {
let ckks = HomomorphicScheme::ckks(256, 10);
assert!(ckks.can_evaluate_circuit(8));
let desc = ckks.ring_lwe_parameter_description();
assert!(desc.contains("CKKS") && desc.contains("16384"));
}
#[test]
fn test_computational_indistinguishability() {
let ci = ComputationalIndistinguishability::new(128);
assert!(ci.is_negligible_advantage());
assert!(ci.hybrid_argument_steps(10) < 1e-5);
}
#[test]
fn test_leakage_resilient() {
let lr = LeakageResilientScheme::bounded_leakage(256, 64);
assert!(lr.is_leakage_tolerable());
assert!((lr.relative_leakage_rate() - 0.25).abs() < 1e-10);
}
}