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

Add ERC: PLUME Signature in Wallets #37

Closed
wants to merge 14 commits into from
211 changes: 211 additions & 0 deletions ERCS/erc-7524.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
eip: 7524
title: PLUME Signature in Wallets
description: A new signature scheme for Ethereum keypairs that allows for "nullifiers" to enable unique anonymity and zk voting.
author: Yush G (@Divide-By-0) <[email protected]>, Kobi Gurkan (@kobigurk), Richard Liu (@rrrliu), Vivek Bhupatiraju (@vb7401), Barry Whitehat (@barryWhiteHat)
discussions-to: https://ethereum-magicians.org/t/erc-7524-plume-signature-in-wallets/15902
status: Draft
type: Standards Track
category: ERC
created: 2023-09-24
---

## Abstract

ZK-SNARKs have enabled ideation for new identity applications based on anonymous proof-of-ownership. One of the primary technologies that would enable the jump from existing apps to systems that require anonymous uniqueness is the development of verifiably deterministic signatures. Because we are on ECDSA, there is no way right now for someone to verify that a signature is generated deterministically, even with ‘deterministic’ ECDSA signatures: a ZK-SNARK proof would need someone’s private key to do so, and some hardware wallets do not even allow viewing of a private key. Broadly, we don’t want to export/copy-paste the private key into a SNARK to be an intended user behavior, and most hardware wallets will not be able to run SNARK arithmetization inside a secure enclave for existing schemes (and nor do we want to standardize an entire proof system inside a wallet right now when they emerge and evolve almost every year). Thus we are left to select a new algorithm.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ZK-SNARKs have enabled ideation for new identity applications based on anonymous proof-of-ownership. One of the primary technologies that would enable the jump from existing apps to systems that require anonymous uniqueness is the development of verifiably deterministic signatures. Because we are on ECDSA, there is no way right now for someone to verify that a signature is generated deterministically, even with ‘deterministic’ ECDSA signatures: a ZK-SNARK proof would need someone’s private key to do so, and some hardware wallets do not even allow viewing of a private key. Broadly, we don’t want to export/copy-paste the private key into a SNARK to be an intended user behavior, and most hardware wallets will not be able to run SNARK arithmetization inside a secure enclave for existing schemes (and nor do we want to standardize an entire proof system inside a wallet right now when they emerge and evolve almost every year). Thus we are left to select a new algorithm.
ZK-SNARKs have enabled ideation for new identity applications based on anonymous proof-of-ownership. One of the primary technologies that would enable the jump from existing apps to systems that require anonymous uniqueness is the development of verifiably deterministic signatures. Because Ethereum is based on ECDSA, there is no way right now for someone to verify that a signature is generated deterministically, even with ‘deterministic’ ECDSA signatures: a ZK-SNARK proof would need someone’s private key to do so, and some hardware wallets do not even allow viewing of a private key. Broadly, we don’t want to export/copy-paste the private key into a SNARK to be an intended user behavior, and most hardware wallets will not be able to run SNARK arithmetization inside a secure enclave for existing schemes (and nor do we want to standardize an entire proof system inside a wallet right now when they emerge and evolve almost every year). Thus we are left to select a new algorithm.


One specific example of how such a signature can lead to unique pseudonymity is that we prove it was generated correctly in a ZK-SNARK that only reveals publicly the hash(signature), and the SNARK additionally proves some property the public key has (i.e. is in some anonymity set, has executed some set of actions on chain, etc). This proof is the only thing that is ever seen by other people, and so the hash(signature) can be used as a “nullifier”: a public commitment to a specific anonymous account, to forbid actions like double spending, or allow a consistent identity between anonymous actions. We aim to standardize a new verifiably deterministic signature algorithm that both uniquely identifies the keypair, and keeps the account identity secret, where verification does not require a secret key. The specific signature function is $hash(message, public\ key) ^ {secret\ key}$.

## Motivation

- Existing ZK applications have the advantage that there is no uniqueness constraint on the provers: that is, allowing the same wallet to prove itself as a member more than once is intended. However, many applications require a maximum of one action per user, especially protocols that desire Sybil resistance. Such protocols are not natively possible on Ethereum right now without mapping each address into an opt-in mapping that also maps a user’s private key to a new system, which adds complexity, loses atomicity, and does not benefit from the rich on-chain history of Ethereum accounts.
- Specific applications that require this tech include:
- zk voting, where each account in some set has one vote
- pseudonymously claiming an airdrop like Stealthdrop
- moderating a pseudonymous forum, where people can prove that they are the same identity elsewhere in the forum
- zk proof of solvency — if you want two exchanges to prove they know a set of private keys that hold some balance, you need a way to ensure that two exchanges aren’t both claiming the same address, while keeping it private

As such, a deterministic value based on the Ethereum account’s ECDSA keypair is a necessary component of ensuring one action per user and enables all these applications on Ethereum.


## Specification

We propose a new signature standard that offers the following properties, to be implemented for standard ECDSA keys within wallets:

1. It produces signatures that contain a deterministic component and a nondeterministic component. The deterministic component may be used as a *nullifier*.
2. Signers can use existing secpk256k1 keypairs, such as those in hardware wallets that support Ethereum accounts. As a consequence, secret keys can remain in secure enclaves if there is a generator point multiplication API into the enclave (which Ledger for instance has).

### Parameters

This scheme uses the secp256k1 curve, defined in SEC 2: Recommended Elliptic Curve Domain Parameters v2, page 9.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't permit external links (except as documented in EIP-1.)

This particular PDF has a very permissive license, so I'd recommend copying it into your assets directory (../assets/erc-7542/) and linking to it there.

Copy link
Contributor Author

@Divide-By-0 Divide-By-0 Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to change erc > eip to avoid error. Filed an issue: #243

Error for context:

* At ./_site/EIPS/eip-7524.html:252:

  internally linking to ../assets/erc-7524/sec2-v2.pdf, which does not exist

* At ./_site/EIPS/eip-7524.html:281:

  internally linking to ../assets/erc-7524/sec1-v2.pdf, which does not exist

I get this issue from HTMLProofer when referring to the erc-x folder.


We use the following notation to refer to the parameters of this curve:

- $g$: the base point (also called the generator) of the curve.
- $p$: the order of the curve.
- $F_p$: the finite field whose order is $p$.

Note we use exponential notation to denote elliptic curve scalar multiplications.

### Public key encoding functions

### SEC1

This scheme uses the SEC1 elliptic curve point encoding scheme defined in SEC 1: Elliptic Curve Cryptography v2 . Point compression is used. We use the notation $\mathsf{sec1}(pk)$ to denote the compressed encoding of secp256k1 curve point $pk$ as a bytestring of length 33.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, please put a copy of this PDF in your assets directory.


### Hash functions

**SHA256**

This scheme uses the SHA256 hash function defined in IETF RFC4634.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do allow links to RFCs:

Suggested change
This scheme uses the SHA256 hash function defined in IETF RFC4634.
This scheme uses the SHA256 hash function defined in [RFC 4634](https://www.rfc-editor.org/rfc/rfc4634).


In this document, we use the notation $\mathsf{sha256}(a_1,.. a_n)$ to denote the sha256 digest of the concatentation of $n$ values $a_1, ..., a_n$. The digest should then be interpreted as a big-endian value in the secp256k1 scalar field.

### Hash-to-curve

We use the notation $\mathsf{htc}([a_1, ..., a_n])$ to denote the elliptic curve point which is the result of the `secp256k1_XMD:SHA-256_SSWU_RO_ (IETF Draft draft-irtf-cfrg-hash-to-curve-16 Appendix J.8.1)` hash-to-curve algorithm over the concatentation of $n$ values $a_1, ..., a_n$.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this reference be replaced with https://www.rfc-editor.org/rfc/rfc9380?


### Key generation

A *keypair* comprises of $(sk, pk)$, defined as such:

- $sk$: The user's secret key, which is a cryptographically secure random scalar in the field $F_p$.
- $pk$: The user's public key, defined as $g^{sk}$, which is a point on the secp256k1 curve.

### Signature generation

This scheme builds upon the Chaum-Pedersen signature scheme. Given a 32-byte message $m$ and a keypair $(sk, pk)$, a user may generate a signature as such:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a good idea to cite the original paper. I think this is the correct one, but I'm terrible at finding academic papers, so please confirm.

Suggested change
This scheme builds upon the Chaum-Pedersen signature scheme. Given a 32-byte message $m$ and a keypair $(sk, pk)$, a user may generate a signature as such:
This scheme builds upon the Chaum-Pedersen signature scheme. [^1] Given a 32-byte message $m$ and a keypair $(sk, pk)$, a user may generate a signature as such:
[^1]:
```csl-json
{
"DOI": "10.1007/3-540-48071-4_7",
"URL": "https://link.springer.com/content/pdf/10.1007/3-540-48071-4_7.pdf",
"publisher-place": "Berlin, Heidelberg",
"author": [
{
"given": "David",
"family": "Chaum"
},
{
"given": "Torben Pryds",
"family": "Pedersen"
}
],
"container-title": "Advances in Cryptology — CRYPTO' 92",
"editor": [
{
"given": "Ernest F.",
"family": "Brickell"
}
],
"type": "paper-conference",
"id": "10.1007/3-540-48071-4_7",
"citation-label": "10.1007/3-540-48071-4_7",
"ISBN": "978-3-540-48071-6",
"issued": {
"date-parts": [
[
1993
]
]
},
"page": "89-105",
"publisher": "Springer Berlin Heidelberg",
"title": "Wallet Databases with Observers"
}
```


1. Pick a random $r$ from $F_p$.
2. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
3. Compute $z = h ^ r$.
4. Compute the nullifier $\mathsf{nul} = h^{sk}$.
5. Compute $c = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z]])$.
6. Compute $s = r + sk \cdot c$.

The signature is $(z, s, g^r, c, \mathsf{nul})$.

The length of the input to $\mathsf{htc}$ is always 65 bytes.

Note that in this scheme, we compute $h$ as the hash of the message and $pk$, not the message and $r$. This is to make our scheme deterministic.

### Signature verification (non-ZK)

********************Note: Non-ZK signature verification is not part of the proposal but relevant for an intuitive understanding of the ZK signature verification.********************
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally I'd say that if something isn't part of the specification, it doesn't belong in the specification section. In this case, I don't have enough domain knowledge to say whether this is sufficiently relevant or not. Feel free to leave it in.

I would, however, recommend against using long strings of asterisks and to use something like this instead:

Suggested change
********************Note: Non-ZK signature verification is not part of the proposal but relevant for an intuitive understanding of the ZK signature verification.********************
> 📝 **Note:** This section is non-normative.
>
> Non-ZK signature verification is not part of this proposal but relevant for an intuitive understanding of the ZK signature verification.


In a situation where the verifier knows $g$, $m$, the signer's public key $pk$, and the signature $(z, s, g^r, c, \mathsf{nul})$, they may perform the following checks to determine if the signature is valid:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $c' = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z])$.
3. Reject if any of the following is false:
a. $g^{s} \cdot pk^{-c} \stackrel{?}{=} g^r$
b. $h^s \cdot \mathsf{nul}^{-c} \stackrel{?}{=} z$
c. $c \stackrel{?}{=} c'$
4. Accept if all of the above is true.

Now we move onto the ZK signature verification specs.

### Version 1: Verifier Optimized

In a situation where there is a verifier who must *not* know the signer's $pk$, but the signer must nevertheless prove that they know $sk$ corresponding to the signature given $m$, a zero-knowledge proof is required.

The following verification function may be described via a circuit as part of a non-interactive zero-knowledge proving system, such as Groth16. To create a proof, the prover supplies the following inputs:

**Public**: $\mathsf{nul}$, $c$
**Private**: $pk$, $r$, $s$, $z$, $g^r$, $hash[m, g^sk]$ (included to save constraints)

The circuit performs the following computations:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $pk = g^{sk}$.
3. Compute $c' = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z]])$.
4. Compute $g^{s} \cdot pk^{-c}$.
5. Compute $g^r$.
6. Compute $h^s \cdot \mathsf{nul}^{-c}$.

It also establishes the following constraints:

- $g^{s} \cdot pk^{-c} = g^r$
- $h^s \cdot \mathsf{nul}^{-c} = z$
- $c = c'$

### Version 2: Prover Optimized

Currently, SHA-256 hashing operations are particularly expensive with zk proofs in the browser. In the context of PLUME, the computation of $c$ is a bottleneck for efficient proof times, so one modification suggested by the Poseidon team was to move this hash computation outside the circuit, into the verifier.

To do this, we make $z$ and $g^r$ public signals in the circuit and update the definition of $c$ to $c = \text{sha256}([\text{nul}, g^r, z])$. The updated protocol is as follows.

**************Public:************** $\mathsf{nul}$, $c$, $g^r$, $z$
**************Private:************** $pk$, $r$, $s$, $hash[m, g^sk]$

The circuit performs the following computations:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $pk = g^{sk}$.
3. Compute $g^{s} \cdot pk^{-c}$.
4. Compute $g^r$.
5. Compute $h^s \cdot \mathsf{nul}^{-c}$.

The circuit establishes the following constraints:

- $g^{s} \cdot pk^{-c} = g^r$
- $h^s \cdot \mathsf{nul}^{-c} = z$

In addition to verifying the zk-SNARK, the PLUME verifier performs the following check.

$c == \text{hash}(\text{nul}, g^r, h^r)$

Due to SHA-256 being a native precompile on Ethereum, this operation will still be efficient for smart contract verifiers.

### Version 3:

There may be a more efficient V3 in the future, perhaps via removing indifferentiability from hash_to_curve.

## Rationale

We will define a few specific properties we are looking for in a candidate algorithm, then define a few other intuitive algorithms and explain why they don’t actually work.

- Noninteractivity
- The importance of noninteractivity in ZK ID systems is that it enables a large anonymity set from the start, making it resistant to sybil attacks and spam, which would be possible if there was an interactive phase. This allows for new use cases such as ZK airdrops.
- Noninteractivity enables the full set of eligible users to be part of the anonymity set, without requiring any interaction. This is possible if the zk proof can verify the set membership in the Merkle tree, the message via the signature, and the unique nullifier. Interactive nullifiers, such as tornado.cash's, require updating the anonymity set Merkle tree with each new user,
- Uniqueness
- If we want to forbid actions like double spending or double claiming, we need them to be verifiably unique per account.
- For example: Because ECDSA signatures are nondeterministic, signatures don’t suffice; we need a new deterministic function, verifiable with only the public key. We want the nullifier to be non-interactive, to uniquely identify the keypair yet keep the account identity secret.
- The key insight is that such nullifiers can be used as a public commitment to a specific anonymous account to provide us with a uniqueness guarantee.
- Deterministic
- We want each account to only generate one such signature, and generate it exactly the same over time into the future.
- Verifiable without a secret key
- In cases where signatures are nondeterministic (like ECDSA) the signature alone is not sufficient for verification.
- We want a new, deterministic function verifiable only with the public key
- We don’t want users copy-pasting secret keys anywhere, and we need to choose a function such that the enclave calculation is simple enough for hardware wallets.
- Because the nullifier is non-interactive, we are able to uniquely identify the key pair without revealing the account identity.

For a few possible simpler algorithm designs that were considered, see blog.aayushg.com > /posts/plume > ‘**One address <-> one nullifier’** section. We based the final design off of BLS signatures, Chaum-Pederson EQDL, and Goh-Jarecki’s EDL paper, but to work on secp256k1.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this external link.


## Reference Implementation

The GitHub repository `plume-sig/zk-nuliifier-sig` contains the reference implementation in several languages including Rust and Javascript. There is a sample PR to Metamask Core as well, and a PR to Taho Core incoming.
Comment on lines +185 to +187
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Reference Implementation
The GitHub repository `plume-sig/zk-nuliifier-sig` contains the reference implementation in several languages including Rust and Javascript. There is a sample PR to Metamask Core as well, and a PR to Taho Core incoming.

Either include a reference implementation here (or in your assets folder), or remove this section entirely.


## Security Considerations

There are formal proofs of this specific algorithm’s cryptography in a PLUME paper. The theory has been published, and implementations have had one internal round of audit, but they have not end-to-end been formally verified or audited yet, although empirically they correctly conform to the spec laid out. We invite folks in our discussion thread to help surface more possible ways the scheme can be misused in practice.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either cite this PLUME paper (see my earlier comment for an example; this comes in handy if you have a BIB file), or remove this external link.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposals should be written so that they make sense once they move to the Final status.

Suggested change
There are formal proofs of this specific algorithm’s cryptography in a PLUME paper. The theory has been published, and implementations have had one internal round of audit, but they have not end-to-end been formally verified or audited yet, although empirically they correctly conform to the spec laid out. We invite folks in our discussion thread to help surface more possible ways the scheme can be misused in practice.
There are formal proofs of this specific algorithm’s cryptography in a PLUME paper. The theory has been published, and implementations have had one internal round of audit, but they have not end-to-end been formally verified or audited yet, although empirically they correctly conform to the spec laid out.


**The Interactivity-Quantum Secrecy Tradeoff**

Note that in the far future, once quantum computers can break ECDSA keypair security, most Ethereum keypairs will be broken, but migration to a quantum-resistant keypair in advance will keep active funds safe. Specifically, people can merely sign messages committing to new quantum-resistant keypairs (or just higher-bit keypairs on similar algorithms), and the canonical chain can fork to make such keypairs valid. ZK-SNARKs become forgeable, but yet secret data in past proofs still cannot ever be revealed. In the best case, the chain should be able to continue without a hitch.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] but yet secret data in past proofs still cannot ever be revealed.

This bit is slightly confusing.


However, if people rely on any type of deterministic nullifier like our construction, their anonymity is immediately broken: someone can merely derive the secret keys for the whole anonymity set, calculate all the nullifiers, and see which ones match. This problem will exist for any deterministic nullifier algorithm on ECDSA, since revealing the secret key reveals the only source of “randomness” that guarantees anonymity in a deterministic protocol.

If people want to keep post-quantum secrecy of data, they have to give up at least one of our properties: the easiest one is probably non-interactivity. For example, for the zero-knowledge airdrop, each account in the anonymity set publicly signs a commitment to a new semaphore id commitment (effectively address pk publishes $hash[randomness\ |\ external\ nullifier\ |\ pk]$). Then to claim, they reveal their external nullifier and ZK prove it came from one of the semaphore ids in the anonymity set. This considerably shrinks the anonymity set to everyone who has opted in to a semaphore commitment prior to that account claiming. As a result, there probably needs to be a separate signup phase where people commit to nullifiers in order to seed the anonymity set. This interactivity requirement makes applications such as the zk airdrop or nicer tornado cash construction (in the use cases section) much harder. However, since hashes (as far as we currently know) are still hard with quantum computers, it’s unlikely that people will be able to ever de-anonymize you.

A recent approximation of $2n^2$ qubits needed to solve discrete log via quantum annealing that failed to work on larger than $n$ = 6-bit primes shows that we are likely several decades from this becoming a reality, and the $n^2$ qubits needed to solve RSA having predictions 10-40 years out suggest that it will likely take longer than that to solve discrete log.

We hope that people will choose the appropriate algorithm for their chosen point on the interactivity-quantum secrecy tradeoff for their application, and hope that including this information helps folks make the right choice for themselves. Folks prioritizing shorter-term secrecy, like DAO voting or confessions of the young who will likely no longer care when they’re old, might prioritize this document’s nullifier construction, but whistleblowers or journalists might want to consider the semaphore construction instead.

### Additional Reading

We recommend reading the original paper, the PLUME Blog Post, the PLUME Slide Deck, and the ZK Nullifer (PLUME) Presentation at ZKSummit.
Comment on lines +205 to +207
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Additional Reading
We recommend reading the original paper, the PLUME Blog Post, the PLUME Slide Deck, and the ZK Nullifer (PLUME) Presentation at ZKSummit.

Please remove this section.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aaron Thornton


## Copyright

Copyright and related rights waived via CC0.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Copyright and related rights waived via CC0.
Copyright and related rights waived via [CC0](../LICENSE.md).

Please use the exact copyright notice from the template.

Loading