-
Notifications
You must be signed in to change notification settings - Fork 53
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
feat(rln): How to securely store RLN credentials cross-client #1278
Comments
I don't see an impediment in using an external module for writing/reading external credentials, but IMO the effort of implementing this idea should be compared against the effort of using existing libraries in each language (like it does in go, and nim after extracting it from nimbus) In Prysm (an eth2 client), they are using https://github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 https://github.com/prysmaticlabs/prysm/blob/d077483577bc8fdc658940adf71d8d11dfa5949b/tools/keystores/main.go . For JS, Chainsafe implemented https://www.npmjs.com/package/@chainsafe/bls-keystore which is compatible with EIP2335 and used in Lodestar, and according to its description, it can be used on the browser. -- in go-waku, while the chat2 example stores the credentials in plaintext (for compatibility across implementations), the wakunode is using go-ethereum keystore to write the credentials https://github.com/status-im/go-waku/blob/master/waku/rln-credentials.go#L50, encrypted with a password that can be passed via the |
The encryptDataV3 API used in go-waku encrypts data in a way that doesn't seem to be EIP-2335 compliant (I cannot indeed find its specification there), but formats are however similar:
vs.
In encryptDataV3 there is a field called mac, but in fact is just the keccak256 of the right 16 bytes of the derived key https://github.com/ethereum/go-ethereum/blob/b9ba6f6e4d86d0ee86c63e8f4552e233fe0450aa/accounts/keystore/passphrase.go#L159. It should be equivalent to the EIP field checksum's message: https://github.com/status-im/nimbus-eth2/blob/c585b0a5b1ae4d55af38ad7f4715ad455e791552/beacon_chain/spec/keystore.nim#L905. So, which approach shall we follow? Fully EIP-compliat (with fields we don't use zeroed, like pubkey, etc.) or the format provided by encryptDataV3? Both are equally possible with minor modifications. I expect more libraries to be able to deal directly with EIP-compliant keystores (think of JSON schema validation), although we're adapting it for a different use than its original purpose and indeed some fields are unnecessary. |
Ah! this is because go-waku is not using at the moment EIP2335, but https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition. This should be implemented in nim in: |
Thanks! Same as for nimbus, plaintext is hardcoded to be a secret key, but this can be fixed. The .md states that scrypt is not supported but I can see it implemented, so we should have compatibility! It would be great if you can post 1-2 test-vector (scrypt/pkdf2) with password so that I can check against customized nim-eth implementation! |
In https://github.com/ethereum/go-ethereum/blob/master/accounts/keystore/testdata/v3_test_vector.json there are a couple of test vectors with their |
It seems that encrypted credentials returned by go-waku based on encryptDataV3 don't embed the I was able to fully replicate test vectors content (but for arbitrary input data) and produce keyfiles compliant with https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition. However we need to decide if we want to keep all fields (even if we don't use some) and refer to the standard, or have a custom/minimal version of the JSON. For me is a minor refactor, I guess what really could make a difference is what libraries are available for js-waku and the output format of keyfiles' JSONs. |
As a side note: this PR can proceed in parallel and even be merged before an agreement on the (unencrypted) RLN credential format, i.e. a solution to vacp2p/rfc#543, is found. Indeed, keyfiles' logic is agnostic from the content they encrypt. Once an agreement on vacp2p/rfc#543 is found, we just replace the input to the keyfile creation routine from current rlnCredentials.txt content to the data in the agreed format. |
For JS, the following libraries are available, but would probably require some minor work for them to allow encrypting arbitrary data |
The reason why go-waku does not add |
The implementation in |
I agree with @richard-ramos's comments above. Considering what we are trying to achieve, I am not convinced it is worth using a common library (imported in wasm) across implementations. If we can find an existing standard (e.g. EIP-2335) that fits the purpose then it would make sense. I see EIP-2335 is BLS specific. Would it makes sense to propose an EIP extension to use it for zk credentials usage too? |
Not sure. At the end we're using a (really minor) revision of https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition , that is we just removed the
I was unable to find any |
Also note that for the browser, vacp2p/zerokit#56 (comment) enables deterministic generation of credentials from an ethereum wallet signature. AFAIK, this strategy is used by several zk projects (e.g. aztec network, zksync). This enables delegation of the storing of credentials to the Ethereum Wallet. The only missing part being the membership id: I assume this can be retrieve by finding the transaction that inserted the member? WDYT about using seeded generation as a first step to save credentials in the browser? |
Right now, we don't have an import/export format, though that is something we are planning to add. I agree that JSON is probably the best format. |
Finding commitments among leaves should be easy. However, the naive linear approach requires 2^19 checks on average for a tree with max 2^20 elements. Unfortunately the tree is not ordered (this would have required just ~20 checks) since otherwise commitment indexes would keep changing with new registrations. But a space-time tradeoff is also possible: we maintain a table with keys all values from If we use n of size 2 bytes, i.e. n=256*256 (or we just look at least 2 bytes of commitment), then the indexes we need to try would be 2^19/2^16 = 2^3 = 8, even better than an ordered tree. Also, given the size of such table it could also be distributed (along with the tree, once we can store it). |
Wouldn't it be easier to just find the matching Ethereum transaction sent to the contract from the loaded wallet and look at the receipt of said transaction? |
Not sure easier: to generate valid proofs, assumption here is that you already have the local tree filled/updated and at that point is easier to search the index locally rather than online, since both approaches require linear time if done naively (I don't see how we can optimize the online way, while for the local search we can do something like what I described in my previous comment). In any case, I'm not sure if you need to go through all blocks since contract deployment to get all tx logs (complexity > than searching in local tree) or if you can directly query only tx logs coming from a specific contract address (complexity >= than searching in local tree). |
This issue has been addressed by #1285 and its follow-up PR #1466. The solution implements #1238 (comment), that is a structured JSON keystore supporting multiple membership credentials encrypted with an implementation derived from nimbus keyfile module. |
Background
In
is raised multiple times the question of standardizing the RLN credential format and securely persist it.
Details
nwaku
,js-waku
andgo-waku
generates RLN credentials throughzerokit
FFI/WASM APIs.While standardization of a format for RLN credentials can be pursued in vacp2p/rfc#543 (a tentative solution was proposed here), their secure persistence and cross-client usage (e.g. decryption) is non-trivial.
As suggested here,
nwaku
comes with animbus
keystore implementation that allows to securely encrypt messages (in fact, keys) using a password/mnemonic sentence. However, to allow cross-client usage of encrypted credentials, the underlying employed primitives (scrypt, pbkdf, sha256, aes-128-ctr
) should be ported/implemented injs-waku
andgo-waku
too.On top of this, nimbus keystores don't seem to allow enough flexibility on fields structure to reach something similar to what proposed here and come with primitives that should probably be replaced at least to provide 256 bits of security (I would personally use Argon2 + ChaChaPoly).
Given this, a possible solution could be to implement a WASM-friendly rust module that we can interface, similarly as zerokit, with FFI/WASM implementing all the logic on our custom standardized RLN credential format (most probably JSON with fields content encrypted), so that we avoid multiple implementations of the same crypto primitives.
Nevertheless, if implementation/usage of a browser extension is envisioned for js-rln in order to safely store credentials (e.g., crypt-keeper), then we might opt for separate implementations in
nwaku
andgo-waku
of RLN credentials' field encryption, since both already support Noise primitives. In any case, import/export of credentials should be supported too by the browser extension and crypt-keeper doesn't seem to have such feature yet.Pro and cons
Acceptance criteria
@staheri14 @rymnc @fryorcraken @richard-ramos @oskarth
The text was updated successfully, but these errors were encountered: