Add attack on ghash which leaks the MAC key

This commit is contained in:
th4s
2024-01-04 10:58:17 +01:00
parent c3d958c0c8
commit 0bf1cbadd2
4 changed files with 91 additions and 1 deletions

12
Cargo.lock generated
View File

@@ -335,6 +335,17 @@ dependencies = [
"typenum",
]
[[package]]
name = "delegate"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.40",
]
[[package]]
name = "der"
version = "0.7.8"
@@ -584,6 +595,7 @@ dependencies = [
name = "ole-protocols"
version = "0.1.0"
dependencies = [
"delegate",
"itybity",
"mpz-share-conversion-core",
"p256",

View File

@@ -10,6 +10,7 @@ mpz-share-conversion-core = { git = "https://github.com/privacy-scaling-explorat
p256 = { version = "0.13", features = ["arithmetic"] }
itybity = "0.2"
rand = "0.8"
delegate = "0.12"

View File

@@ -5,7 +5,7 @@ mod verifier;
use crate::func::ole::Ole;
use mpz_share_conversion_core::{fields::gf2_128::Gf2_128, Field};
pub use prover::Prover;
pub use prover::{MaliciousProver, Prover};
pub use verifier::Verifier;
pub fn ghash(blocks: &[Gf2_128], prover: &mut Prover, verifier: &mut Verifier) -> Gf2_128 {
@@ -33,6 +33,36 @@ pub fn ghash(blocks: &[Gf2_128], prover: &mut Prover, verifier: &mut Verifier) -
ghash1 + ghash2
}
/// The prover is malicious and will set r1 to zero
pub fn ghash_with_input_zero_from_prover(
blocks: &[Gf2_128],
prover: &mut MaliciousProver,
verifier: &mut Verifier,
) -> Gf2_128 {
let mut ole = Ole::default();
prover.preprocess_ole_input(&mut ole);
verifier.preprocess_ole_input(&mut ole);
prover.preprocess_ole_output(&mut ole);
verifier.preprocess_ole_output(&mut ole);
let d1 = prover.handshake_a_open_d();
let d2 = verifier.handshake_a_open_d();
let d = d1 + d2;
prover.handshake_a_set_di(d);
verifier.handshake_a_set_di(d);
prover.handshake_a_set_hi();
verifier.handshake_a_set_hi();
let ghash1 = prover.handshake_output_ghash(blocks);
let ghash2 = verifier.handshake_output_ghash(blocks);
ghash1 + ghash2
}
fn pascal_tri<T: Field>(n: usize) -> Vec<Vec<T>> {
let mut pascal = vec![vec![T::one()]];
@@ -85,6 +115,24 @@ mod tests {
assert_eq!(ghash, ghash_expected);
}
#[test]
fn test_malicious_prover() {
let mut rng = thread_rng();
let blocks: Vec<Gf2_128> = (0..10).map(|_| Gf2_128::rand(&mut rng)).collect();
let h1: Gf2_128 = Gf2_128::rand(&mut rng);
let h2: Gf2_128 = Gf2_128::rand(&mut rng);
let h = h1 + h2;
let mut prover = MaliciousProver::new(blocks.len(), h1);
let mut verifier = Verifier::new(blocks.len(), h2);
let _ghash = ghash_with_input_zero_from_prover(&blocks, &mut prover, &mut verifier);
// Now we can extract the full MAC key from the prover's view
assert_eq!(prover.inner.d_powers[1], h);
}
#[test]
fn test_ghash_invariants() {
let mut rng = thread_rng();

View File

@@ -1,6 +1,7 @@
use super::pascal_tri;
use crate::func::ole::Ole;
use crate::func::Role;
use delegate::delegate;
use mpz_share_conversion_core::{
fields::{compute_product_repeated, gf2_128::Gf2_128, UniformRand},
Field,
@@ -75,3 +76,31 @@ impl Prover {
res
}
}
pub struct MaliciousProver {
pub inner: Prover,
}
impl MaliciousProver {
/// Create a new malicious prover, which wraps an inner prover, but sets r1 to 0.
pub fn new(block_num: usize, h1: Gf2_128) -> Self {
let mut prover = Self {
inner: Prover::new(block_num, h1),
};
prover.inner.r1 = Gf2_128::zero();
prover
}
delegate! {
to self.inner {
pub fn preprocess_ole_input(&self, ole: &mut Ole<Gf2_128>);
pub fn preprocess_ole_output(&mut self, ole: &mut Ole<Gf2_128>);
pub fn handshake_a_open_d(&self) -> Gf2_128;
pub fn handshake_a_set_di(&mut self, d: Gf2_128);
pub fn handshake_a_set_hi(&mut self);
pub fn handshake_output_ghash(&self, blocks: &[Gf2_128]) -> Gf2_128;
}
}
}