Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use protobuf instead of JSON for direct messages #228

Merged
merged 1 commit into from
Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
11 changes: 6 additions & 5 deletions examples/eth-dm/src/messaging/SendMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down Expand Up @@ -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,
Expand Down
46 changes: 34 additions & 12 deletions examples/eth-dm/src/messaging/wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,43 @@ export class PublicKeyMessage {
}
}

export interface DirectMessagePayload {
toAddress: Uint8Array;
message: string;
}

/**
* Direct Encrypted Message used for private communication over the Waku network.
*/
export interface DirectMessage {
toAddress: string;
message: string;
}
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 encode<T>(msg: T): Buffer {
const jsonStr = JSON.stringify(msg);
return Buffer.from(jsonStr, 'utf-8');
}
constructor(public payload: DirectMessagePayload) {}

public encode(): Uint8Array {
const message = DirectMessage.Type.create(this.payload);
return DirectMessage.Type.encode(message).finish();
}

export function decode<T>(bytes: Uint8Array): T {
const buf = Buffer.from(bytes);
const str = buf.toString('utf-8');
return JSON.parse(str);
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;
}
}
11 changes: 7 additions & 4 deletions examples/eth-dm/src/waku.ts
Original file line number Diff line number Diff line change
@@ -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({});
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/waku_message/version_1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down