Use protobuf instead of JSON for direct messages

This commit is contained in:
Franck Royer 2021-07-12 17:29:22 +10:00
parent b8296648e4
commit c2cef05c2d
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
5 changed files with 51 additions and 24 deletions

View File

@ -25,7 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Breaking**: `WakuMessage` constructor is now private, `from*` and `decode*` function should be used.
- `WakuMessage` version 1 is partially supported, enabling asymmetrical encryption and signature of messages;
this can be done by passing keys to `WakuMessage.from*` and `WakuMessage.decode*` methods.
- Examples (eth-dm): Use Waku Message version 1 encryption scheme instead of `eth-crypto`.
- Examples (eth-dm): Use Waku Message version 1 encryption scheme instead of `eth-crypto`.
- Examples (eth-dm): Use Protobuf for direct messages instead of JSON ([#214](https://github.com/status-im/js-waku/issues/214)).
### Fixed
- Disable `keepAlive` if set to `0`.

View File

@ -8,7 +8,8 @@ import {
} from '@material-ui/core';
import React, { ChangeEvent, useState, KeyboardEvent } from 'react';
import { Waku, WakuMessage } from 'js-waku';
import { DirectMessage, encode } from './wire';
import { hexToBuf } from 'js-waku/lib/utils';
import { DirectMessage } from './wire';
import { DirectMessageContentTopic } from '../waku';
const useStyles = makeStyles((theme) => ({
@ -108,12 +109,12 @@ async function encodeEncryptedWakuMessage(
publicKey: string,
address: string
): Promise<WakuMessage> {
const directMsg: DirectMessage = {
toAddress: address,
const directMsg = new DirectMessage({
toAddress: hexToBuf(address),
message: message,
};
});
const payload = encode(directMsg);
const payload = directMsg.encode();
return WakuMessage.fromBytes(payload, {
contentTopic: DirectMessageContentTopic,
encPublicKey: publicKey,

View File

@ -55,21 +55,43 @@ export class PublicKeyMessage {
}
}
/**
* Direct Encrypted Message used for private communication over the Waku network.
*/
export interface DirectMessage {
toAddress: string;
export interface DirectMessagePayload {
toAddress: Uint8Array;
message: string;
}
export function encode<T>(msg: T): Buffer {
const jsonStr = JSON.stringify(msg);
return Buffer.from(jsonStr, 'utf-8');
}
/**
* Direct Encrypted Message used for private communication over the Waku network.
*/
export class DirectMessage {
private static Type = new Type('DirectMessage')
.add(new Field('toAddress', 1, 'bytes'))
.add(new Field('message', 2, 'string'));
private static Root = new Root().define('messages').add(DirectMessage.Type);
export function decode<T>(bytes: Uint8Array): T {
const buf = Buffer.from(bytes);
const str = buf.toString('utf-8');
return JSON.parse(str);
constructor(public payload: DirectMessagePayload) {}
public encode(): Uint8Array {
const message = DirectMessage.Type.create(this.payload);
return DirectMessage.Type.encode(message).finish();
}
public static decode(bytes: Uint8Array | Buffer): DirectMessage | undefined {
const payload = DirectMessage.Type.decode(
bytes
) as unknown as DirectMessagePayload;
if (!payload.toAddress || !payload.message) {
console.log('Field missing on decoded Direct Message', payload);
return;
}
return new DirectMessage(payload);
}
get toAddress(): Uint8Array {
return this.payload.toAddress;
}
get message(): string {
return this.payload.message;
}
}

View File

@ -1,12 +1,12 @@
import { Dispatch, SetStateAction } from 'react';
import { getStatusFleetNodes, Waku, WakuMessage } from 'js-waku';
import { decode, DirectMessage, PublicKeyMessage } from './messaging/wire';
import { DirectMessage, PublicKeyMessage } from './messaging/wire';
import { validatePublicKeyMessage } from './crypto';
import { Message } from './messaging/Messages';
import { bufToHex, equalByteArrays } from 'js-waku/lib/utils';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/proto';
export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json';
export const DirectMessageContentTopic = '/eth-dm/1/direct-message/proto';
export async function initWaku(): Promise<Waku> {
const waku = await Waku.create({});
@ -64,8 +64,11 @@ export async function handleDirectMessage(
) {
console.log('Direct Message received:', wakuMsg);
if (!wakuMsg.payload) return;
const directMessage: DirectMessage = decode(wakuMsg.payload);
const directMessage = DirectMessage.decode(wakuMsg.payload);
if (!directMessage) {
console.log('Failed to decode Direct Message');
return;
}
if (!equalByteArrays(directMessage.toAddress, address)) return;
const timestamp = wakuMsg.timestamp ? wakuMsg.timestamp : new Date();

View File

@ -28,7 +28,7 @@ export function clearEncode(
): { payload: Uint8Array; sig?: Signature } {
let envelope = Buffer.from([0]); // No flags
envelope = addPayloadSizeField(envelope, messagePayload);
envelope = Buffer.concat([envelope, messagePayload]);
envelope = Buffer.concat([envelope, Buffer.from(messagePayload)]);
// Calculate padding:
let rawSize =