Fix computation of h for the SI-86

This commit is contained in:
aniampio
2024-10-17 12:40:32 +01:00
committed by Jędrzej Stuczyński
parent 5af6ee763c
commit 871b54e314
4 changed files with 92 additions and 11 deletions
+1 -1
View File
@@ -253,7 +253,7 @@ mod tests {
let sigs = sks
.iter()
.map(|sk| sign(&params, sk, &attributes).unwrap())
.map(|sk| sign(sk, &attributes).unwrap())
.collect::<Vec<_>>();
// aggregating (any) threshold works
+17 -8
View File
@@ -453,7 +453,6 @@ pub fn verify_partial_blind_signature(
/// Creates a Coconut Signature under a given secret key on a set of public attributes only.
pub fn sign(
params: &Parameters,
secret_key: &SecretKey,
public_attributes: &[&Attribute],
) -> Result<Signature> {
@@ -464,13 +463,23 @@ pub fn sign(
});
}
// TODO: why in the python implementation this hash onto the curve is present
// while it's not used in the paper? the paper uses random exponent instead.
// (the python implementation hashes string representation of all attributes onto the curve,
// but I think the same can be achieved by just summing the attributes thus avoiding the unnecessary
// transformation. If I'm wrong, please correct me.)
let attributes_sum = public_attributes.iter().copied().sum::<Scalar>();
let h = hash_g1((params.gen1() * attributes_sum).to_bytes());
//Serialize the array structure of the public attributes into a byte array
let mut serialized_attributes = Vec::new();
//Prepend the length of the entire array (in bytes)
let array_len = public_attributes.len() as u64;
serialized_attributes.extend_from_slice(&array_len.to_le_bytes());
//Serialize each attribute with its length
for &attribute in public_attributes.iter() {
let attr_bytes = attribute.to_bytes();
let attr_len = attr_bytes.len() as u64;
// Prefix the attribute with its length
serialized_attributes.extend_from_slice(&attr_len.to_le_bytes());
serialized_attributes.extend_from_slice(&attr_bytes);
}
//Hash the resulting byte array to derive the point H
let h = hash_g1(serialized_attributes);
// x + m0 * y0 + m1 * y1 + ... mn * yn
let exponent = secret_key.x
+2 -2
View File
@@ -436,8 +436,8 @@ mod tests {
let keypair1 = keygen(&params);
let keypair2 = keygen(&params);
let sig1 = sign(&params, keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(&params, keypair2.secret_key(), &attributes).unwrap();
let sig1 = sign(keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(keypair2.secret_key(), &attributes).unwrap();
assert!(verify(
&params,
@@ -312,6 +312,7 @@ pub fn verify(
#[cfg(test)]
mod tests {
use crate::scheme::issuance::sign;
use crate::scheme::keygen::keygen;
use crate::scheme::setup::setup;
@@ -355,4 +356,75 @@ mod tests {
theta
);
}
#[test]
fn reject_forged_signature_via_linear_combination() {
// This test checks if the protocol correctly rejects forged signatures created
// by linear combinations of valid signatures. The verification for forged
// signatures should fail.
let params = Parameters::new(4).unwrap();
let scalar_2 = Scalar::one() + Scalar::one();
let scalar_2_inv = Scalar::invert(&scalar_2).unwrap();
//#1
let a = params.random_scalar();
let zero = Scalar::zero();
let a_zero = vec![&a, &zero];
let zero_a = vec![&zero, &a];
let validator_keypair = keygen(&params);
//#2
let sig_a_zero = sign(validator_keypair.secret_key(), &a_zero).unwrap();
let sig_zero_a = sign(validator_keypair.secret_key(), &zero_a).unwrap();
assert!(verify(
&params,
validator_keypair.verification_key(),
&a_zero,
&sig_a_zero
));
assert!(verify(
&params,
validator_keypair.verification_key(),
&zero_a,
&sig_zero_a
));
//#3
let h0 = sig_a_zero.0;
let h1 = &scalar_2_inv * &sig_a_zero.1 + &scalar_2_inv * &sig_zero_a.1;
let forged_signature = Signature(h0, h1);
let a_half = a * scalar_2_inv;
let new_plaintext = vec![&a_half, &a_half];
// The forged signature should not pass verification
assert!(!verify(
&params,
validator_keypair.verification_key(),
&new_plaintext,
&forged_signature
));
//#4
let scalar_3 = Scalar::one() + Scalar::one() + Scalar::one();
let scalar_4 = Scalar::one() + Scalar::one() + Scalar::one() + Scalar::one();
let scalar_4_inv = Scalar::invert(&scalar_4).unwrap();
let scalar_3_over_4 = scalar_3 * scalar_4_inv;
let h1_2 = &scalar_4_inv * &sig_a_zero.1 + &scalar_3_over_4 * &sig_zero_a.1;
let forged_signature_2 = Signature(h0, h1_2);
let a_quarter = a * scalar_4_inv;
let a_3_over_4 = a * scalar_3_over_4;
let new_plaintext_2 = vec![&a_quarter, &a_3_over_4];
// The second forged signature should also not pass verification
assert!(!verify(
&params,
validator_keypair.verification_key(),
&new_plaintext_2,
&forged_signature_2
));
}
}