mirror of https://github.com/status-im/js-waku.git
Use EIP-712 to sign public key message
This commit is contained in:
parent
01696d074c
commit
076192aa66
|
@ -5,7 +5,7 @@
|
|||
- Private Messaging
|
||||
- React/TypeScript
|
||||
- Waku Light Push
|
||||
- Signature with Web3
|
||||
- Signature with Web3 using [EIP-712 v4: `eth_signTypedData_v4`](https://eips.ethereum.org/EIPS/eip-712)
|
||||
- Asymmetric Encryption
|
||||
- Usage of [`eth_decrypt`](https://docs.metamask.io/guide/rpc-api.html#eth-decrypt) Wallet API
|
||||
|
||||
|
|
|
@ -193,6 +193,7 @@ function App() {
|
|||
address={address}
|
||||
encryptionPublicKey={encPublicKey}
|
||||
waku={waku}
|
||||
providerRequest={provider?.provider?.request}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
|
|
|
@ -11,6 +11,9 @@ interface Props {
|
|||
waku: Waku | undefined;
|
||||
signer: Signer | undefined;
|
||||
address: string | undefined;
|
||||
providerRequest:
|
||||
| ((request: { method: string; params?: Array<any> }) => Promise<any>)
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export default function BroadcastPublicKey({
|
||||
|
@ -18,15 +21,22 @@ export default function BroadcastPublicKey({
|
|||
encryptionPublicKey,
|
||||
address,
|
||||
waku,
|
||||
providerRequest,
|
||||
}: Props) {
|
||||
const broadcastPublicKey = () => {
|
||||
if (!encryptionPublicKey) return;
|
||||
if (!signer) return;
|
||||
if (!address) return;
|
||||
if (!waku) return;
|
||||
if (!providerRequest) return;
|
||||
|
||||
console.log('Creating Public Key Message');
|
||||
createPublicKeyMessage(signer, address, encryptionPublicKey)
|
||||
createPublicKeyMessage(
|
||||
signer,
|
||||
address,
|
||||
encryptionPublicKey,
|
||||
providerRequest
|
||||
)
|
||||
.then((msg) => {
|
||||
console.log('Public Key Message created');
|
||||
encodePublicKeyWakuMessage(msg)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import '@ethersproject/shims';
|
||||
|
||||
import { ethers } from 'ethers';
|
||||
import { Signer } from '@ethersproject/abstract-signer';
|
||||
import { PublicKeyMessage } from './messaging/wire';
|
||||
import { hexToBuf, equalByteArrays, bufToHex } from 'js-waku/lib/utils';
|
||||
import * as sigUtil from 'eth-sig-util';
|
||||
|
||||
/**
|
||||
* Sign the Eth-DM public key with Web3. This can then be published to let other
|
||||
|
@ -13,12 +13,19 @@ import { hexToBuf, equalByteArrays, bufToHex } from 'js-waku/lib/utils';
|
|||
export async function createPublicKeyMessage(
|
||||
web3Signer: Signer,
|
||||
address: string,
|
||||
encryptionPublicKey: Uint8Array
|
||||
encryptionPublicKey: Uint8Array,
|
||||
providerRequest: (request: {
|
||||
method: string;
|
||||
params?: Array<any>;
|
||||
}) => Promise<any>
|
||||
): Promise<PublicKeyMessage> {
|
||||
console.log('Asking wallet to sign Public Key Message');
|
||||
const signature = await web3Signer.signMessage(
|
||||
formatPublicKeyForSignature(encryptionPublicKey)
|
||||
const signature = await signEncryptionKey(
|
||||
encryptionPublicKey,
|
||||
address,
|
||||
providerRequest
|
||||
);
|
||||
|
||||
console.log('Asking wallet to sign Public Key Message');
|
||||
console.log('Public Key Message signed');
|
||||
|
||||
return new PublicKeyMessage({
|
||||
|
@ -28,33 +35,68 @@ export async function createPublicKeyMessage(
|
|||
});
|
||||
}
|
||||
|
||||
function buildMsgParams(encryptionPublicKey: Uint8Array, fromAddress: string) {
|
||||
return JSON.stringify({
|
||||
domain: {
|
||||
chainId: 1,
|
||||
name: 'Ethereum Private Message over Waku',
|
||||
version: '1',
|
||||
},
|
||||
message: {
|
||||
encryptionPublicKey: bufToHex(encryptionPublicKey),
|
||||
ownerAddress: fromAddress,
|
||||
},
|
||||
// Refers to the keys of the *types* object below.
|
||||
primaryType: 'PublishEncryptionPublicKey',
|
||||
types: {
|
||||
EIP712Domain: [
|
||||
{ name: 'name', type: 'string' },
|
||||
{ name: 'version', type: 'string' },
|
||||
{ name: 'chainId', type: 'uint256' },
|
||||
],
|
||||
PublishEncryptionPublicKey: [
|
||||
{ name: 'encryptionPublicKey', type: 'string' },
|
||||
{ name: 'ownerAddress', type: 'string' },
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function signEncryptionKey(
|
||||
encryptionPublicKey: Uint8Array,
|
||||
fromAddress: string,
|
||||
providerRequest: (request: {
|
||||
method: string;
|
||||
params?: Array<any>;
|
||||
from?: string;
|
||||
}) => Promise<any>
|
||||
): Promise<Uint8Array> {
|
||||
const msgParams = buildMsgParams(encryptionPublicKey, fromAddress);
|
||||
|
||||
const result = await providerRequest({
|
||||
method: 'eth_signTypedData_v4',
|
||||
params: [fromAddress, msgParams],
|
||||
from: fromAddress,
|
||||
});
|
||||
|
||||
console.log('TYPED SIGNED:' + JSON.stringify(result));
|
||||
|
||||
return hexToBuf(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.encryptionPublicKey);
|
||||
try {
|
||||
const sigAddress = ethers.utils.verifyMessage(formattedMsg, msg.signature);
|
||||
return equalByteArrays(sigAddress, msg.ethAddress);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
'Failed to verify signature for Public Key Message',
|
||||
formattedMsg,
|
||||
msg
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Eth-Dm Public key to be signed for publication.
|
||||
* 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(encryptionPublicKey: Uint8Array): string {
|
||||
return JSON.stringify({
|
||||
encryptionPublicKey: bufToHex(encryptionPublicKey),
|
||||
const recovered = sigUtil.recoverTypedSignature_v4({
|
||||
data: JSON.parse(
|
||||
buildMsgParams(msg.encryptionPublicKey, '0x' + bufToHex(msg.ethAddress))
|
||||
),
|
||||
sig: '0x' + bufToHex(msg.signature),
|
||||
});
|
||||
|
||||
console.log('Recovered', recovered);
|
||||
console.log('ethAddress', '0x' + bufToHex(msg.ethAddress));
|
||||
|
||||
return equalByteArrays(recovered, msg.ethAddress);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue