77 lines
2.3 KiB
TypeScript
Raw Normal View History

2021-06-11 15:33:29 +10:00
import '@ethersproject/shims';
2021-05-28 15:35:50 +10:00
import * as EthCrypto from 'eth-crypto';
import { ethers } from 'ethers';
import { Signer } from '@ethersproject/abstract-signer';
2021-06-15 15:29:41 +10:00
import { PublicKeyMessage } from './messages';
2021-05-28 15:35:50 +10:00
2021-06-11 15:33:29 +10:00
const Salt =
'Salt for Eth-Dm, do not share a signature of this message or others could decrypt your messages';
export interface KeyPair {
privateKey: string;
publicKey: string;
address: string;
}
2021-05-28 15:35:50 +10:00
/**
2021-06-11 15:33:29 +10:00
* Use the signature of the Salt ("Salt for eth-dm...") as
2021-05-28 15:35:50 +10:00
* the entropy for the EthCrypto keypair. Note that the entropy is hashed with keccak256
* to make the private key.
*/
2021-06-11 15:33:29 +10:00
export async function generateEthDmKeyPair(
web3Signer: Signer
): Promise<KeyPair> {
const signature = await web3Signer.signMessage(Salt);
// Need to remove '0x' prefix to allow buffer to decode the hex string.
const sigBuf = Buffer.from(signature.slice(2), 'hex');
const entropy = Buffer.concat([sigBuf, sigBuf]);
2021-05-28 15:35:50 +10:00
const keys = EthCrypto.createIdentity(entropy);
return keys;
}
/**
* Sign the Eth-DM public key with Web3. This can then be published to let other
* users know to use this Eth-DM public key to encrypt messages destinated to the
* Web3 account holder (ie, Ethereum Address holder).
*/
2021-06-11 15:33:29 +10:00
export async function createPublicKeyMessage(
web3Signer: Signer,
ethDmPublicKey: string
): Promise<PublicKeyMessage> {
2021-05-28 15:35:50 +10:00
const ethAddress = await web3Signer.getAddress();
2021-06-11 15:33:29 +10:00
const sig = await web3Signer.signMessage(
formatPublicKeyForSignature(ethDmPublicKey)
);
2021-05-28 15:35:50 +10:00
return { ethDmPublicKey, ethAddress, sig };
}
/**
* Validate that the EthDm Public Key was signed by the holder of the given Ethereum address.
2021-05-28 15:35:50 +10:00
*/
export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean {
2021-05-28 15:35:50 +10:00
try {
2021-06-11 15:33:29 +10:00
const sigAddress = ethers.utils.verifyMessage(
formatPublicKeyForSignature(msg.ethDmPublicKey),
msg.sig
);
return sigAddress === msg.ethAddress;
} catch (e) {
2021-05-28 15:35:50 +10:00
return false;
}
}
/**
* Prepare Eth-Dm Public key to be signed for publication.
* The public key is set in on Object `{ ethDmPublicKey: 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.
*/
2021-06-11 15:33:29 +10:00
function formatPublicKeyForSignature(ethDmPublicKey: string): string {
const txt = JSON.stringify({
ethDmPublicKey,
});
return txt;
2021-05-28 15:35:50 +10:00
}