Skip to content
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

EIP4844: Suggestion to remove ssz from the Fiat-Shamir function #3026

Closed
kevaundray opened this issue Oct 5, 2022 · 7 comments
Closed

EIP4844: Suggestion to remove ssz from the Fiat-Shamir function #3026

kevaundray opened this issue Oct 5, 2022 · 7 comments
Labels
Deneb was called: eip-4844

Comments

@kevaundray
Copy link
Contributor

The method to create Fiat-Shamir challenges looks like:

def hash_to_bls_field(x: Container) -> BLSFieldElement:
    """
    Compute 32-byte hash of serialized container and convert it to BLS field.
    The output is not uniform over the BLS field.
    """
    return bytes_to_bls_field(hash(ssz_serialize(x)))

For security, the Fiat-Shamir protocol requires a bijection from an object to bytes. This is the case if the serialise methods on an ssz struct is setup correctly since ssz was intended to be bijective.

This however indirectly ties the security of the commitment scheme to the ssz serialisation strategy, ie its not possible to test the Fiat-Shamir component entirely in the cryptography library without first assuming that the serialisation strategy that caller is using is bijective (The cryptography would only receive bytes). This seems to be an abstraction leak.

To keep the cryptography completely modularised, one could implement this function as:

def hash_to_bls_field(polys: List[Tuple[Polynomial | Blob]], comms: List[KZGCommitment]) -> BLSFieldElement:
   """
   Compute 32-byte hash of serialised polynomials and commitments concatenated
   This hash is then converted to a BLS field.
   The output is not uniform over the BLS field.
   """
   
   bytes = []
   
   # Append each polynomial
   for poly in polys:
       for serialised_evaluation in poly:
           bytes.extend(serialised_evaluation)
   
   # Append serialised g1 points
   for serialised_comm in comms:
       bytes.extend(serialised_comm)
       
   return bytes_to_bls_field(hash(bytes))

The cryptography already knows how to de/serialise field and group elements, so the hash_to_bls_field can live in the cryptography code and tested in isolation.

Changes implied

Instead of:

hash_to_bls_field(BlobsAndCommitments(blobs=blobs, kzg_commitments=kzg_commitments))
hash_to_bls_field(PolynomialAndCommitment(polynomial=aggregated_poly,kzg_commitment=aggregated_poly_commitment)

It would be called as:

hash_to_bls_field(blobs, kzg_commitments)
hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment])

@hwwhww and @asn-d6 The ssz addition seems to have been introduced by you folks, If this change seems reasonable, I can push a PR. Eager to hear your thoughts.

@asn-d6
Copy link
Contributor

asn-d6 commented Oct 5, 2022

Hello,

You are effectively saying that you don't trust that ssz_serialize() is a bijective function. And that instead we should handle the Fiat-Shamir in the crypto library where we have more control.

I think that's a reasonable defense in-depth argument given what's at stake. I also think your pseudocode for hash_to_bls_field() looks reasonable, but it will probably require modifications to run.

I guess the counter argument for this is that the crypto library does not know that Fiat-Shamir is used above it. It only exposes a bytes_to_bls_field() func, and it's the responsibility of the caller to use that correctly for her agenda. In this case the caller's choice of using ssz_serialize() might be a reasonable decision. Why does the crypto library need to test the Fiat-Shamir functionality, since it doesn't expose such a function?

All in all, I think a patch for this would be a reasonable improvement.

@dankrad
Copy link
Contributor

dankrad commented Oct 5, 2022

Why does it need to be bijective? An injective function would be enough, right?

I think it is fairly easy to prove that SSZ is injective

@kevaundray
Copy link
Contributor Author

Why does it need to be bijective? An injective function would be enough, right?

I think it is fairly easy to prove that SSZ is injective

Right, but this dependency on ssz is not necessary and doesn't seem to provide any advantages, since the cryptography library is able to handle the Fiat-Shamir protocol internally.

Should something ever change with the way clients implement the necessary methods on a user defined struct for ssz, the cryptography will not need to be re-analysed, for example.

I don't know how likely that example is, but if we can avoid the dependency, I see no reason not to?

@kevaundray
Copy link
Contributor Author

Hello,

You are effectively saying that you don't trust that ssz_serialize() is a bijective function. And that instead we should handle the Fiat-Shamir in the crypto library where we have more control.

I think that's a reasonable defense in-depth argument given what's at stake. I also think your pseudocode for hash_to_bls_field() looks reasonable, but it will probably require modifications to run.

I guess the counter argument for this is that the crypto library does not know that Fiat-Shamir is used above it. It only exposes a bytes_to_bls_field() func, and it's the responsibility of the caller to use that correctly for her agenda. In this case the caller's choice of using ssz_serialize() might be a reasonable decision. Why does the crypto library need to test the Fiat-Shamir functionality, since it doesn't expose such a function?

All in all, I think a patch for this would be a reasonable improvement.

Good point, I find testing and modularising the Fiat-Shamir protocol hardens the code and makes it easier to reason about security.

An example of what I was referring to can be seen here:

https://github.com/crate-crypto/proto-danksharding-crypto/blob/master/crypto/src/kzg/transcript.rs#L46

So the Fiat-Shamir protocol is encapsulated in this Transcript struct which allows you to add polynomials and points.

I tend to do it this way because the Fiat-Shamir protocol usually has its own set of recommended practices such as domain separators, so this isolates it even further.

Not relevant to this issue, but domain separator usage can be seen here for example: https://github.com/zcash/halo2/blob/main/halo2_proofs/src/transcript.rs#L140

If the Fiat-Shamir protocol ever needs changing, the code for kzg can stay exactly the same and we just modify the transcript file.

@dankrad
Copy link
Contributor

dankrad commented Oct 5, 2022

Should something ever change with the way clients implement the necessary methods on a user defined struct for ssz, the cryptography will not need to be re-analysed, for example.

Right, but I guess SSZ (which is a strict dependency of Ethereum) would also be fundamentally broken if SSZ were not injective. So from my point of view this does not introduce any new assumptions.

@kevaundray
Copy link
Contributor Author

Should something ever change with the way clients implement the necessary methods on a user defined struct for ssz, the cryptography will not need to be re-analysed, for example.

Right, but I guess SSZ (which is a strict dependency of Ethereum) would also be fundamentally broken if SSZ were not injective. So from my point of view this does not introduce any new assumptions.

Yep, though it would still be an unnecessary abstraction leak into the cryptography module.

I think it's advantageous to not have the cryptography rely on any extraneous assumptions. I linked some code above to show how one can encapsulate the Fiat-Shamir protocol if this extra assumption is removed.

In terms of conventions, I think using ssz or some other objective function for Fiat-Shamir is more out of the norm than using the serialisation format that comes with points and field elements, see the halo2 impl I linked above

@kevaundray
Copy link
Contributor Author

Closing as #3030 and #3038 have been merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Deneb was called: eip-4844
Projects
None yet
Development

No branches or pull requests

4 participants