Interesting, this is precisely what I’m going to be doing for my project as well! I’m building a new L1 blockchain whose smartcontracts will be compiled to WASM and their execution will be proven in Halo2 (feel free to ask me my motivations etc., I’m happy to provide more info about my project.)
What are you working on?
Yep. And I’ve gathered even more information about the matter, I’ve now learned that Schnorr provides two more important advantages over EdDSA:
- EdDSA is vulnerable to malleability attacks if care is not taken on the verifier side (see here for details). Schnorr, on the other hand, is non-malleable.
- The Schnorr scheme makes signature aggregation possible, a feature that EdDSA doesn’t have.
Besides, EdDSA is pretty much always used with Curve25519 which is somewhat worse than Pallas & Vesta in terms of entropy of the scalars (such as the private key and secret nonces). The order of the scalar field of Curve25519 is a large prime multiple of 8, meaning that in order for the whole scheme to be secure you need to perform a specific clamping procedure whenever you generate a random scalar. This clamping procedure is defined by Ed25519 and implemented e.g. here. As you can see, it zeroes the three least significant bits. Not a big deal, you still have 252 bits of entropy, but Pallas & Vesta don’t have that problem because the order of their respective scalar fields are large primes. So the two Pasta curves allow for slightly more entropy than Curve25519.
(Unfortunately I’m going to be unable to leverage this benefit in my project because I’m using mTLS for authentication which doesn’t support Schnorr or Pallas, so the private keys of my blockchain need to be usable on both curves, so my key derivation process actually performs Ed25519 clamping and loses 3 bits of entropy.)
… yes and no. I’m still working on the low-level protocol, things like authenticating the nodes, joining and leaving the network, etc. so the signatures I’m dealing with right now are not going to be verified in zero-knowledge proofs and therefore they don’t need to use the Poseidon hash. SHA3 is generally more secure and also much easier to use than Poseidon. The latter is a 128-bit hash, potentially vulnerable to post-quantum attacks, and it has different usage modes and APIs for different use cases, e.g. fixed-length messages vs. variable-length ones… I’ve tried using the halo2_poseidon
crate and it was an absolute mess.
But I am using the Schnorr scheme! So far I’ve implemented two types of signatures:
- generic signatures for protobuf messages using Schnorr over Pallas with SHA3;
- the dual-Schnorr signature scheme that I use for authenticating the nodes of the network via mTLS certificates (I discussed it in this thread but there have been developments since then, I should update it).
Both implemented here: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
Notable parts:
- Generic Schnorr-Pallas-SHA3 signing: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
- Generic Schnorr-Pallas-SHA3 verification: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
- “Dual-Schnorr” signing scheme: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
- “Dual-Schnorr” signature verification: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
- If you’re curious about certificate generation: node/src/ssl.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub
- For key derivation, since I had to do Ed25519 clamping anyway as explained above, I made a hybrid process using the
ed25519_dalek
crate as well as my own Pallas point multiplication with thepasta_curves
crate. The full process runs here: node/src/keys.rs at 25e98380d4fe258c707f06298efc25059f858199 · dotakon-mirror/node · GitHub (the Pallas point multiplication is at line 71).
This is probably not quite what you were looking for since I’m using SHA3 instead of Poseidon… (and I’m not making a Halo2 circuit out of it anyway, for now)
The lesson I’ve learned is that Poseidon is so complicated that it only makes sense inside Halo2 circuits, so the whole halo2_poseidon
crate is not really the best in terms of usefulness. When I get to the point of running WASM programs in Halo2 I’ll actually use the Poseidon implementation provided in the halo2_gadgets
crate (it’s a crate containing several reusable circuit components, such as Poseidon hashing: halo2/halo2_gadgets/src/poseidon.rs at 8056703404299dd0a1e381ecfaa780f891dfc392 · zcash/halo2 · GitHub).