mirror of https://github.com/waku-org/js-waku.git
Merge pull request #227 from status-im/179-eth-dm-encrypt
This commit is contained in:
commit
b8296648e4
|
@ -25,6 +25,7 @@ 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`.
|
||||
|
||||
### Fixed
|
||||
- Disable `keepAlive` if set to `0`.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,6 @@
|
|||
"@types/jest": "^26.0.15",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"eth-crypto": "^1.9.0",
|
||||
"ethers": "^5.2.0",
|
||||
"fontsource-roboto": "^4.0.0",
|
||||
"js-waku": "../../build/main",
|
||||
|
|
|
@ -124,6 +124,20 @@ function App() {
|
|||
};
|
||||
}, [waku, address]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!waku) return;
|
||||
if (!ethDmKeyPair) return;
|
||||
|
||||
waku.relay.addDecryptionPrivateKey(ethDmKeyPair.privateKey);
|
||||
|
||||
return function cleanUp() {
|
||||
if (!waku) return;
|
||||
if (!ethDmKeyPair) return;
|
||||
|
||||
waku.relay.deleteDecryptionPrivateKey(ethDmKeyPair.privateKey);
|
||||
};
|
||||
}, [waku, ethDmKeyPair]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!waku) return;
|
||||
if (!ethDmKeyPair) return;
|
||||
|
@ -147,9 +161,11 @@ function App() {
|
|||
};
|
||||
}, [waku, address, ethDmKeyPair]);
|
||||
|
||||
let peers = 0;
|
||||
let relayPeers = 0;
|
||||
let lightPushPeers = 0;
|
||||
if (waku) {
|
||||
peers = waku.libp2p.connectionManager.connections.size;
|
||||
relayPeers = waku.relay.getPeers().size;
|
||||
lightPushPeers = waku.lightPush.peers.length;
|
||||
}
|
||||
|
||||
let addressDisplay = '';
|
||||
|
@ -174,7 +190,7 @@ function App() {
|
|||
/>
|
||||
</IconButton>
|
||||
<Typography className={classes.peers} aria-label="connected-peers">
|
||||
{peers} peer{peers && peers > 1 ? 's' : ''}
|
||||
Peers: {relayPeers} relay, {lightPushPeers} light push
|
||||
</Typography>
|
||||
<Typography variant="h6" className={classes.title}>
|
||||
Ethereum Direct Message
|
||||
|
|
|
@ -40,9 +40,12 @@ export default function BroadcastPublicKey({
|
|||
setPublicKeyMsg(msg);
|
||||
encodePublicKeyWakuMessage(msg)
|
||||
.then((wakuMsg) => {
|
||||
waku.lightPush.push(wakuMsg).catch((e) => {
|
||||
console.error('Failed to send Public Key Message', e);
|
||||
});
|
||||
waku.lightPush
|
||||
.push(wakuMsg)
|
||||
.then((res) => console.log('Public Key Message pushed', res))
|
||||
.catch((e) => {
|
||||
console.error('Failed to send Public Key Message', e);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import '@ethersproject/shims';
|
||||
|
||||
import * as EthCrypto from 'eth-crypto';
|
||||
import { ethers } from 'ethers';
|
||||
import { Signer } from '@ethersproject/abstract-signer';
|
||||
import { DirectMessage, PublicKeyMessage } from './messaging/wire';
|
||||
import { PublicKeyMessage } from './messaging/wire';
|
||||
import { hexToBuf, equalByteArrays, bufToHex } from 'js-waku/lib/utils';
|
||||
import {
|
||||
generatePrivateKey,
|
||||
getPublicKey,
|
||||
} from 'js-waku/lib/waku_message/version_1';
|
||||
|
||||
export interface KeyPair {
|
||||
privateKey: string;
|
||||
publicKey: string;
|
||||
privateKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +20,9 @@ export interface KeyPair {
|
|||
* to make the private key.
|
||||
*/
|
||||
export async function generateEthDmKeyPair(): Promise<KeyPair> {
|
||||
return EthCrypto.createIdentity();
|
||||
const privateKey = generatePrivateKey();
|
||||
const publicKey = getPublicKey(privateKey);
|
||||
return { privateKey, publicKey };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,16 +32,15 @@ export async function generateEthDmKeyPair(): Promise<KeyPair> {
|
|||
*/
|
||||
export async function createPublicKeyMessage(
|
||||
web3Signer: Signer,
|
||||
ethDmPublicKey: string
|
||||
ethDmPublicKey: Uint8Array
|
||||
): Promise<PublicKeyMessage> {
|
||||
const ethAddress = await web3Signer.getAddress();
|
||||
const bytesEthDmPublicKey = hexToBuf(ethDmPublicKey);
|
||||
const signature = await web3Signer.signMessage(
|
||||
formatPublicKeyForSignature(bytesEthDmPublicKey)
|
||||
formatPublicKeyForSignature(ethDmPublicKey)
|
||||
);
|
||||
|
||||
return new PublicKeyMessage({
|
||||
ethDmPublicKey: bytesEthDmPublicKey,
|
||||
ethDmPublicKey: ethDmPublicKey,
|
||||
ethAddress: hexToBuf(ethAddress),
|
||||
signature: hexToBuf(signature),
|
||||
});
|
||||
|
@ -72,20 +76,3 @@ function formatPublicKeyForSignature(ethDmPublicKey: Uint8Array): string {
|
|||
ethDmPublicKey: bufToHex(ethDmPublicKey),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a Direct Message using the private key.
|
||||
*/
|
||||
export function decryptMessage(
|
||||
privateKey: string,
|
||||
directMessage: DirectMessage
|
||||
) {
|
||||
return EthCrypto.decryptWithPrivateKey(privateKey, directMessage.encMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt message with given Public Key
|
||||
*/
|
||||
export async function encryptMessage(publicKey: string, message: string) {
|
||||
return await EthCrypto.encryptWithPublicKey(publicKey, message);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
import React, { ChangeEvent, useState, KeyboardEvent } from 'react';
|
||||
import { Waku, WakuMessage } from 'js-waku';
|
||||
import { DirectMessage, encode } from './wire';
|
||||
import { encryptMessage } from '../crypto';
|
||||
import { DirectMessageContentTopic } from '../waku';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
|
@ -109,16 +108,15 @@ async function encodeEncryptedWakuMessage(
|
|||
publicKey: string,
|
||||
address: string
|
||||
): Promise<WakuMessage> {
|
||||
const encryptedMsg = await encryptMessage(publicKey, message);
|
||||
|
||||
const directMsg: DirectMessage = {
|
||||
toAddress: address,
|
||||
encMessage: encryptedMsg,
|
||||
message: message,
|
||||
};
|
||||
|
||||
const payload = encode(directMsg);
|
||||
return WakuMessage.fromBytes(payload, {
|
||||
contentTopic: DirectMessageContentTopic,
|
||||
encPublicKey: publicKey,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as EthCrypto from 'eth-crypto';
|
||||
import * as protobuf from 'protobufjs/light';
|
||||
|
||||
export interface PublicKeyMessagePayload {
|
||||
|
@ -61,7 +60,7 @@ export class PublicKeyMessage {
|
|||
*/
|
||||
export interface DirectMessage {
|
||||
toAddress: string;
|
||||
encMessage: EthCrypto.Encrypted;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function encode<T>(msg: T): Buffer {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { getStatusFleetNodes, Waku, WakuMessage } from 'js-waku';
|
||||
import { decode, DirectMessage, PublicKeyMessage } from './messaging/wire';
|
||||
import { decryptMessage, validatePublicKeyMessage } from './crypto';
|
||||
import { validatePublicKeyMessage } from './crypto';
|
||||
import { Message } from './messaging/Messages';
|
||||
import { bufToHex, equalByteArrays } from 'js-waku/lib/utils';
|
||||
|
||||
|
@ -58,31 +58,25 @@ export function handlePublicKeyMessage(
|
|||
|
||||
export async function handleDirectMessage(
|
||||
setter: Dispatch<SetStateAction<Message[]>>,
|
||||
privateKey: string,
|
||||
privateKey: Uint8Array,
|
||||
address: string,
|
||||
wakuMsg: WakuMessage
|
||||
) {
|
||||
console.log('Direct Message received:', wakuMsg);
|
||||
if (!wakuMsg.payload) return;
|
||||
const directMessage: DirectMessage = decode(wakuMsg.payload);
|
||||
// Only decrypt messages for us
|
||||
|
||||
if (!equalByteArrays(directMessage.toAddress, address)) return;
|
||||
|
||||
try {
|
||||
const text = await decryptMessage(privateKey, directMessage);
|
||||
const timestamp = wakuMsg.timestamp ? wakuMsg.timestamp : new Date();
|
||||
|
||||
const timestamp = wakuMsg.timestamp ? wakuMsg.timestamp : new Date();
|
||||
|
||||
console.log('Message decrypted:', text);
|
||||
setter((prevMsgs: Message[]) => {
|
||||
const copy = prevMsgs.slice();
|
||||
copy.push({
|
||||
text: text,
|
||||
timestamp: timestamp,
|
||||
});
|
||||
return copy;
|
||||
console.log('Message decrypted:', directMessage.message);
|
||||
setter((prevMsgs: Message[]) => {
|
||||
const copy = prevMsgs.slice();
|
||||
copy.push({
|
||||
text: directMessage.message,
|
||||
timestamp: timestamp,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(' Failed to decrypt message', e);
|
||||
}
|
||||
return copy;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export function hexToBuf(str: string): Buffer {
|
||||
return Buffer.from(str.replace(/^0x/i, ''), 'hex');
|
||||
export function hexToBuf(hex: string | Buffer | Uint8Array): Buffer {
|
||||
if (typeof hex === 'string') {
|
||||
return Buffer.from(hex.replace(/^0x/i, ''), 'hex');
|
||||
} else {
|
||||
return Buffer.from(hex);
|
||||
}
|
||||
}
|
||||
|
||||
export function bufToHex(buf: Uint8Array | Buffer | ArrayBuffer): string {
|
||||
|
|
|
@ -16,7 +16,7 @@ const dbg = debug('waku:message');
|
|||
export interface Options {
|
||||
contentTopic?: string;
|
||||
timestamp?: Date;
|
||||
encPublicKey?: Uint8Array;
|
||||
encPublicKey?: Uint8Array | string;
|
||||
sigPrivKey?: Uint8Array;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ export function clearEncode(
|
|||
|
||||
const remainder = rawSize % PaddingTarget;
|
||||
const paddingSize = PaddingTarget - remainder;
|
||||
const pad = randomBytes(paddingSize);
|
||||
const pad = Buffer.from(randomBytes(paddingSize));
|
||||
|
||||
if (!validateDataIntegrity(pad, paddingSize)) {
|
||||
throw new Error('failed to generate random padding of size ' + paddingSize);
|
||||
|
@ -110,9 +110,9 @@ export function clearDecode(
|
|||
*/
|
||||
export async function encryptAsymmetric(
|
||||
data: Uint8Array | Buffer,
|
||||
publicKey: Uint8Array | Buffer
|
||||
publicKey: Uint8Array | Buffer | string
|
||||
): Promise<Uint8Array> {
|
||||
return ecies.encrypt(Buffer.from(publicKey), Buffer.from(data));
|
||||
return ecies.encrypt(hexToBuf(publicKey), Buffer.from(data));
|
||||
}
|
||||
|
||||
export async function decryptAsymmetric(
|
||||
|
|
Loading…
Reference in New Issue