Add encryption/signature documentation

This commit is contained in:
Franck Royer 2021-07-16 11:17:11 +10:00
parent 455b568cde
commit 4f796ab920
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
2 changed files with 129 additions and 0 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Examples (web-chat): New `/fleet` command to switch connection between Status prod and test fleets.
- Export `generatePrivateKey` and `getPublicKey` directly from the root.
- Usage of the encryption and signature APIs to the readme.
### Changed
- **Breaking**: Renamed `WakuRelay.(add|delete)PrivateDecryptionKey` to `WakuRelay.(add|delete)DecryptionKey` to make it clearer that it accepts both symmetric keys and asymmetric private keys.

128
README.md
View File

@ -117,6 +117,134 @@ waku.store.queryHistory({
});
```
## Encryption & Signature
With js-waku, you can:
- Encrypt messages over the wire using public/private key pair (asymmetric encryption),
- Encrypt messages over the wire using a unique key to both encrypt and decrypt (symmetric encryption),
- Sign and verify your waku messages (must use encryption, compatible with both symmetric and asymmetric).
### Cryptographic Libraries
A quick note on the cryptographic libraries used as it is a not a straightforward affair:
- Asymmetric encryption: Uses [ecies-geth](https://github.com/cyrildever/ecies-geth/) which in turns uses [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) Web API (browser), [secp256k1](https://www.npmjs.com/package/secp256k1) (native binding for node) or [elliptic](https://www.npmjs.com/package/elliptic) (pure JS if none of the other libraries are available).
- Symmetric encryption: uses [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) Web API (browser) or [NodeJS' crypto](https://nodejs.org/api/crypto.html) module. Which means there is no fallback if [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) is not available, [elliptic](https://www.npmjs.com/package/elliptic) could be added if the need rises.
### Create new keys
Asymmetric private keys and symmetric keys are expected to be 32 bytes arrays.
```ts
import { generatePrivateKey, getPublicKey } from 'js-waku';
// Asymmetric
const privateKey = generatePrivateKey();
const publicKey = getPublicKey(privateKey);
// Symmetric
const symKey = generatePrivateKey();
```
### Encrypt Waku Messages
To encrypt your waku messages, simply pass the encryption key when creating it:
```ts
import { WakuMessage } from 'js-waku';
// Asymmetric
const message = await WakuMessage.fromBytes(payload, {
contentTopic: myAppContentTopic,
encPublicKey: publicKey,
});
// Symmetric
const message = await WakuMessage.fromBytes(payload, {
contentTopic: myAppContentTopic,
symKey: symKey,
});
```
### Decrypt Waku Messages
#### Waku Relay
If you expect to receive encrypted messages then simply add private decryption key(s) to `WakuRelay`.
Waku Relay will attempt to decrypt incoming messages with each keys, both for symmetric and asymmetric encryption.
Messages that are successfully decrypted (or received in clear) will be passed to the observers, other messages will be ommitted.
```ts
// Asymmetric
waku.relay.addDecryptionKey(privateKey);
// Symmetric
waku.relay.addDecryptionKey(symKey);
// Then add the observer
waku.relay.addObserver(callback, [contentTopic]);
```
Keys can be removed using `WakuMessage.deleteDecryptionKey`.
#### Waku Store
```ts
const messages = await waku.store.queryHistory({
contentTopics: [],
decryptionKeys: [privateKey, symKey],
});
```
Similarly to relay, only decrypted or clear messages will be returned.
### Sign Waku Messages
As per version 1`s [specs](https://rfc.vac.dev/spec/26/), signatures are only included in encrypted messages.
In the case where your app does not need encryption then you could use symmetric encryption with a trivial key, I intend to dig [more on the subject](https://github.com/status-im/js-waku/issues/74#issuecomment-880440186) and come back with recommendation and examples.
Signature keys can be generated the same way asymmetric keys for encryption are:
```ts
import { generatePrivateKey, getPublicKey, WakuMessage } from 'js-waku';
const signPrivateKey = generatePrivateKey();
// Asymmetric Encryption
const message = await WakuMessage.fromBytes(payload, {
contentTopic: myAppContentTopic,
encPublicKey: recipientPublicKey,
sigPrivKey: signPrivateKey
});
// Symmetric Encryption
const message = await WakuMessage.fromBytes(payload, {
contentTopic: myAppContentTopic,
encPublicKey: symKey,
sigPrivKey: signPrivateKey
});
```
### Verify Waku Message signatures
Two fields are available on `WakuMessage` regarding signatures:
- `signaturePublicKey`: If the message is signed, it holds the public key of the signature,
- `signature`: If the message is signed, it holds the actual signature.
Thus, if you expect messages to be signed by Alice,
you can simply compare `WakuMessage.signaturePublicKey` with Alice's public key.
As comparing hex string can lead to issues (is the `0x` prefix present?),
simply use helper function `equalByteArrays`.
```ts
import { equalByteArrays } from 'js-waku/lib/utils';
const sigPubKey = wakuMessage.signaturePublicKey;
const isSignedByAlice = sigPubKey && equalByteArrays(sigPubKey, alicePublicKey);
```
## More documentation
Find more [examples](#examples) below