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

@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `WakuMessage` version 1 is partially supported, enabling asymmetrical encryption and signature of messages; - `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. 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 ### Fixed
- Disable `keepAlive` if set to `0`. - Disable `keepAlive` if set to `0`.

View File

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

View File

@ -55,21 +55,43 @@ export class PublicKeyMessage {
} }
} }
/** export interface DirectMessagePayload {
* Direct Encrypted Message used for private communication over the Waku network. toAddress: Uint8Array;
*/
export interface DirectMessage {
toAddress: string;
message: string; message: string;
} }
export function encode<T>(msg: T): Buffer { /**
const jsonStr = JSON.stringify(msg); * Direct Encrypted Message used for private communication over the Waku network.
return Buffer.from(jsonStr, 'utf-8'); */
} 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 { constructor(public payload: DirectMessagePayload) {}
const buf = Buffer.from(bytes);
const str = buf.toString('utf-8'); public encode(): Uint8Array {
return JSON.parse(str); 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 { Dispatch, SetStateAction } from 'react';
import { getStatusFleetNodes, Waku, WakuMessage } from 'js-waku'; 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 { validatePublicKeyMessage } from './crypto';
import { Message } from './messaging/Messages'; import { Message } from './messaging/Messages';
import { bufToHex, equalByteArrays } from 'js-waku/lib/utils'; import { bufToHex, equalByteArrays } from 'js-waku/lib/utils';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/proto'; 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> { export async function initWaku(): Promise<Waku> {
const waku = await Waku.create({}); const waku = await Waku.create({});
@ -64,8 +64,11 @@ export async function handleDirectMessage(
) { ) {
console.log('Direct Message received:', wakuMsg); console.log('Direct Message received:', wakuMsg);
if (!wakuMsg.payload) return; 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; if (!equalByteArrays(directMessage.toAddress, address)) return;
const timestamp = wakuMsg.timestamp ? wakuMsg.timestamp : new Date(); const timestamp = wakuMsg.timestamp ? wakuMsg.timestamp : new Date();

View File

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