diff --git a/README.md b/README.md index 98ad3d0..8c27b1b 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ This repository contains specifications for the Waku suite of protocols. |[WAKU2-DEVICE-PAIRING](standards/application/device-pairing.md)| Device Pairing and Secure Transfers with Noise | |[WAKU2-NOISE](standards/application/noise.md)| Noise Protocols for Waku Payload Encryption | |[TOR-PUSH](standards/application/tor-push.md)| Waku Tor Push | +|[RLN-KEYSTORE](standards/application/rln-keystore.md)| Waku RLN Keystore JSON schema| ### Informational diff --git a/standards/application/rln-keystore.md b/standards/application/rln-keystore.md new file mode 100644 index 0000000..a9dde99 --- /dev/null +++ b/standards/application/rln-keystore.md @@ -0,0 +1,299 @@ +--- +title: WAKU-RLN-KEYSTORE +name: Waku RLN Keystore +category: Standards Track +editor: Jimmy Debe +contributors: +- Aaryamann Challani +--- + +## Abstract +This specification describes how RLN, Rate Limit Nullifier, +credentials are securely stored in a JSON schema. + +## Summary +A keystore is a construct to store a user’s keys. +The keys will be encrypted and decrypted based on methods specified in this specification. +The keystore stores a user's credentials locally and +uses [32/RLN-V1](/spec/32/) as a spam-prevention mechanism by generating zero-knowledge proofs. + +## Background +The secure storage of keys is important in peer-to-peer messaging applications. +A `WAKU-RLN-KEYSTORE` uses zero-knowledge proofs for anonymous rate-limiting for messaging frameworks. +Generated credentials by a user are encrypted and stored in the keystore to be retrieved over a network. +With [32/RLN-V1](/spec/32/), sending and receiving +messages will ensure a message rate for a network is being followed while preserving the anonymity of the message owner. + +### Waku RLN Keystore Format: + +A format example of a keystore used by a [17/WAKU2-RLN-Relay](/spec/17/). + +```js +const Keystore { + application: "waku-rln-relay" , + appIdentifier: "string", + version: "string", + credentials: { + "membershipHash": { + crypto: { + cipher: "string", + cipherparams: { + iv: "string", + }, + ciphertext: "string", + kdf: "string", + kdfparams: { + dklen: integer, + c: integer, + prf: "string", + salt: "string", + }, + mac: "string", + } + } + } +} + +``` + +## Specification +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, +“NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +The keystore MUST be generated by a cryptographic construction with password verification and decryption. + +Keystore modules MUST include metadata, key derivation function, checksum, cipher, and a membership hash. + +### Metadata: +Information about the keystore SHOULD be stored in the metadata. + +The declaration of `application`, `version`, and `appIdentifier` COULD occur in the metadata. + +- `application` : current application, MUST be a string +- `version` : application version, MUST be a string, SHOULD follow semantic versioning +- `appIdentifier`: application identifier, MUST be a string + +### Credentials: + +After RLN credentials are generated, it MUST be stored in a JSON schema. +The Waku RLN credentials MUST consist of a `membershipHash` and `WakuCredential`. +The `membershipHash` will be an identity hash of the user. +The `WakuCredential` will store to encryption portion of the keystore. +There COULD be multiple credentials stored in a keystore, categorized by the `membershipHash`. + +Each contruct MUST include the keypair: +> key: [`membershipHash`]: pair: [`WakuCredential`] + +#### membershipHash + +The `membershipHash` SHOULD be generated by user's participating in a membership group, +as decribed in [32/RLN-V1](/spec/32/). +Each user SHOULD register to the group with an `identity_commitment` stored in a Merkle tree. +A cryptographic hash function that SHOULD be used to generate the `membershipHash` is [SHA256](https://www.rfc-editor.org/rfc/rfc4634.txt), +other hash functions MAY be used. +The hash function that is used, +SHOULD be mentioned in the `verison` attribute. + +To generate the `membershipHash`, +the `treeIndex`, `membershipContract`, `chainId` and `identityCredential` attributes SHOULD be used to create a hexadecimal string. +- it MUST NOT already exist in the keystore. + +##### `treeIndex` + +After a user registers to a group, +a `treeIndex` value of the position in the Merkle tree SHOULD be returned. +- it MUST be a Merkle tree data structure filled with `identity_commitment` from user registrations. +- it MUST be a hexadecimal string + +##### `membershipContract` + +For decentralized membership registrations, +the `membershipContract` SHOULD be a `contractAddress` from a public blockchain using smart contracts. +- it MUST be a string. + +##### `chainId` +It uniquely defines the chain upon which the registration has occurred. +The `chainId` SHOULD be the blockchain identifier used for `membershipcontract`, +as described in [EIP155](https://eips.ethereum.org/EIPS/eip-155). +- it MUST be a string + +##### `identityCredential` + +The `identityCredential` MUST be derived after a succussful decryption of the keystore. + +The `identityCredential` MUST be constructed with the `identity_secret`, `identity_secret_hash`, `identity_commitment` values. +- it MUST be a hash of `identity_commitment` stored in a Merkle tree. +- it MUST be a string. + +###### `identity_secret` + +The `identity_secret` MUST be constructed with `identity_nullifier` + `identity_trapdoor` values. +- `identity_nullifier` : Random 32 byte value +- `identity_trapdoor` : Random 32 byte value + +###### `identity_secret_hash` + +Used to derive the `identity_commitment` of the user, and +as a private input for zero-knowledge proof generation. +- it MUST be created with `identity_secret` as a parameter for the hash function. +- This secret hash SHOULD be kept private by the user. + +###### `identity_commitment` +- it SHOULD be created with `identity_secret_hash` by using the hash function Poseidon, +as described in [Poseidon Paper](https://eprint.iacr.org/2019/458.pdf). +- it MUST be used by a user for group registering. + +#### WakuCredential + +The `WakuCredential` will store values used for encrypting and decrypting user's keystores. +- it MUST be used for password verification. +- it MUST follow [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335) +- it SHOULD use [SHA256](https://www.rfc-editor.org/rfc/rfc4634.txt) as the hash function + + +#### KDF + +The password-based encryption used SHOULD be KDF, key derivation function, +to produce a derived key from a password and other parameters. +The keystore COULD use PBKDF2 password-based encryption, +as described in [RFC 2898](https://www.ietf.org/rfc/rfc2898.txt). + +A `WakuCredential` object MUST include: +| Name | Description | +|----|-----| +| password | used to encrypt keystore and decryption key | +| secret | key to be encrypted | +| pubKey | public key | +| path | HD, hardened derivation, path used to generate the secret | +| checksum | hash function | +| cipher | cipher function | + +```js + +crypto: { + + cipher: "string" // The cipher function + cipherparams: { + iv: "string" // The cipher parameters + }, + ciphertext: "string" // The cipher message, + kdf: "string" // KDF Function, + kdfparams: { + param: integer // Salt value and iteration count, + dklen: integer // Length in octets of derived key, MUST be positive integer, + c: "string" // Iteration count, MUST be positive integer, + prf: "string" // Underlying pseudorandom function, + salt: "string" // Produces a large set of keys based on the password + }, + mac: "string" // Checksum +} + +``` + +#### Decryption +The keystore SHOULD decrypt a user's credentials using a password and the `membershipHash`, +using PBKDF2 that returns the `decryptionKey` key. +The decryption key is used to verify the keystore is correct. +- To generate the `decryptionKey`, it MUST be constructed from a password and KDF, +as desrcibed in [ERC-2335: BLS12-381 Keystore](https://eips.ethereum.org/EIPS/eip-2335). +- The `decryptionKey`, is derived from the cipher function and +cipher parameters described in the KDF used in the keystore. + +### Test Vectors + +RLN uses Poseidon hash algorithm to generate the `identityCredential`, +as described in [Poseidon Paper](https://eprint.iacr.org/2019/458.pdf). +The keystore hash algorithm used is [SHA256](https://www.rfc-editor.org/rfc/rfc4634.txt). + +#### Input: + +- `application`: "waku-rln-relay" +- `appIdentifier`: "01234567890abcdef" +- `version`: "0.2" +- `hashFunction`: "poseidonHash" +- `password`: "sup3rsecure" + +```js + +identityCredential = { + IDTrapdoor: [ + 211, 23, 66, 42, 179, 130, 131, 111, 201, 205, 244, 34, 27, 238, 244, + 216, 131, 240, 188, 45, 193, 172, 4, 168, 225, 225, 43, 197, 114, 176, + 126, 9, + ], + IDNullifier: [ + 238, 168, 239, 65, 73, 63, 105, 19, 132, 62, 213, 205, 191, 255, 209, 9, + 178, 155, 239, 201, 131, 125, 233, 136, 246, 217, 9, 237, 55, 89, 81, + 42, + ], + IDSecretHash: [ + 150, 54, 194, 28, 18, 216, 138, 253, 95, 139, 120, 109, 98, 129, 146, + 101, 41, 194, 36, 36, 96, 152, 152, 89, 151, 160, 118, 15, 222, 124, + 187, 4, + ], + IDCommitment: [ + 112, 216, 27, 89, 188, 135, 203, 19, 168, 211, 117, 13, 231, 135, 229, + 58, 94, 20, 246, 8, 33, 65, 238, 37, 112, 97, 65, 241, 255, 93, 171, 15, + ], + +} + +membership = { + chainId: "0xAA36A7", + treeIndex: 8, + address: "0x8e1F3742B987d8BA376c0CBbD7357fE1F003ED71", +} + +``` + +#### Output: + +```js +application: "waku-rln-relay", +appIdentifier: "01234567890abcdef", +version: "0.2", + credentials: { + "9DB2B4718A97485B9F70F68D1CC19F4E10F0B4CE943418838E94956CB8E57548": { + crypto: { + cipher: "aes-128-ctr", + cipherparams: { + iv: "fd6b39eb71d44c59f6bf5ff3d8945c80", + }, + ciphertext: "9c72f47ce95de03ed34502d0288e7576b66b51b9e7d5ae882c27bd89f94e6a03c2c44c2ddf0c982e72003d67212105f1b64614f57cabb0ceadab7e07be165eee1121ad6b81951368a9f3be2dd99ea294515f6013d5f2bd4702a40e36cfde2ea298b23b31e5ce719d8040c3331f73d6bf44f88bca39bac0e917d8bf545500e4f40d321c235426a80f315ac70666acbd3bdf803fbc1e7e7103fed466525ed332b25d72b2dbedf6fa383b2305987c1fe276b029570519b3e79930edf08c1029868d05c2c08ab61d7c64f63c054b4f6a5a12d43cdc79751b6fe58d3ed26b69443eb7c9f7efce27912340129c91b6b813ac94efd5776a40b1dda896d61357de208c7c47a14af911cc231355c8093ee6626e89c07e1037f9e0b22c690e3e049014399ca0212c509cb04c71c7860d1b17a0c47711c490c27bad2825926148a1f15a507f36ba2cdaa04897fce2914e53caed0beaf1bebd2a83af76511cc15bff2165ff0860ad6eca1f30022d7739b2a6b6a72f2feeef0f5941183cda015b4631469e1f4cf27003cab9a90920301cb30d95e4554686922dc5a05c13dfb575cdf113c700d607896011970e6ee7d6edb61210ab28ac8f0c84c606c097e3e300f0a5f5341edfd15432bef6225a498726b62a98283829ad51023b2987f30686cfb4ea3951f3957654035ec291f9b0964a3a8665d81b16cec20fb40f944d5f9bf03ac1e444ad45bae3fa85e7465ce620c0966d8148d6e2856f676c4fbbe3ebe470453efb4bbda1866680037917e37765f680e3da96ef3991f3fe5cda80c523996c2234758bf5f7b6d052dc6942f5a92c8b8eec5d2d8940203bbb6b1cba7b7ebc1334334ca69cdb509a5ea58ec6b2ebaea52307589eaae9430eb15ad234c0c39c83accdf3b77e52a616e345209c5bc9b442f9f0fa96836d9342f983a7", + kdf: "pbkdf2", + kdfparams: { + dklen: 32, + c: 1000000, + prf: "hmac-sha256", + salt: "60f0aa92fbf63a8356dfdbed2ab18058", + }, + mac: "51a227ac6db7f2797c63925880b3db664e034231a4c68daa919ab42d8df38bc6", + }, + } + +``` + +## Security Considerations +### 1.) Add a Password + +An attacker can identify which credential belongs to a combination of `chainId` and +`contractAddress` pair by brute forcing the `treeIndex` iteratively to find a hash match. +The RECOMMENDED solution is to add a password to the construction of `membershipHash` to prevent this attack. + +The RECOMMENDED `membershipHash` Construction: +- `membershipHash` SHOULD be constructed with `treeIndex`, `membershipContract`, `identityCredential`, `membershipPassword` + - `membershipPassword` : a new password created to private attacks compromising keystore credentials. + - The user MUST store the `membershipPassword` privately. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +## References +1. [32/RLN-V1](/spec/32/) +2. [17/WAKU2-RLN-RELAY](/spec/17/) +3. [SHA256](https://www.rfc-editor.org/rfc/rfc4634.txt) +4. [EIP155](https://eips.ethereum.org/EIPS/eip-155) +5. [Poseidon Paper](https://eprint.iacr.org/2019/458.pdf) +6. [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335) +7. [RFC 2898](https://www.ietf.org/rfc/rfc2898.txt) +8. [ERC-2335: BLS12-381 Keystore](https://eips.ethereum.org/EIPS/eip-2335)