chore(32-RLN): update v1 RFC (#581)

fix(32-RLN): change to stable version & rename to RLN-V1

chore(32-RLN): add SSS attack description

chore(32-RLN): PR fixes

chore(32-RLN): minor PR changes
This commit is contained in:
Magamedrasul Ibragimov 2023-03-22 14:01:21 +04:00 committed by GitHub
parent c70a47f645
commit c9052d1826
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 88 deletions

View File

@ -1,14 +1,15 @@
--- ---
slug: 32 slug: 32
title: 32/RLN title: 32/RLN-V1
name: Rate Limit Nullifier name: Rate Limit Nullifier
status: raw status: raw
editor: Blagoj Dimovski <blagoj.dimovski@yandex.com> editor: Rasul Ibragimov <curryrasul@gmail.com>
contributors: contributors:
- Barry Whitehat <barrywhitehat@protonmail.com> - Barry Whitehat <barrywhitehat@protonmail.com>
- Sanaz Taheri <sanaz@status.im> - Sanaz Taheri <sanaz@status.im>
- Oskar Thorén <oskar@status.im> - Oskar Thorén <oskar@status.im>
- Onur Kilic <onurkilic1004@gmail.com> - Onur Kilic <onurkilic1004@gmail.com>
- Blagoj Dimovski <blagoj.dimovski@yandex.com>
--- ---
# Abstract # Abstract
@ -133,14 +134,13 @@ For proof generation,
the user need to submit the following fields to the circuit: the user need to submit the following fields to the circuit:
``` ```
{ {
identity_secret: identity_secret_hash, identity_secret: identity_secret_hash,
path_elements: Merkle_proof.path_elements, path_elements: Merkle_proof.path_elements,
identity_path_index: Merkle_proof.indices, identity_path_index: Merkle_proof.indices,
x: signal_hash, x: signal_hash,
epoch: epoch, external_nullifier: external_nullifier
rln_identifier: rln_identifier }
}
``` ```
@ -155,8 +155,7 @@ The following fields are needed for proof output calculation:
``` ```
{ {
identity_secret_hash: bigint, identity_secret_hash: bigint,
epoch: bigint, external_nullifier: bigint,
rln_identifier: bigint,
x: bigint, x: bigint,
} }
``` ```
@ -164,8 +163,6 @@ The following fields are needed for proof output calculation:
The output `[y, internal_nullifier]` is calculated in the following way: The output `[y, internal_nullifier]` is calculated in the following way:
``` ```
external_nullifier = poseidonHash([epoch, rln_identifier])
a_0 = identity_secret_hash a_0 = identity_secret_hash
a_1 = poseidonHash([a0, external_nullifier]) a_1 = poseidonHash([a0, external_nullifier])
@ -196,10 +193,10 @@ Additionally depending on the application,
the following fields might be required: the following fields might be required:
``` ```
{ {
root: Merkle_proof.root, root: Merkle_proof.root,
epoch: epoch epoch: epoch
} }
``` ```
@ -265,8 +262,7 @@ The `zk_proof` should be verified by providing the `zk_proof` field to the circu
Merkle_proof.root, Merkle_proof.root,
internal_nullifier, internal_nullifier,
x, # signal_hash x, # signal_hash
epoch, external_nullifier
rln_identifier
] ]
``` ```
@ -345,15 +341,14 @@ using the [circomlib](https://docs.circom.io/) library.
### System parameters ### System parameters
- `n_levels` - Merkle tree depth - `DEPTH` - Merkle tree depth
### Circuit parameters ### Circuit parameters
**Public Inputs** **Public Inputs**
- `x` - `x`
- `epoch` - `external_nullifier`
- `rln_identifier`
**Private Inputs** **Private Inputs**
* `identity_secret_hash` * `identity_secret_hash`
@ -443,9 +438,9 @@ The identity credentials of a user are composed of:
The `identity_secret` is generated in the following way: The `identity_secret` is generated in the following way:
``` ```
identity_nullifier = random_32_byte_buffer identity_nullifier = random_32_byte_buffer
identity_trapdoor = random_32_byte_buffer identity_trapdoor = random_32_byte_buffer
identity_secret = [identity_nullifier, identity_trapdoor] identity_secret = [identity_nullifier, identity_trapdoor]
``` ```
The same secret should not be used accross different protocols, The same secret should not be used accross different protocols,
@ -456,7 +451,7 @@ because revealing the secret at one protocol could break privacy for the user in
The `identity_secret_hash` is generated by obtaining a Poseidon hash of the `identity_secret` array: The `identity_secret_hash` is generated by obtaining a Poseidon hash of the `identity_secret` array:
``` ```
identity_secret_hash = poseidonHash(identity_secret) identity_secret_hash = poseidonHash(identity_secret)
``` ```
### `identity_commitment` ### `identity_commitment`
@ -477,6 +472,16 @@ The standard for this is to use trusted [Multi-Party Computation (MPC)](https://
which requires two phases. which requires two phases.
Trusted MPC ceremony has not yet been performed for the RLN circuits. Trusted MPC ceremony has not yet been performed for the RLN circuits.
## SSS security assumptions
Shamir-Secret Sharing requires polynomial coefficients to be independent of each other.
However, `a_1` depends on `a_0` through the Poseidon hash algorithm.
Due to the design of Poseidon, it is possible to [attack](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) the protocol.
It was decided *not* to change the circuits design, since at the moment the attack is infeasible. Therefore, implementers must be aware that the current version provides approximately 160-bit security and not 254.
Possible improvements:
* [change the circuit](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) to make coefficients independent;
* switch to other hash function (Keccak, SHA);
# Appendix B: Identity scheme choice # Appendix B: Identity scheme choice
The hashing scheme used is based on the design decisions which also include the Semaphore circuits. The hashing scheme used is based on the design decisions which also include the Semaphore circuits.
@ -499,9 +504,9 @@ To achieve the above interoperability UX while preventing the shared app securit
we had to do the follow in regard the identity secret and identity commitment: we had to do the follow in regard the identity secret and identity commitment:
``` ```
identity_secret = [identity_nullifier, identity_trapdoor] identity_secret = [identity_nullifier, identity_trapdoor]
identity_secret_hash = poseidonHash(identity_secret) identity_secret_hash = poseidonHash(identity_secret)
identity_commitment = poseidonHash([identity_secret_hash]) identity_commitment = poseidonHash([identity_secret_hash])
``` ```
Secret components for generating Semaphore proof: Secret components for generating Semaphore proof:
@ -554,82 +559,73 @@ The examples are written in [rust](https://www.rust-lang.org/).
## Creating a RLN object ## Creating a RLN object
```rust ```rust
use rln::protocol::*; use rln::protocol::*;
use rln::public::*; use rln::public::*;
use std::io::Cursor; use std::io::Cursor;
// We set the RLN parameters:
// We set the RLN parameters: // - the tree height;
// - the tree height; // - the circuit resource folder (requires a trailing "/").
// - the circuit resource folder (requires a trailing "/"). let tree_height = 20;
let tree_height = 20; let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/");
let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/"); // We create a new RLN instance
let mut rln = RLN::new(tree_height, resources);
// We create a new RLN instance
let mut rln = RLN::new(tree_height, resources);
``` ```
## Generating identity credentials ## Generating identity credentials
```rust ```rust
// We generate an identity tuple // We generate an identity tuple
let mut buffer = Cursor::new(Vec::<u8>::new()); let mut buffer = Cursor::new(Vec::<u8>::new());
rln.extended_key_gen(&mut buffer).unwrap(); rln.extended_key_gen(&mut buffer).unwrap();
// We deserialize the keygen output to obtain
// We deserialize the keygen output to obtain // the identiy_secret and id_commitment
// the identiy_secret and id_commitment let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = deserialize_identity_tuple(buffer.into_inner());
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = deserialize_identity_tuple(buffer.into_inner());
``` ```
## Adding ID commitment to the RLN Merkle tree ## Adding ID commitment to the RLN Merkle tree
```rust ```rust
// We define the tree index where id_commitment will be added // We define the tree index where id_commitment will be added
let id_index = 10; let id_index = 10;
// We serialize id_commitment and pass it to set_leaf
// We serialize id_commitment and pass it to set_leaf let mut buffer = Cursor::new(serialize_field_element(id_commitment));
let mut buffer = Cursor::new(serialize_field_element(id_commitment)); rln.set_leaf(id_index, &mut buffer).unwrap();
rln.set_leaf(id_index, &mut buffer).unwrap();
``` ```
## Setting epoch and signal ## Setting epoch and signal
```rust ```rust
// We generate epoch from a date seed and we ensure is // We generate epoch from a date seed and we ensure is
// mapped to a field element by hashing-to-field its content // mapped to a field element by hashing-to-field its content
let epoch = hash_to_field(b"Today at noon, this year"); let epoch = hash_to_field(b"Today at noon, this year");
// We set our signal
// We set our signal let signal = b"RLN is awesome";
let signal = b"RLN is awesome";
``` ```
## Generating proof ## Generating proof
```rust ```rust
// We prepare input to the proof generation routine // We prepare input to the proof generation routine
let proof_input = prepare_prove_input(identity_secret, id_index, epoch, signal); let proof_input = prepare_prove_input(identity_secret, id_index, epoch, signal);
// We generate a RLN proof for proof_input
// We generate a RLN proof for proof_input let mut in_buffer = Cursor::new(proof_input);
let mut in_buffer = Cursor::new(proof_input); let mut out_buffer = Cursor::new(Vec::<u8>::new());
let mut out_buffer = Cursor::new(Vec::<u8>::new()); rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
.unwrap(); .unwrap();
// We get the public outputs returned by the circuit evaluation
// We get the public outputs returned by the circuit evaluation let proof_data = out_buffer.into_inner();
let proof_data = out_buffer.into_inner();
``` ```
## Verifiying proof ## Verifiying proof
```rust ```rust
// We prepare input to the proof verification routine // We prepare input to the proof verification routine
let verify_data = prepare_verify_input(proof_data, signal); let verify_data = prepare_verify_input(proof_data, signal);
// We verify the zk-proof against the provided proof values
// We verify the zk-proof against the provided proof values let mut in_buffer = Cursor::new(verify_data);
let mut in_buffer = Cursor::new(verify_data); let verified = rln.verify(&mut in_buffer).unwrap();
let verified = rln.verify(&mut in_buffer).unwrap(); // We ensure the proof is valid
assert!(verified);
// We ensure the proof is valid
assert!(verified);
``` ```
For more details please visit the [`zerokit`](https://github.com/vacp2p/zerokit) library. For more details please visit the [`zerokit`](https://github.com/vacp2p/zerokit) library.
@ -652,3 +648,5 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
- [10] https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-merkle-trees-using-the-poseidon-hash-function/7446 - [10] https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-merkle-trees-using-the-poseidon-hash-function/7446
- [11] https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing - [11] https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
- [12] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/ - [12] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/
- [13] https://github.com/Rate-Limiting-Nullifier/rln-circuits/
- [14] https://rate-limiting-nullifier.github.io/rln-docs/

View File

@ -8,7 +8,7 @@ bookMenuLevels: 1
- [24/STATUS-CURATION]({{< relref "/docs/rfcs/24/README.md" >}}) - [24/STATUS-CURATION]({{< relref "/docs/rfcs/24/README.md" >}})
- [28/STATUS-FEATURING]({{< relref "/docs/rfcs/28/README.md" >}}) - [28/STATUS-FEATURING]({{< relref "/docs/rfcs/28/README.md" >}})
- [31/WAKU2-ENR]({{< relref "/docs/rfcs/31/README.md" >}}) - [31/WAKU2-ENR]({{< relref "/docs/rfcs/31/README.md" >}})
- [32/RLN-SPEC]({{< relref "/docs/rfcs/32/README.md" >}}) - [32/RLN-V1-SPEC]({{< relref "/docs/rfcs/32/README.md" >}})
- [34/WAKU2-PEER-EXCHANGE]({{< relref "/docs/rfcs/34/README.md" >}}) - [34/WAKU2-PEER-EXCHANGE]({{< relref "/docs/rfcs/34/README.md" >}})
- [35/WAKU2-NOISE]({{< relref "/docs/rfcs/35/README.md" >}}) - [35/WAKU2-NOISE]({{< relref "/docs/rfcs/35/README.md" >}})
- [37/WAKU2-NOISE-SESSIONS]({{< relref "/docs/rfcs/37/README.md" >}}) - [37/WAKU2-NOISE-SESSIONS]({{< relref "/docs/rfcs/37/README.md" >}})