mirror of https://github.com/status-im/go-waku.git
chore: add docs for encoding/decoding messages (#236)
This commit is contained in:
parent
386d59747a
commit
19f13b80fa
40
README.md
40
README.md
|
@ -52,46 +52,20 @@ make dynamic-library
|
||||||
## Tutorials and documentation
|
## Tutorials and documentation
|
||||||
- [Receive and send messages using Waku Relay](docs/relay.md)
|
- [Receive and send messages using Waku Relay](docs/relay.md)
|
||||||
- [Send messages using Waku Lightpush](docs/lightpush.md)
|
- [Send messages using Waku Lightpush](docs/lightpush.md)
|
||||||
|
- [Encoding and decoding Waku Messages](docs/encoding.md)
|
||||||
- [C Bindings](library/README.md)
|
- [C Bindings](library/README.md)
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
Examples of usage of go-waku as a library can be found in the `examples/` folder:
|
Examples of usage of go-waku as a library can be found in the `examples/` folder:
|
||||||
|
|
||||||
- [**basic2**](../examples/basic2) - demonstrates how to send and receive messages
|
- [**basic2**](tree/master/examples/basic2) - demonstrates how to send and receive messages
|
||||||
- [**chat2**](../examples/chat2) - simple chat client using waku relay / lightpush + filter / store protocol to send/receive messages and retrieve message history
|
- [**chat2**](tree/master/examples/chat2) - simple chat client using waku relay / lightpush + filter / store protocol to send/receive messages and retrieve message history
|
||||||
- [**filter2**](../examples/filter2) - demonstrates how to use filter protocol
|
- [**filter2**](tree/master/examples/filter2) - demonstrates how to use filter protocol
|
||||||
- [**c-bindings**](../examples/c-bindings) - simple program to demonstrate how to consume the go-waku library via C FFI
|
- [**c-bindings**](tree/master/examples/c-bindings) - simple program to demonstrate how to consume the go-waku library via C FFI
|
||||||
- [**waku-csharp**](../examples/csharp) - C# console application that uses the go-waku library via FFI
|
- [**waku-csharp**](tree/master/examples/csharp) - C# console application that uses the go-waku library via FFI
|
||||||
- [**android-kotlin**](../examples/android-kotlin) - android app that uses a .jar generated by gomobile using kotlin
|
- [**android-kotlin**](tree/master/examples/android-kotlin) - android app that uses a .jar generated by gomobile using kotlin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Waku Protocol Support
|
|
||||||
|
|
||||||
- ✔: Supported
|
|
||||||
- 🚧: Implementation in progress
|
|
||||||
- ⛔: Support is not planned
|
|
||||||
|
|
||||||
| Spec | Implementation Status |
|
|
||||||
| ---- | -------------- |
|
|
||||||
|[7/WAKU-DATA](https://rfc.vac.dev/spec/7)|✔|
|
|
||||||
|[10/WAKU2](https://rfc.vac.dev/spec/10)|🚧|
|
|
||||||
|[11/WAKU2-RELAY](https://rfc.vac.dev/spec/11)|✔|
|
|
||||||
|[12/WAKU2-FILTER](https://rfc.vac.dev/spec/12)|✔|
|
|
||||||
|[13/WAKU2-STORE](https://rfc.vac.dev/spec/13)|✔|
|
|
||||||
|[14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14)|✔|
|
|
||||||
|[15/WAKU2-BRIDGE](https://rfc.vac.dev/spec/15)|⛔|
|
|
||||||
|[16/WAKU2-RPC](https://rfc.vac.dev/spec/16)|✔|
|
|
||||||
|[17/WAKU2-RLNRELAY](https://rfc.vac.dev/spec/17)||
|
|
||||||
|[18/WAKU2-SWAP](https://rfc.vac.dev/spec/18)|🚧|
|
|
||||||
|[21/WAKU2-FTSTORE](https://rfc.vac.dev/spec/21)|✔|
|
|
||||||
|[22/TOY-CHAT](https://rfc.vac.dev/spec/22)|✔|
|
|
||||||
|[23/TOPICS](https://rfc.vac.dev/spec/22)|✔|
|
|
||||||
|[25/LIBP2P-DNS-DISCOVERY](https://rfc.vac.dev/spec/25)|🚧|
|
|
||||||
|[26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26)|✔|
|
|
||||||
|[27/WAKU2-PEERS](https://rfc.vac.dev/spec/27)|✔|
|
|
||||||
|[29/WAKU2-CONFIG](https://rfc.vac.dev/spec/29)|🚧|
|
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
Thank you for considering to help out with the source code! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
|
Thank you for considering to help out with the source code! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
Encoding and decoding Waku Messages
|
||||||
|
===
|
||||||
|
|
||||||
|
The Waku Message format provides an easy way to encrypt messages using symmetric or asymmetric encryption. The encryption comes with several handy design requirements: confidentiality, authenticity and integrity. You can find more details about Waku Message Payload Encryption in 26/WAKU-PAYLOAD.
|
||||||
|
|
||||||
|
## What data is encrypted
|
||||||
|
With Waku Message Version 1, the entire payload is encrypted.
|
||||||
|
|
||||||
|
Which means that the only discriminating data available in clear text is the content topic and timestamp (if present). Hence, if Alice expects to receive messages under a given content topic, she needs to try to decrypt all messages received on said content topic.
|
||||||
|
|
||||||
|
This needs to be kept in mind for scalability and forward secrecy concerns:
|
||||||
|
|
||||||
|
- If there is high traffic on a given content topic then all clients need to process and attempt decryption of all messages with said content topic;
|
||||||
|
- If a content topic is only used by a given (group of) user(s) then it is possible to deduce some information about said user(s) communications such as sent time and frequency of messages.
|
||||||
|
|
||||||
|
## Key management
|
||||||
|
By using Waku Message Version 1, you will need to provide a way to your users to generate and store keys in a secure manner. Storing, backing up and recovering key is out of the scope of this guide.
|
||||||
|
|
||||||
|
## Which encryption method should I use?
|
||||||
|
Whether you should use symmetric or asymmetric encryption depends on your use case.
|
||||||
|
|
||||||
|
Symmetric encryption is done using a single key to encrypt and decrypt.
|
||||||
|
|
||||||
|
Which means that if Alice knows the symmetric key `K` and uses it to encrypt a message, she can also use `K` to decrypt any message encrypted with `K`, even if she is not the sender.
|
||||||
|
|
||||||
|
Group chats is a possible use case for symmetric encryption: All participants can use an out-of-band method to agree on a `K`. Participants can then use `K` to encrypt and decrypt messages within the group chat. Participants MUST keep `K` secret to ensure that no external party can decrypt the group chat messages.
|
||||||
|
|
||||||
|
Asymmetric encryption is done using a key pair: the public key is used to encrypt messages, the matching private key is used to decrypt messages.
|
||||||
|
|
||||||
|
For Alice to encrypt a message for Bob, she needs to know Bob’s Public Key `K`. Bob can then use his private key `k` to decrypt the message. As long as Bob keep his private key `k` secret, then he, and only he, can decrypt messages encrypted with `K`.
|
||||||
|
|
||||||
|
Private 1:1 messaging is a possible use case for asymmetric encryption: When Alice sends an encrypted message for Bob, only Bob can decrypt it.
|
||||||
|
|
||||||
|
## Symmetric Encryption
|
||||||
|
|
||||||
|
### Encrypt a Message
|
||||||
|
To encrypt a message, assign the 32 byte symmetric key to a `KeyInfo`, and set its `Kind` to `node.Symmetric`. `node.EncodeWakuMessage` can then be used to encrypt the payload of a WakuMessage (that uses version `1`).
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/status-im/go-waku/waku/v2/utils"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
symKey := []byte{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
|
||||||
|
|
||||||
|
keyInfo := &node.KeyInfo{
|
||||||
|
Kind: node.Symmetric,
|
||||||
|
SymKey: symKey,
|
||||||
|
// PrivKey: Set a privkey if the message requires a signature
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &pb.WakuMessage{
|
||||||
|
Payload: []byte("Hello World"),
|
||||||
|
Version: 1,
|
||||||
|
ContentTopic: "/test/1/test/proto",
|
||||||
|
Timestamp: utils.GetUnixEpoch(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.EncodeWakuMessage(msg, keyInfo); err != nil {
|
||||||
|
fmt.Println("Error encrypting the message payload: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The `WakuMessage` payload will be encrypted, and can be later broadcasted via Relay or Lightpush. It's also possible to not have to rely on a `WakuMessage` by creating instead a `node.Payload`, setting the payload in the `Data` attribute and the key in `Key`, and then use `payload.Encode(1)` to encrypt your message, receiving a `byte[]` as a result.
|
||||||
|
|
||||||
|
The message can also be signed with a private key (`*ecdsa.PrivKey`) by setting it into the `PrivKey` attribute of the `KeyInfo` instance.
|
||||||
|
|
||||||
|
### Decrypting a Message
|
||||||
|
To decrypt a message, regardless of the protocol on which it was received, assign the 32 byte symmetric key to a `KeyInfo`, and set its `Kind` to `node.Symmetric`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/status-im/go-waku/waku/v2/utils"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
symKey := []byte{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
|
||||||
|
|
||||||
|
keyInfo := &node.KeyInfo{
|
||||||
|
Kind: node.Symmetric,
|
||||||
|
SymKey: symKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This message could have arrived via any of these protocols: relay, filter, store
|
||||||
|
msg := &pb.WakuMessage{
|
||||||
|
Payload: ..., // Some encrypted payload
|
||||||
|
Version: 1,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.DecodeWakuMessage(msg, keyInfo); err != nil {
|
||||||
|
fmt.Println("Error decrypting the message payload: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(msg.Payload)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `WakuMessage` payload will be decrypted and available in plain text. Messages that can't be decrypted will return an `error`.
|
||||||
|
|
||||||
|
> To have access to the message author's public key and signature (if available) of the message, `DecodePayload(msg, keyInfo)` can be used instead. It will return a `DecodedPayload` instance containing `PubKey` and `Signature` attributes, and it's not a destructive operation, so the `WakuMessage` protobuffer will not be modified.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Asymmetric Encryption
|
||||||
|
|
||||||
|
### Encrypt a Message
|
||||||
|
To encrypt a message, assign an `*ecdsa.PublicKey` to a `KeyInfo`, and set its `Kind` to `node.Asymmetric`. `node.EncodeWakuMessage` can then be used to encrypt the payload of a WakuMessage (that uses version `1`).
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/status-im/go-waku/waku/v2/utils"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
|
||||||
|
|
||||||
|
keyInfo := &node.KeyInfo{
|
||||||
|
Kind: node.Asymmetric,
|
||||||
|
PubKey: ..., // The public key to encrypt the messages with
|
||||||
|
// PrivKey: Set a privkey if the message requires a signature
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &pb.WakuMessage{
|
||||||
|
Payload: []byte("Hello World"),
|
||||||
|
Version: 1,
|
||||||
|
ContentTopic: "/test/1/test/proto",
|
||||||
|
Timestamp: utils.GetUnixEpoch(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.EncodeWakuMessage(msg, keyInfo); err != nil {
|
||||||
|
fmt.Println("Error encrypting the message payload: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The `WakuMessage` payload will be encrypted, and can be later broadcasted via Relay or Lightpush. It's also possible to not have to rely on a `WakuMessage` by creating instead a `node.Payload`, setting the payload in the `Data` attribute and the key in `Key`, and then use `payload.Encode(1)` to encrypt your message, receiving a `byte[]` as a result.
|
||||||
|
|
||||||
|
The message can also be signed with a private key (`*ecdsa.PrivKey`) by setting it into the `PrivKey` attribute of the `KeyInfo` instance.
|
||||||
|
|
||||||
|
### Decrypting a Message
|
||||||
|
To decrypt a message that was encrypted with your public key, regardless of the protocol on which it was received, assign the `*ecdsa.PrivateKey` to `KeyInfo`, and set its `Kind` to `node.Asymmetric`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/status-im/go-waku/waku/v2/utils"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/node"
|
||||||
|
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
keyInfo := &node.KeyInfo{
|
||||||
|
Kind: node.Symmetric,
|
||||||
|
PrivKey: ..., // Your private key
|
||||||
|
}
|
||||||
|
|
||||||
|
// This message could have arrived via any of these protocols: relay, filter, store
|
||||||
|
msg := &pb.WakuMessage{
|
||||||
|
Payload: ..., // Some encrypted payload
|
||||||
|
Version: 1,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.DecodeWakuMessage(msg, keyInfo); err != nil {
|
||||||
|
fmt.Println("Error decrypting the message payload: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(msg.Payload)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `WakuMessage` payload will be decrypted and available in plain text. Messages that can't be decrypted will return an `error`.
|
||||||
|
|
||||||
|
> To have access to the message author's public key and signature (if available) of the message, `DecodePayload(msg, keyInfo)` can be used instead. It will return a `DecodedPayload` instance containing `PubKey` and `Signature` attributes, and it's not a destructive operation, so the `WakuMessage` protobuffer will not be modified.
|
Loading…
Reference in New Issue