-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fake user Inclusion Proof verified in contract #9
Comments
Another example: random username hashes added at the last rows from 131066 to 131071 become valid witnesses with 0 balances. POC
- *cell = Scheme::Scalar::random(&mut rng);
+ *cell = Scheme::Scalar::from(97);
// @audit user_index can be any value in [131066..131072]
let user_index = 131071;
let challenge = omega.pow_vartime([user_index as u64]);
let user_values = [Fp::from(97), Fp::zero(), Fp::zero()];
let column_range = 0..N_CURRENCIES + 1;
let mut inclusion_proof: Vec<Vec<u8>> = Vec::new();
for column_index in column_range {
let f_poly = advice_polys.advice_polys.get(column_index).unwrap();
let z = if column_index == 0 {
Fp::from(97)
// big_uint_to_fp(entries[user_index as usize].username_as_big_uint())
} else {
Fp::zero()
// big_uint_to_fp(&entries[user_index as usize].balances()[column_index - 1])
};
cd ./prover
cargo run generate_commitment_and_proofs RecommendationI suggest to change the username hash column to an unblinded advice column and regard - let username = meta.advice_column();
+ let username = meta.unblind_advice_column(); |
If these two conditions hold in-circuit:
Doesn't that eliminate this attack? |
Thank you for considering it. I agree that these two conditions are already satisfied by this snippet. I would like to point out that a blinding row |
There are assumptions in this issue:
As per your description of this issue, I agree that the fake users' proof can be verified as valid in the contract. However, the assumptions might not actually hold because the prover has no motivation to generate fake proofs in the current implementation. But, as you pointed out in the case of 'general application', Contrary to your concern, I believe that indistinguishability helps protect sensitive information about the custodian, specifically the number of customers existing in the CEX. For example, let’s assume there is a CEX generating a commitment with K=20 param, but their actual user base is slight more than Thus, while your recommendation is a good optional feature for general applications based on Summa B that aim to more explicitly show the existence of users and non-users in the future, the indistinguishability provided by the blinding factor currently helps to protect sensitive information within the general scope of Summa B. |
participants: @qpzm, @rkdud007
Context
We managed to generate fake inclusion proof of a non-existing user, the user id is out of the bounds of the original CSV file. As all the balance cells’ values are zero, it might not be a critical issue in the CEX use case of proof of liability, but this becomes critical issue when Summa’s core logic is utilized in more general application use cases that inclusion itself plays an important role.
The intended behavior of the blind/unblind advice column
user_name
is a blind advice column, which is the original implementation of the advice column. However,balance_i
columns are defined as an unblind advice column which is implemented in halo2 in this commit.As can be seen, both the blind column and unblind column share the same$2^{K}$ - N_USER rows of both user_name and balance_i columns are considered unusable rows.
region.assign_advice
method to fill in the values in the table. Unlike the blind column, unblind keeps the&advice_values[unusable_rows_start..]
in theScalar::ZERO
value, which is described in this line. And as we use a fixed column from range_check, basicallyMeaning, to visualize commitments computation to advice column polynomials step, it would look like below :
This case, it will not be problematic in checking total liability as this only verifies via the sum of balances, but for a small amount of possibility that corresponds with hash collision, there might be a change that someone asks for inclusion proof.
Commit with KZG not using blind column
As checked above, both blind/unblind columns pass an additional parameter
Blind
which blind set as a random value, and unblind set as zero.However, if we go into the
commit_lagrange
function which is actually expected to utilize this param to compute commitment, it comments out the value and does not use it anywhere.Commit with KZG:
It’s different behavior from the IPA commitment version.
Commit with IPA :
To sum up, we can now think this is how the table looks like:
And$2^{K}$ - N_USER index can generate fake inclusion proof of user_name, balance_i all set in 0 value.
PoC
We did a PoC with this commit to generate a non-existing user’s inclusion proof and check if it passed the verification of InclusionVerifier.
Basically
gen_commit_and_proof.rs
binary generates fake inclusion proof call data file of user index 18. Note that csv file contains only 16 lists of users.Run with command, contract verifies the fake proof file as valid :
The text was updated successfully, but these errors were encountered: