Change public key message encoding to protobuf

This commit is contained in:
Franck Royer 2021-07-01 11:52:07 +10:00
parent 90e39d3e0a
commit dc2c09bd41
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 261 additions and 18 deletions

View File

@ -19,6 +19,7 @@
"ethers": "^5.2.0", "ethers": "^5.2.0",
"fontsource-roboto": "^4.0.0", "fontsource-roboto": "^4.0.0",
"js-waku": "../../build/main", "js-waku": "../../build/main",
"protobufjs": "^6.11.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
@ -3705,6 +3706,60 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
},
"node_modules/@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
},
"node_modules/@protobufjs/codegen": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
},
"node_modules/@protobufjs/eventemitter": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
},
"node_modules/@protobufjs/fetch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
"dependencies": {
"@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0"
}
},
"node_modules/@protobufjs/float": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
},
"node_modules/@protobufjs/inquire": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
},
"node_modules/@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
},
"node_modules/@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
},
"node_modules/@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
},
"node_modules/@rollup/plugin-node-resolve": { "node_modules/@rollup/plugin-node-resolve": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz",
@ -4204,6 +4259,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
}, },
"node_modules/@types/long": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
},
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
@ -14838,6 +14898,11 @@
"url": "https://tidelift.com/funding/github/npm/loglevel" "url": "https://tidelift.com/funding/github/npm/loglevel"
} }
}, },
"node_modules/long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"node_modules/loose-envify": { "node_modules/loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -17973,6 +18038,31 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"node_modules/protobufjs": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
"integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==",
"hasInstallScript": true,
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
"@protobufjs/codegen": "^2.0.4",
"@protobufjs/eventemitter": "^1.1.0",
"@protobufjs/fetch": "^1.1.0",
"@protobufjs/float": "^1.0.2",
"@protobufjs/inquire": "^1.1.0",
"@protobufjs/path": "^1.1.2",
"@protobufjs/pool": "^1.1.0",
"@protobufjs/utf8": "^1.1.0",
"@types/long": "^4.0.1",
"@types/node": ">=13.7.0",
"long": "^4.0.0"
},
"bin": {
"pbjs": "bin/pbjs",
"pbts": "bin/pbts"
}
},
"node_modules/proxy-addr": { "node_modules/proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -26672,6 +26762,60 @@
} }
} }
}, },
"@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
},
"@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
},
"@protobufjs/codegen": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
},
"@protobufjs/eventemitter": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
},
"@protobufjs/fetch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
"requires": {
"@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0"
}
},
"@protobufjs/float": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
},
"@protobufjs/inquire": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
},
"@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
},
"@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
},
"@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
},
"@rollup/plugin-node-resolve": { "@rollup/plugin-node-resolve": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz",
@ -27034,6 +27178,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
}, },
"@types/long": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
},
"@types/minimatch": { "@types/minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
@ -35215,6 +35364,11 @@
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
"integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw=="
}, },
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"loose-envify": { "loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -37707,6 +37861,26 @@
} }
} }
}, },
"protobufjs": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
"integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==",
"requires": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
"@protobufjs/codegen": "^2.0.4",
"@protobufjs/eventemitter": "^1.1.0",
"@protobufjs/fetch": "^1.1.0",
"@protobufjs/float": "^1.0.2",
"@protobufjs/inquire": "^1.1.0",
"@protobufjs/path": "^1.1.2",
"@protobufjs/pool": "^1.1.0",
"@protobufjs/utf8": "^1.1.0",
"@types/long": "^4.0.1",
"@types/node": ">=13.7.0",
"long": "^4.0.0"
}
},
"proxy-addr": { "proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",

View File

@ -16,6 +16,7 @@
"ethers": "^5.2.0", "ethers": "^5.2.0",
"fontsource-roboto": "^4.0.0", "fontsource-roboto": "^4.0.0",
"js-waku": "../../build/main", "js-waku": "../../build/main",
"protobufjs": "^6.11.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",

View File

@ -1,7 +1,7 @@
import { Button } from '@material-ui/core'; import { Button } from '@material-ui/core';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { createPublicKeyMessage, KeyPair } from './crypto'; import { createPublicKeyMessage, KeyPair } from './crypto';
import { encode, PublicKeyMessage } from './messaging/wire'; import { PublicKeyMessage } from './messaging/wire';
import { WakuMessage, Waku } from 'js-waku'; import { WakuMessage, Waku } from 'js-waku';
import { Signer } from '@ethersproject/abstract-signer'; import { Signer } from '@ethersproject/abstract-signer';
import { PublicKeyContentTopic } from './InitWaku'; import { PublicKeyContentTopic } from './InitWaku';
@ -56,7 +56,9 @@ export default function BroadcastPublicKey({
); );
} }
function encodePublicKeyWakuMessage(ethDmMsg: PublicKeyMessage): WakuMessage { function encodePublicKeyWakuMessage(
const payload = encode(ethDmMsg); publicKeyMessage: PublicKeyMessage
): WakuMessage {
const payload = publicKeyMessage.encode();
return WakuMessage.fromBytes(payload, PublicKeyContentTopic); return WakuMessage.fromBytes(payload, PublicKeyContentTopic);
} }

View File

@ -1,10 +1,15 @@
import { Dispatch, SetStateAction, useEffect } from 'react'; import { Dispatch, SetStateAction, useEffect } from 'react';
import { Environment, getStatusFleetNodes, Waku, WakuMessage } from 'js-waku'; import { Environment, getStatusFleetNodes, Waku, WakuMessage } from 'js-waku';
import { decode, DirectMessage, PublicKeyMessage } from './messaging/wire'; import {
bytesToHexStr,
decode,
DirectMessage,
PublicKeyMessage,
} from './messaging/wire';
import { decryptMessage, KeyPair, validatePublicKeyMessage } from './crypto'; import { decryptMessage, KeyPair, validatePublicKeyMessage } from './crypto';
import { Message } from './messaging/Messages'; import { Message } from './messaging/Messages';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/json'; 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/json';
interface Props { interface Props {
@ -115,13 +120,15 @@ function handlePublicKeyMessage(
msg: WakuMessage msg: WakuMessage
) { ) {
if (!msg.payload) return; if (!msg.payload) return;
const publicKeyMsg: PublicKeyMessage = decode(msg.payload); const publicKeyMsg = PublicKeyMessage.decode(msg.payload);
if (publicKeyMsg.ethDmPublicKey === myPublicKey) return; const ethDmPublicKey = bytesToHexStr(publicKeyMsg.ethDmPublicKey);
if (ethDmPublicKey === myPublicKey) return;
const res = validatePublicKeyMessage(publicKeyMsg); const res = validatePublicKeyMessage(publicKeyMsg);
console.log(`Public Key Message Received, valid: ${res}`, publicKeyMsg); console.log(`Public Key Message Received, valid: ${res}`, publicKeyMsg);
setter((prevPks: Map<string, string>) => { setter((prevPks: Map<string, string>) => {
prevPks.set(publicKeyMsg.ethAddress, publicKeyMsg.ethDmPublicKey); prevPks.set(bytesToHexStr(publicKeyMsg.ethAddress), ethDmPublicKey);
return new Map(prevPks); return new Map(prevPks);
}); });
} }

View File

@ -3,7 +3,11 @@ import '@ethersproject/shims';
import * as EthCrypto from 'eth-crypto'; import * as EthCrypto from 'eth-crypto';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { Signer } from '@ethersproject/abstract-signer'; import { Signer } from '@ethersproject/abstract-signer';
import { DirectMessage, PublicKeyMessage } from './messaging/wire'; import {
bytesToHexStr,
DirectMessage,
PublicKeyMessage,
} from './messaging/wire';
export interface KeyPair { export interface KeyPair {
privateKey: string; privateKey: string;
@ -29,10 +33,19 @@ export async function createPublicKeyMessage(
ethDmPublicKey: string ethDmPublicKey: string
): Promise<PublicKeyMessage> { ): Promise<PublicKeyMessage> {
const ethAddress = await web3Signer.getAddress(); const ethAddress = await web3Signer.getAddress();
const sig = await web3Signer.signMessage( const signature = await web3Signer.signMessage(
formatPublicKeyForSignature(ethDmPublicKey) formatPublicKeyForSignature(ethDmPublicKey)
); );
return { ethDmPublicKey, ethAddress, sig };
const bytesEthDmPublicKey = Buffer.from(ethDmPublicKey, 'hex');
const bytesEthAddress = Buffer.from(ethAddress.replace(/0x/, ''), 'hex');
const bytesSignature = Buffer.from(signature.replace(/0x/, ''), 'hex');
return new PublicKeyMessage({
ethDmPublicKey: bytesEthDmPublicKey,
ethAddress: bytesEthAddress,
signature: bytesSignature,
});
} }
/** /**
@ -41,10 +54,10 @@ export async function createPublicKeyMessage(
export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean { export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean {
try { try {
const sigAddress = ethers.utils.verifyMessage( const sigAddress = ethers.utils.verifyMessage(
formatPublicKeyForSignature(msg.ethDmPublicKey), formatPublicKeyForSignature(bytesToHexStr(msg.ethDmPublicKey)),
msg.sig msg.signature
); );
return sigAddress === msg.ethAddress; return sigAddress === bytesToHexStr(msg.ethAddress);
} catch (e) { } catch (e) {
return false; return false;
} }

View File

@ -1,12 +1,58 @@
import * as EthCrypto from 'eth-crypto'; import * as EthCrypto from 'eth-crypto';
import * as protobuf from 'protobufjs/light';
export interface PublicKeyMessagePayload {
ethDmPublicKey: Uint8Array;
ethAddress: Uint8Array;
signature: Uint8Array;
}
const Root = protobuf.Root,
Type = protobuf.Type,
Field = protobuf.Field;
/** /**
* Message used to communicate the Eth-Dm public key linked to a given Ethereum account * Message used to communicate the Eth-Dm public key linked to a given Ethereum account
*/ */
export interface PublicKeyMessage { export class PublicKeyMessage {
ethDmPublicKey: string; private static Type = new Type('PublicKeyMessage')
ethAddress: string; .add(new Field('PublicKeyMessage', 1, 'bytes'))
sig: string; .add(new Field('ethAddress', 2, 'bytes'))
.add(new Field('signature', 3, 'bytes'));
private static Root = new Root()
.define('messages')
.add(PublicKeyMessage.Type);
constructor(public payload: PublicKeyMessagePayload) {}
public encode(): Uint8Array {
const message = PublicKeyMessage.Type.create(this.payload);
return PublicKeyMessage.Type.encode(message).finish();
}
public static decode(bytes: Uint8Array | Buffer): PublicKeyMessage {
const payload = PublicKeyMessage.Type.decode(
bytes
) as unknown as PublicKeyMessagePayload;
return new PublicKeyMessage(payload);
}
get ethDmPublicKey(): Uint8Array {
return this.payload.ethDmPublicKey;
}
get ethAddress(): Uint8Array {
return this.payload.ethAddress;
}
get signature(): Uint8Array {
return this.payload.signature;
}
}
export function bytesToHexStr(bytes: Uint8Array): string {
const buf = new Buffer(bytes);
return buf.toString('hex');
} }
/** /**