Giter VIP home page Giter VIP logo

zk-nullifier-sig's Introduction

PLUME: Verifiably Deterministic Signatures on ECDSA

This repository provides libraries for the construction of deterministic nullifiers on Ethereum keys, ERC 7524. We call them Privately Linked Unique Message Entities (or PLUMEs). PLUMEs enable zk voting, anonymous proof of solvency, and anonymous message board moderation to be possible with Ethereum keys directly, and so we think it is a critical primitive to push forward blockchain adoption. To understand how this primitive works and the reason for design decisions, we recommend checking out our blog post.

We hope that wallets integrate the javascript, rust, or C repositories for both software and hardware signature generation, and dapps integrate the zk proof in the circuits/ directory.

Installation

To install our npm package for JS/TS, do

yarn add plume-sig

To install our Cargo package for Rust, do

cargo add plume_rustcrypto

Docs and usage guides are linked to from the packages.

Contributions and Grants

If you would like to get a grant to create PLUME applications or improve the library, we have grants available from Ethereum Foundation PSE and Gitcoin Grants, and would give grants for any PRs to the repository! There are projects ideas both below in the README, as well as bountied every issue in Github has a $50 bounty on it. Feel free to pick one up, and dmย us on Twitter/Telegram (@yush_g) for guidance and help, or join the discussion in the public channel in the PSE Discord for progress updates and community questions! This work was generously funded and supported by 0xPARC, Gitcoin donors, and EF PSE, and exists only due to the valuable work by contributors to this Github such as yush_g, Oren Yomtov, Richard Liu, Blake M Scurr, Piotr Roslaniec, Vu Voth, Weijie Koh, and Vivek Bhupatiraju who directly contributed to the code. Thanks to Poseidon Labs for a V2 proposal and Weiking Chen for his filed issues, and our auditors (0xbok), as well as all of the folks acknowledged in the research paper and blog post.

If you'd like to contribute, we offer $50 bounties in Eth/DAI for resolving any of the bugs in our issues! Each of them is quite small. That includes #28, #24, #14, and #13.

Implementations

  • rust-k256: Rust, using the k256 library
  • rust-arkworks: Rust, using arkworks
  • javascript: JavaScript, using MIRACL

Wallet Implementations

  • Mina: Uses it for nullifiers in their code here and here. They use Poseidon for the hash function instead, which makes it slower to generate in hardware wallets, but faster to prove. Their docs for this scheme are here.
  • Taho: We have an open PR that we are waiting on them to merge!
  • Rabby: We have an open PR that we are waiting on them to merge!
  • Metamask: We have an open PR set (rpc, api, core) that we are waiting on them to merge! Snaps dropped support for secret key access so a Metamask Snap is no longer a tenable path, although we did have a snap as well.
  • Aztec: WIP, pending implementation in Noir.
  • Ledger: This app compiles and generates PLUME signatures on embedded hardware and works on Ledgers. Test via the Ledger app builder.
  • ZK Snap: The "holy grail of private voting", according to Ameen, co-author of the private voting report. Uses PLUME as a core component of an end-to-end private voting system.

Audits

We have been audited by PSE Security for these three implementations V1 and V2 implementations, as well as for V1 circuits in circom. We expect the halo2 circuits to be runnable on mobile (once we have audited that code circa ~April and put up a recursive proving infrastructure setup).

Testing the circom circuit

First, clone this repository and navigate to the javascript/ directory.

Install dependencies:

pnpm i

If you encounter an error No prebuilt binaries found, try switching to node v18.17.0 (using n, for example) to work around our dependency's build issue.

Then, navigate to the circuits/ directory and install the dependencies there:

pnpm i

Run the tests:

pnpm run flatten-deps && \
pnpm run test

Be prepared to wait around 20-40 minutes for the tests to complete.

Open Work

We invite contributors to collaborate on this effort. There are great tasks for beginners (the issues), a halo2 intermediate level (circuits), cryptography intermediate level (the v1 improvement to make it v2 compatible below), and on the application layer (building apps that use PLUME).

  • Create a V3
    • Reduce number of arguments to c in V1 via Wei Dai's + Poseidons suggestions (potentially just g^sk, h[m, pk], g^r is fine) that are currently used in the V2, and write a proof in the Algebraic Group Model for the change.
  • [$500 Bounty] Fix stealthdrop MVP, the first anonymous airdrop to any Ethereum keys via PLUMEs -- repo and slides.
  • [$500 Bounty] Implement ZK voting via PLUMEs, as described in Poseidons proposal.
  • [$500 bounty] Implement the ZK circuits in Noir to integrate them into Aztec.

Resources

Paper

Thesis [most up to date version]: https://aayushg.com/thesis.pdf
Paper [slightly out of date]: https://eprint.iacr.org/2022/1255

Slides

http://slides.plume.run

Blog Post

blog.aayushg.com/nullifier

This describes the construction as well as explains our choices for the various hash/hash-to-curve functions.

ERC 7524

Official ERC: erc.plume.run

Discussion

ERC 7524 Taho Wallet Integration

Demo

https://nullifier.xyz

Talk

https://www.youtube.com/watch?v=6ajBnMdJGoY

Circom Proof Data

For the V1, See this PR.
6.5 million constraints. Mostly dominated by EC operations, but the hashes are very expensive too.

sha256 ~1.5M. hash_to_curve ~0.5M. a/b^c ~1.5 each (this is the sub circuit for the first 2 verification equations). the remaining 1.5M is probably dominated by calculating g^s and h^s.

For the V2, the sha256 is 0 cost in the circuit, but is added to the verification cost. This takes in-circuit constraints down to 5M and adds the sha to the verification.

Hash to Curve Circom Code and Explainer

https://github.com/geometryresearch/secp256k1_hash_to_curve/ https://geometry.dev/notebook/Hashing-to-the-secp256k1-Elliptic-Curve

Nullifier Calculation Spec

https://hackmd.io/uZQbMHrVSbOHvoI_HrJJlw

Circom Verification Spec

https://hackmd.io/VsojkopuSMuEA4vkYKSB8g?edit

V2 Spec and Discussion

notion.so/mantanetwork/PLUME-Discussion-6f4b7e7cf63e4e33976f6e697bf349ff

This includes some discussion on justifications for the V2 signature calculation, as well as concrete ways to use PLUME proofs + Proof of ECDSA to do nullifiers and voting respectively.

zk-nullifier-sig's People

Contributors

0xmad avatar blakemscurr avatar dependabot[bot] avatar divide-by-0 avatar orenyomtov avatar rajeshrk18 avatar rrrliu avatar skaunov avatar vuvoth avatar weijiekoh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

zk-nullifier-sig's Issues

Introduce DST specific for the protocol!

Current used DST is taken from the example, so it will collide with other projects which didn't introduce their own DST, which defies its purpose. I see it as quite a priority since if it won't be done until people start to use the thing it will be quite painful to change as it's not backward compatible in no way.

On the other hand there's quite an amount of tests alignment and small modifications due to change of the DST to proper one. Though not a horrific amount.

So the choice is better be done once and never changed, so it worth to put some effort in it. While it should be done in reasonable time. Obvious step is to start the string with "PLUME", and maybe it would be enough to be aligned with usual string, maybe some more information is nice to put there. Too long string bring small burden, btw.

PS Sorry for brevity, am writing in hurry; hope to edit for better readability, or clarify anything in discussion.

Are bad/malicious inputs tested?

I didn't check, but it seems to me that cases when c is zero, or EC points are at infinity aren't covered by tests, and in couple of recent PRs such tests would be helpful. I guess there also maybe such important inputs which would be good to test.

(Super cool would be to have a file of test vectors.)

SHA-512 in `rust-arkworks`

I noticed that both c are produced with SHA-256 in <./javascript>. Is it ok to that crate to do it with SHA-512?

autotest skips <circuits>

Two possible solutions were mentioned. Both require some experience/research to implement.

Replace Jest with cargo-test for ?

Is there any specific in that test suit which won't work better in Rust? I guess circom crate can be just a dev dependency there (instead of external call), which potentially might enable tests parallelization. Also there's small chance of running it in GitHub action that way (though I guess it would hit some bottleneck along the way).

circom-tester

#24 (comment)

320 bytes used to store Secp256k1 coordinate

A point $(x,y)$ on Secp256k1 curve is of 64 bytes in its uncompressed form (32 byte for each coordinate).

hash_to_curve.rs#L45-L62 uses 320 bytes for each coordinate. Arkworks uses 40 bytes to store a coordinate.

Recommendation:
Although the test passes, you can use 40 bytes instead of 320:

-let num_field_bytes = 320;
+let num_field_bytes = 40;

Different implementations use sha256 or sha512

Circom and js use sha256.
Rust implementations use sha512.

So these implementations are not compatible.

I suggest passing all these implementations through a common test to ensure consistency.

`tests` in <./rust-k256> are confusing

Tests in rust_k256 use the same function while producing test data as the function they test. So actually they test wrapping (which is useful too), but c_sha256_vec_signal is left untested in fact.

prevention of PK recovery with two signatures on the same message

          I totally trust you just trying to understand.

Deterministic as "to know c beforehand of signing"; or is it just the fact that V2 wouldn't work since it lacks the point $r$ value? Or something else?

I mean I kind of don't see yet the essential difference if signer adds to the message point $r$ instead of the info/data you mentioned. ๐Ÿค”

Originally posted by @skaunov in #98 (comment)

`sha256_preimage_bit_length` is a free signal

verify_nullifier.circom#L33

Prover is free to choose any value forsha256_preimage_bit_length to generate the sha256 hash for c. Since the length of the hash pre-image is fixed, it can be removed as an input signal. The TODO comment indicates this too:

// ...TODO: calculate internally in circom to simplify API
signal input sha256_preimage_bit_length;

Recommendation: sha256_preimage_bit_length should always be equal to message_bits (6*33*8).

<./rust-arkworks> is over generalized

The crate is quite complex and I fail to see any reason behind it. It offers a complex trait, but its type system requires further development to be really useful. (And error handling isn't well-compatible with other crates.) It's very generic over curves and its generators, but the only curve other implementations support is deprecated, and I can't find a case when another curve would be plugged into it.

I well might be just fail to see the big idea though. @weijiekoh , could you explain these since I struggled to pick-up the reasons from code but it doesn't add up well in my mind. =(

My current proposal is to ditch the defined trait, simplify few places, and decide on the level of generality. If we don't expect no other curves for PLUME in foreseeable future then further simplify to make it concrete, if do expect then [try] to preserve this part.
[try]: deprecation of the curve definition makes this more a grounding and reference work (than just use) until the whole thing isn't maintained to be compatible with current arkworks version

Add `sign` method to <./rust-k256>

Seems like <./rust-k256> designed only for verification of a signature, as there's no ready outlet to pub which could sign a message. Should it be so, or does it just lacking it?

`SecretKeyMaterial` is handled recklessly in <./rust-arkworks>

It's yet named SecretKey, oncoming PR renames it to not give false impression of security.

here arkworks should be checked for proper methods for keys handling
at least zeroize should be applied
also would be nice to check that proper RNG is enforced

alternative security proof

Just to add, there is a quick way to prove the PLUME security, in case anyone asks.

This is the GDH undeniable signature with the confirmation protocol replaced with NIZK, and here the NIZK is a classical Chaum-Pedersen protocol.

The GDH undeniable signature can be found here: Tatsuaki Okamoto and David Pointcheval. The gap-problems: A new class of problems for the security of cryptographic schemes. In PKC โ€™01

This is also discussed in the BLS signature paper. Section 2.2.

Uniqueness comes from hashing to the curve.

Add tests for wrapping `c` over $p$

It might be a RustCrypto thing which just panics on certain methods when bytes yields the value larger than $p$, but it's still a worthy case to have in the suite across implementation to be sure that wrapping is done correctly, and that signatures equality can be facilitated.

Differential test to verify all implementations

It's important to have consistency across these impls. A few examples:

  • sha256 in js, circom vs sha512 in rust.
  • c is returned as a plain number in js, circom vs a field element in rust.
  • More issues may be uncovered, like encoding/decoding across different formats.

You should run a differential test on random values for message and private key (maybe pre-generate and freeze them).

unnecessity of indifferentiability

I am recently reading into the PLUME design and the use of Geometry's map. Note that Geometry's map was designed for a different purpose. If we target at making a nullifier, there is at least one trick that we can use.

Note that for provable indifferentiability, Geometry's map does hashing to curves twice and adds the results together. This is not necessary if we use the signature as the nullifier because you don't need to reveal the signature (see #11, I am referring to the GDH undeniable signature, the signature part), and to hide the signature, just hash the final result.

This ideally should be able to reduce the cost by half (given that clearing the cofactor is not necessary for secp256k1).

Unit tests would help reference implementation readability

It's kind of #72 (comment), but letting moving forward meanwhile.

I added a test which should be showing that hashing to curve isn't correct (at least on signing; before #84 ). As there's many conversions and different formats/endings the test isn't super readable, so it's quite probable I just messed up along the way. This is quite easy to check if anybody would add a hash_to_curve test which a current implementation would pass.

Anyway this/such test is a good contribution to the code. Mine was born when my implementation yielded a signature (V1) different from the current one using the same inputs which correctness I double-checked. (Yep, it's quite probable I messed up implementation and that test; it's enough to have just two errors for this. On the other hand it's god enough signal to dig into this.)

Refactor `CryptoError`

At ark crate it's used quite suboptimal now, also see branch:43 for a further suggestion.

Crates API and documentation

Both crates basically lacks documentation, and <./rust-k256> lacks API choices.

Also their name are ...temporary.

PS It would be nice to think about traits used and reexported so that it would not clash with versions that downstream use. Though most likely Cargo will do its job on it, just it's better to be sure.
This one is more about releasing the crates when things will come to it.

Error handling in _rust_k256_

fn encode_pt(point: ProjectivePoint) -> Result<Vec<u8>, Error> always returns Ok(..) currently. Should be analyzed to either introduce error handling or made it infallible.

Refactor `verify_signals`

In rust_k256 crate this fn seems to be fundamental. I'd make it pub, redo some internals (at least better separate computed and input values), and got rid of println! which are suitable for a bin crate, not for a lib.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.