diff --git a/examples/eth-dm/src/App.tsx b/examples/eth-dm/src/App.tsx index 707b8e8d6e..db5df849ff 100644 --- a/examples/eth-dm/src/App.tsx +++ b/examples/eth-dm/src/App.tsx @@ -3,7 +3,6 @@ import '@ethersproject/shims'; import React, { useEffect, useState } from 'react'; import './App.css'; import { Waku } from 'js-waku'; -import { ethers } from 'ethers'; import { Signer } from '@ethersproject/abstract-signer'; import { KeyPair } from './crypto'; import { Message } from './messaging/Messages'; @@ -26,8 +25,7 @@ import { initWaku, PublicKeyContentTopic, } from './waku'; - -declare let window: any; +import ConnectWallet from './ConnectWallet'; const theme = createMuiTheme({ palette: { @@ -70,27 +68,17 @@ const useStyles = makeStyles({ function App() { const [waku, setWaku] = useState(); const [signer, setSigner] = useState(); - const [ethDmKeyPair, setEthDmKeyPair] = useState(); - const [publicKeys, setPublicKeys] = useState>(new Map()); + const [EncryptionKeyPair, setEncryptionKeyPair] = useState< + KeyPair | undefined + >(); + const [publicKeys, setPublicKeys] = useState>( + new Map() + ); const [messages, setMessages] = useState([]); const [address, setAddress] = useState(); const classes = useStyles(); - useEffect(() => { - try { - window.ethereum - .request({ method: 'eth_requestAccounts' }) - .then((accounts: string[]) => { - const _provider = new ethers.providers.Web3Provider(window.ethereum); - setAddress(accounts[0]); - setSigner(_provider.getSigner()); - }); - } catch (e) { - console.error('No web3 provider available'); - } - }, [address, signer]); - // Waku initialization useEffect(() => { if (waku) return; @@ -106,7 +94,6 @@ function App() { useEffect(() => { if (!waku) return; - if (!address) return; const observerPublicKeyMessage = handlePublicKeyMessage.bind( {}, @@ -126,27 +113,26 @@ function App() { useEffect(() => { if (!waku) return; - if (!ethDmKeyPair) return; + if (!EncryptionKeyPair) return; - waku.relay.addDecryptionKey(ethDmKeyPair.privateKey); + waku.relay.addDecryptionKey(EncryptionKeyPair.privateKey); return function cleanUp() { if (!waku) return; - if (!ethDmKeyPair) return; + if (!EncryptionKeyPair) return; - waku.relay.deleteDecryptionKey(ethDmKeyPair.privateKey); + waku.relay.deleteDecryptionKey(EncryptionKeyPair.privateKey); }; - }, [waku, ethDmKeyPair]); + }, [waku, EncryptionKeyPair]); useEffect(() => { if (!waku) return; - if (!ethDmKeyPair) return; + if (!EncryptionKeyPair) return; if (!address) return; const observerDirectMessage = handleDirectMessage.bind( {}, setMessages, - ethDmKeyPair.privateKey, address ); @@ -159,7 +145,7 @@ function App() { DirectMessageContentTopic, ]); }; - }, [waku, address, ethDmKeyPair]); + }, [waku, address, EncryptionKeyPair]); let relayPeers = 0; let lightPushPeers = 0; @@ -202,14 +188,18 @@ function App() {
- Eth-DM Key Pair + Wallet + +
+
+ Encryption Key Pair setEthDmKeyPair(keyPair)} + encryptionKeyPair={EncryptionKeyPair} + setEncryptionKeyPair={setEncryptionKeyPair} />
diff --git a/examples/eth-dm/src/BroadcastPublicKey.tsx b/examples/eth-dm/src/BroadcastPublicKey.tsx index c302538f98..518be119f0 100644 --- a/examples/eth-dm/src/BroadcastPublicKey.tsx +++ b/examples/eth-dm/src/BroadcastPublicKey.tsx @@ -7,20 +7,20 @@ import { Signer } from '@ethersproject/abstract-signer'; import { PublicKeyContentTopic } from './waku'; interface Props { - ethDmKeyPair: KeyPair | undefined; + EncryptionKeyPair: KeyPair | undefined; waku: Waku | undefined; signer: Signer | undefined; } export default function BroadcastPublicKey({ signer, - ethDmKeyPair, + EncryptionKeyPair, waku, }: Props) { const [publicKeyMsg, setPublicKeyMsg] = useState(); const broadcastPublicKey = () => { - if (!ethDmKeyPair) return; + if (!EncryptionKeyPair) return; if (!signer) return; if (!waku) return; @@ -35,7 +35,7 @@ export default function BroadcastPublicKey({ console.log('Failed to encode Public Key Message in Waku Message'); }); } else { - createPublicKeyMessage(signer, ethDmKeyPair.publicKey) + createPublicKeyMessage(signer, EncryptionKeyPair.publicKey) .then((msg) => { setPublicKeyMsg(msg); encodePublicKeyWakuMessage(msg) @@ -64,9 +64,9 @@ export default function BroadcastPublicKey({ variant="contained" color="primary" onClick={broadcastPublicKey} - disabled={!ethDmKeyPair || !waku} + disabled={!EncryptionKeyPair || !waku} > - Broadcast Eth-DM Public Key + Broadcast Encryption Public Key ); } diff --git a/examples/eth-dm/src/ConnectWallet.tsx b/examples/eth-dm/src/ConnectWallet.tsx new file mode 100644 index 0000000000..cd575e2da5 --- /dev/null +++ b/examples/eth-dm/src/ConnectWallet.tsx @@ -0,0 +1,33 @@ +import { Button } from '@material-ui/core'; +import React from 'react'; +import { Signer } from '@ethersproject/abstract-signer'; +import { ethers } from 'ethers'; + +declare let window: any; + +interface Props { + setAddress: (address: string) => void; + setSigner: (signer: Signer) => void; +} + +export default function ConnectWallet({ setAddress, setSigner }: Props) { + const connectWallet = () => { + try { + window.ethereum + .request({ method: 'eth_requestAccounts' }) + .then((accounts: string[]) => { + const _provider = new ethers.providers.Web3Provider(window.ethereum); + setAddress(accounts[0]); + setSigner(_provider.getSigner()); + }); + } catch (e) { + console.error('No web3 provider available'); + } + }; + + return ( + + ); +} diff --git a/examples/eth-dm/src/crypto.ts b/examples/eth-dm/src/crypto.ts index abe65fc50f..aadb189da0 100644 --- a/examples/eth-dm/src/crypto.ts +++ b/examples/eth-dm/src/crypto.ts @@ -16,7 +16,7 @@ export interface KeyPair { * the entropy for the EthCrypto keypair. Note that the entropy is hashed with keccak256 * to make the private key. */ -export async function generateEthDmKeyPair(): Promise { +export async function generateEncryptionKeyPair(): Promise { const privateKey = generatePrivateKey(); const publicKey = getPublicKey(privateKey); return { privateKey, publicKey }; @@ -29,25 +29,25 @@ export async function generateEthDmKeyPair(): Promise { */ export async function createPublicKeyMessage( web3Signer: Signer, - ethDmPublicKey: Uint8Array + encryptionPublicKey: Uint8Array ): Promise { const ethAddress = await web3Signer.getAddress(); const signature = await web3Signer.signMessage( - formatPublicKeyForSignature(ethDmPublicKey) + formatPublicKeyForSignature(encryptionPublicKey) ); return new PublicKeyMessage({ - ethDmPublicKey: ethDmPublicKey, + encryptionPublicKey: encryptionPublicKey, ethAddress: hexToBuf(ethAddress), signature: hexToBuf(signature), }); } /** - * Validate that the EthDm Public Key was signed by the holder of the given Ethereum address. + * Validate that the Encryption Public Key was signed by the holder of the given Ethereum address. */ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean { - const formattedMsg = formatPublicKeyForSignature(msg.ethDmPublicKey); + const formattedMsg = formatPublicKeyForSignature(msg.encryptionPublicKey); try { const sigAddress = ethers.utils.verifyMessage(formattedMsg, msg.signature); return equalByteArrays(sigAddress, msg.ethAddress); @@ -63,13 +63,13 @@ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean { /** * Prepare Eth-Dm Public key to be signed for publication. - * The public key is set in on Object `{ ethDmPublicKey: string; }`, converted + * The public key is set in on Object `{ encryptionPublicKey: string; }`, converted * to JSON and then hashed with Keccak256. * The usage of the object helps ensure the signature is only used in an Eth-DM * context. */ -function formatPublicKeyForSignature(ethDmPublicKey: Uint8Array): string { +function formatPublicKeyForSignature(encryptionPublicKey: Uint8Array): string { return JSON.stringify({ - ethDmPublicKey: bufToHex(ethDmPublicKey), + encryptionPublicKey: bufToHex(encryptionPublicKey), }); } diff --git a/examples/eth-dm/src/key_pair_handling/KeyPairHandling.tsx b/examples/eth-dm/src/key_pair_handling/KeyPairHandling.tsx index a9db833941..c937cd1569 100644 --- a/examples/eth-dm/src/key_pair_handling/KeyPairHandling.tsx +++ b/examples/eth-dm/src/key_pair_handling/KeyPairHandling.tsx @@ -2,7 +2,7 @@ import { Button } from '@material-ui/core'; import { LoadKeyPair } from './LoadKeyPair'; import { SaveKeyPair } from './SaveKeyPair'; import React, { useState } from 'react'; -import { generateEthDmKeyPair, KeyPair } from '../crypto'; +import { generateEncryptionKeyPair, KeyPair } from '../crypto'; import { makeStyles } from '@material-ui/core/styles'; import PasswordInput from './PasswordInput'; @@ -29,24 +29,24 @@ const useStyles = makeStyles({ }); export interface Props { - ethDmKeyPair: KeyPair | undefined; - setEthDmKeyPair: (keyPair: KeyPair) => void; + encryptionKeyPair: KeyPair | undefined; + setEncryptionKeyPair: (keyPair: KeyPair) => void; } export default function KeyPairHandling({ - ethDmKeyPair, - setEthDmKeyPair, + encryptionKeyPair, + setEncryptionKeyPair, }: Props) { const classes = useStyles(); const [password, setPassword] = useState(); const generateKeyPair = () => { - if (ethDmKeyPair) return; + if (encryptionKeyPair) return; - generateEthDmKeyPair() + generateEncryptionKeyPair() .then((keyPair) => { - setEthDmKeyPair(keyPair); + setEncryptionKeyPair(keyPair); }) .catch((e) => { console.error('Failed to generate Key Pair', e); @@ -60,9 +60,9 @@ export default function KeyPairHandling({ variant="contained" color="primary" onClick={generateKeyPair} - disabled={!!ethDmKeyPair} + disabled={!!encryptionKeyPair} > - Generate Eth-DM Key Pair + Generate Encryption Key Pair
setEthDmKeyPair(keyPair)} - disabled={!!ethDmKeyPair} + setEncryptionKeyPair={(keyPair) => setEncryptionKeyPair(keyPair)} + disabled={!!encryptionKeyPair} password={password} />
- +
diff --git a/examples/eth-dm/src/key_pair_handling/LoadKeyPair.tsx b/examples/eth-dm/src/key_pair_handling/LoadKeyPair.tsx index 2a79cb37c0..9c857d14ff 100644 --- a/examples/eth-dm/src/key_pair_handling/LoadKeyPair.tsx +++ b/examples/eth-dm/src/key_pair_handling/LoadKeyPair.tsx @@ -4,19 +4,23 @@ import { loadKeyPairFromStorage } from './key_pair_storage'; import { KeyPair } from '../crypto'; export interface Props { - setEthDmKeyPair: (keyPair: KeyPair) => void; + setEncryptionKeyPair: (keyPair: KeyPair) => void; disabled: boolean; password: string | undefined; } -export function LoadKeyPair({ password, disabled, setEthDmKeyPair }: Props) { +export function LoadKeyPair({ + password, + disabled, + setEncryptionKeyPair, +}: Props) { const loadKeyPair = () => { if (disabled) return; if (!password) return; loadKeyPairFromStorage(password).then((keyPair: KeyPair | undefined) => { if (!keyPair) return; - console.log('EthDm KeyPair loaded from storage'); - setEthDmKeyPair(keyPair); + console.log('Encryption KeyPair loaded from storage'); + setEncryptionKeyPair(keyPair); }); }; @@ -27,7 +31,7 @@ export function LoadKeyPair({ password, disabled, setEthDmKeyPair }: Props) { onClick={loadKeyPair} disabled={!password || disabled} > - Load Eth-DM Key Pair from storage + Load Encryption Key Pair from storage ); } diff --git a/examples/eth-dm/src/key_pair_handling/SaveKeyPair.tsx b/examples/eth-dm/src/key_pair_handling/SaveKeyPair.tsx index f8fef3399a..8ec7648f97 100644 --- a/examples/eth-dm/src/key_pair_handling/SaveKeyPair.tsx +++ b/examples/eth-dm/src/key_pair_handling/SaveKeyPair.tsx @@ -4,16 +4,16 @@ import { KeyPair } from '../crypto'; import { saveKeyPairToStorage } from './key_pair_storage'; export interface Props { - ethDmKeyPair: KeyPair | undefined; + EncryptionKeyPair: KeyPair | undefined; password: string | undefined; } -export function SaveKeyPair({ password, ethDmKeyPair }: Props) { +export function SaveKeyPair({ password, EncryptionKeyPair }: Props) { const saveKeyPair = () => { - if (!ethDmKeyPair) return; + if (!EncryptionKeyPair) return; if (!password) return; - saveKeyPairToStorage(ethDmKeyPair, password).then(() => { - console.log('EthDm KeyPair saved to storage'); + saveKeyPairToStorage(EncryptionKeyPair, password).then(() => { + console.log('Encryption KeyPair saved to storage'); }); }; @@ -22,9 +22,9 @@ export function SaveKeyPair({ password, ethDmKeyPair }: Props) { variant="contained" color="primary" onClick={saveKeyPair} - disabled={!password || !ethDmKeyPair} + disabled={!password || !EncryptionKeyPair} > - Save Eth-DM Key Pair to storage + Save Encryption Key Pair to storage ); } diff --git a/examples/eth-dm/src/key_pair_handling/key_pair_storage.ts b/examples/eth-dm/src/key_pair_handling/key_pair_storage.ts index ccbb425515..1e52cb2f62 100644 --- a/examples/eth-dm/src/key_pair_handling/key_pair_storage.ts +++ b/examples/eth-dm/src/key_pair_handling/key_pair_storage.ts @@ -5,10 +5,10 @@ import { bufToHex, hexToBuf } from 'js-waku/lib/utils'; * Save keypair to storage, encrypted with password */ export async function saveKeyPairToStorage( - ethDmKeyPair: KeyPair, + EncryptionKeyPair: KeyPair, password: string ) { - const { salt, iv, cipher } = await encryptKey(ethDmKeyPair, password); + const { salt, iv, cipher } = await encryptKey(EncryptionKeyPair, password); const data = { salt: bufToHex(salt), @@ -16,7 +16,7 @@ export async function saveKeyPairToStorage( cipher: bufToHex(cipher), }; - localStorage.setItem('cipherEthDmKeyPair', JSON.stringify(data)); + localStorage.setItem('cipherEncryptionKeyPair', JSON.stringify(data)); } /** @@ -25,7 +25,7 @@ export async function saveKeyPairToStorage( export async function loadKeyPairFromStorage( password: string ): Promise { - const str = localStorage.getItem('cipherEthDmKeyPair'); + const str = localStorage.getItem('cipherEncryptionKeyPair'); if (!str) return; const data = JSON.parse(str); @@ -71,13 +71,13 @@ function getWrapKey(keyMaterial: CryptoKey, salt: Uint8Array) { /** * Encrypt Eth-DM KeyPair using provided password */ -async function encryptKey(ethDmKeyPair: KeyPair, password: string) { +async function encryptKey(encryptionKeyPair: KeyPair, password: string) { const keyMaterial = await getKeyMaterial(password); const salt = window.crypto.getRandomValues(new Uint8Array(16)); const wrappingKey = await getWrapKey(keyMaterial, salt); const enc = new TextEncoder(); - const encodedKeyPair = enc.encode(JSON.stringify(ethDmKeyPair)); + const encodedKeyPair = enc.encode(JSON.stringify(encryptionKeyPair)); const iv = window.crypto.getRandomValues(new Uint8Array(12)); const cipher = await window.crypto.subtle.encrypt( diff --git a/examples/eth-dm/src/messaging/Messaging.tsx b/examples/eth-dm/src/messaging/Messaging.tsx index 60d07ff98b..c17d61e9ce 100644 --- a/examples/eth-dm/src/messaging/Messaging.tsx +++ b/examples/eth-dm/src/messaging/Messaging.tsx @@ -14,7 +14,7 @@ const useStyles = makeStyles({ interface Props { waku: Waku | undefined; - recipients: Map; + recipients: Map; messages: Message[]; } diff --git a/examples/eth-dm/src/messaging/SendMessage.tsx b/examples/eth-dm/src/messaging/SendMessage.tsx index 464828479f..650597e8b2 100644 --- a/examples/eth-dm/src/messaging/SendMessage.tsx +++ b/examples/eth-dm/src/messaging/SendMessage.tsx @@ -25,7 +25,7 @@ const useStyles = makeStyles((theme) => ({ export interface Props { waku: Waku | undefined; // address, public key - recipients: Map; + recipients: Map; } export default function SendMessage({ waku, recipients }: Props) { @@ -106,7 +106,7 @@ export default function SendMessage({ waku, recipients }: Props) { async function encodeEncryptedWakuMessage( message: string, - publicKey: string, + publicKey: Uint8Array, address: string ): Promise { const directMsg = new DirectMessage({ @@ -123,7 +123,7 @@ async function encodeEncryptedWakuMessage( function sendMessage( waku: Waku, recipientAddress: string, - recipientPublicKey: string, + recipientPublicKey: Uint8Array, message: string, callback: (res: boolean) => void ) { diff --git a/examples/eth-dm/src/messaging/wire.ts b/examples/eth-dm/src/messaging/wire.ts index f9795288fb..4fa1d65750 100644 --- a/examples/eth-dm/src/messaging/wire.ts +++ b/examples/eth-dm/src/messaging/wire.ts @@ -1,7 +1,7 @@ import * as protobuf from 'protobufjs/light'; export interface PublicKeyMessagePayload { - ethDmPublicKey: Uint8Array; + encryptionPublicKey: Uint8Array; ethAddress: Uint8Array; signature: Uint8Array; } @@ -15,7 +15,7 @@ const Root = protobuf.Root, */ export class PublicKeyMessage { private static Type = new Type('PublicKeyMessage') - .add(new Field('ethDmPublicKey', 1, 'bytes')) + .add(new Field('encryptionPublicKey', 1, 'bytes')) .add(new Field('ethAddress', 2, 'bytes')) .add(new Field('signature', 3, 'bytes')); private static Root = new Root() @@ -35,15 +35,19 @@ export class PublicKeyMessage { const payload = PublicKeyMessage.Type.decode( bytes ) as unknown as PublicKeyMessagePayload; - if (!payload.signature || !payload.ethDmPublicKey || !payload.ethAddress) { + if ( + !payload.signature || + !payload.encryptionPublicKey || + !payload.ethAddress + ) { console.log('Field missing on decoded Public Key Message', payload); return; } return new PublicKeyMessage(payload); } - get ethDmPublicKey(): Uint8Array { - return this.payload.ethDmPublicKey; + get encryptionPublicKey(): Uint8Array { + return this.payload.encryptionPublicKey; } get ethAddress(): Uint8Array { diff --git a/examples/eth-dm/src/waku.ts b/examples/eth-dm/src/waku.ts index 99a2877fe0..1eded8b646 100644 --- a/examples/eth-dm/src/waku.ts +++ b/examples/eth-dm/src/waku.ts @@ -33,24 +33,25 @@ export async function initWaku(): Promise { } export function handlePublicKeyMessage( - myAddress: string, - setter: Dispatch>>, + myAddress: string | undefined, + setter: Dispatch>>, msg: WakuMessage ) { console.log('Public Key Message received:', msg); if (!msg.payload) return; const publicKeyMsg = PublicKeyMessage.decode(msg.payload); if (!publicKeyMsg) return; - const ethDmPublicKey = bufToHex(publicKeyMsg.ethDmPublicKey); - console.log(ethDmPublicKey, myAddress); if (myAddress && equalByteArrays(publicKeyMsg.ethAddress, myAddress)) return; const res = validatePublicKeyMessage(publicKeyMsg); console.log('Is Public Key Message valid?', res); if (res) { - setter((prevPks: Map) => { - prevPks.set(bufToHex(publicKeyMsg.ethAddress), ethDmPublicKey); + setter((prevPks: Map) => { + prevPks.set( + bufToHex(publicKeyMsg.ethAddress), + publicKeyMsg.encryptionPublicKey + ); return new Map(prevPks); }); } @@ -58,7 +59,6 @@ export function handlePublicKeyMessage( export async function handleDirectMessage( setter: Dispatch>, - privateKey: Uint8Array, address: string, wakuMsg: WakuMessage ) {