Last active
June 18, 2023 02:08
-
-
Save bluet/e944003d6d2069666799cb398d48bb01 to your computer and use it in GitHub Desktop.
eth-crypto and web3, public key retrieving, sign, recover and encrypting test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-console */ | |
const EthCrypto = require("eth-crypto"); | |
const sigUtil = require("@metamask/eth-sig-util"); | |
const ethUtil = require("ethereumjs-util"); | |
async function test (provider, selectedAccount) { | |
// eslint-disable-next-line no-undef | |
const web3 = new Web3(provider); | |
// const accounts = await web3.eth.getAccounts(); | |
// selectedAccount = accounts[0]; | |
console.log("Wallet is", web3.eth.accounts.wallet); | |
// | |
// Get signature | |
// | |
console.warn("Get signature\n================"); | |
// Deprecated: This works must shows warning. | |
// https://ethereum.stackexchange.com/questions/41993/how-to-encrypt-a-message-using-only-the-public-key-from-web3-eth-sign/63983#63983 | |
// let secretMsgSignature = await web3.eth.sign( | |
// web3.eth.accounts.hashMessage("Secret message"), | |
// selectedAccount | |
// ); | |
// console.log("Signature is", secretMsgSignature); | |
const secretMsgSignature = await new Promise((resolve, reject) => { | |
window.ethereum.sendAsync({ | |
"method": "personal_sign", | |
"params": [web3.utils.utf8ToHex("Secret message"), selectedAccount], | |
"from": selectedAccount, | |
}, (err, response) => { | |
if (err) {return reject(err);} | |
resolve(response.result); | |
}); | |
}); | |
console.log("Signature is", secretMsgSignature); | |
// | |
// Get signers address from signatures | |
// | |
console.warn("Get signers address from signatures\n================"); | |
let signerAddress = EthCrypto.recover( | |
secretMsgSignature, | |
web3.eth.accounts.hashMessage("Secret message") | |
); | |
console.log("Signer address is", signerAddress); | |
// | |
// Get public key | |
// | |
console.warn("Get public key\n================"); | |
const pubkey_ethcrypto = EthCrypto.recoverPublicKey( | |
secretMsgSignature, | |
web3.eth.accounts.hashMessage("Secret message") | |
); | |
console.log("EthCrypto: My public key is", pubkey_ethcrypto); | |
let pubkey_ethcrypto_compressed = EthCrypto.publicKey.compress(pubkey_ethcrypto); | |
console.log("EthCrypto: My public key compressed is", pubkey_ethcrypto_compressed); | |
console.log("EthCrypto: My public key compressed length is", pubkey_ethcrypto_compressed.length); | |
// | |
// Get Public Key from Ethereum (MetaMask) | |
// | |
console.warn("Get Public Key from Ethereum (MetaMask)\n================"); | |
let pubkey_eth = await window.ethereum.request({ | |
"method": "eth_getEncryptionPublicKey", | |
"params": [selectedAccount], // you must have access to the specified account | |
}); | |
console.log("window.Ethereum: My public Key from Ethereum (MetaMask):", pubkey_eth); | |
console.log("window.Ethereum: My public key from Ethereum (MetaMask) is", Buffer.from(pubkey_eth, "base64").toString("hex")); | |
console.log("window.Ethereum: My public key from Ethereum (MetaMask) length is", Buffer.from(pubkey_eth, "base64").toString("hex").length); | |
let pubkey_eth_decompressed_prefix02 = EthCrypto.publicKey.decompress("02" + Buffer.from(pubkey_eth, "base64").toString("hex")); | |
console.log("window.Ethereum: My public key decompressed (prefix 02) from Ethereum (MetaMask) is", pubkey_eth_decompressed_prefix02); | |
console.log("window.Ethereum: My public key decompressed (prefix 02) length from Ethereum (MetaMask) is", pubkey_eth_decompressed_prefix02.length); | |
let pubkey_eth_decompressed_prefix03 = EthCrypto.publicKey.decompress("03" + Buffer.from(pubkey_eth, "base64").toString("hex")); | |
console.log("window.Ethereum: My public key decompressed (prefix 03) from Ethereum (MetaMask) is", pubkey_eth_decompressed_prefix03); | |
console.log("window.Ethereum: My public key decompressed (prefix 03) length from Ethereum (MetaMask) is", pubkey_eth_decompressed_prefix03.length); | |
// | |
// Encrypt message | |
// | |
console.warn("Encrypt message\n================"); | |
// Encrypt message: Use EthCrypto with EthCrypto public key | |
console.info("Encrypt message: Use EthCrypto with EthCrypto public key"); | |
const encmsg_ethcrypto_ethcryptokey_raw = await EthCrypto.encryptWithPublicKey( | |
pubkey_ethcrypto, | |
"Secret message" | |
); | |
const encmsg_ethcrypto_ethcryptokey = ethUtil.bufferToHex( | |
Buffer.from( | |
JSON.stringify( | |
encmsg_ethcrypto_ethcryptokey_raw | |
), | |
"utf8" | |
) | |
); | |
console.log("EthCrypto: Raw encrypted message (ethcrypto key) is", encmsg_ethcrypto_ethcryptokey_raw); | |
console.log("EthCrypto: Message encrypted (ethcrypto key) is", encmsg_ethcrypto_ethcryptokey); | |
console.log("EthCrypto: Message encrypted (ethcrypto key) EthCrypto.cipher.stringify is", EthCrypto.cipher.stringify(encmsg_ethcrypto_ethcryptokey_raw)); | |
// Encrypt message: Use EthCrypto with Ethereum (MetaMask) public key | |
console.info("Encrypt message: Use EthCrypto with Ethereum (MetaMask) public key"); | |
const encmsg_ethcrypto_ethkey_prefix02_raw = await EthCrypto.encryptWithPublicKey( | |
pubkey_eth_decompressed_prefix02, // pubkey_eth is the public key of the Ethereum (MetaMask) account | |
"Secret message" | |
); | |
const encmsg_ethcrypto_ethkey_prefix02 = ethUtil.bufferToHex( | |
Buffer.from(JSON.stringify(encmsg_ethcrypto_ethkey_prefix02_raw), "utf8") | |
); | |
console.log( | |
"EthCrypto: Raw encrypted message (eth key prefix 02) is", | |
encmsg_ethcrypto_ethkey_prefix02_raw | |
); | |
console.log("EthCrypto: Message encrypted (eth key prefix 02) is", encmsg_ethcrypto_ethkey_prefix02); | |
const encmsg_ethcrypto_ethkey_prefix03_raw = await EthCrypto.encryptWithPublicKey( | |
pubkey_eth_decompressed_prefix03, // pubkey_eth is the public key of the Ethereum (MetaMask) account | |
"Secret message" | |
); | |
const encmsg_ethcrypto_ethkey_prefix03 = ethUtil.bufferToHex( | |
Buffer.from(JSON.stringify(encmsg_ethcrypto_ethkey_prefix03_raw), "utf8") | |
); | |
console.log( | |
"EthCrypto: Raw encrypted message (eth key prefix 03) is", | |
encmsg_ethcrypto_ethkey_prefix03_raw | |
); | |
console.log("EthCrypto: Message encrypted (eth key prefix 03) is", encmsg_ethcrypto_ethkey_prefix03); | |
// Encrypt message: Use Ethereum with EthCrypto public key | |
console.info("Encrypt message: Use Ethereum with EthCrypto public key"); | |
const encmsg_eth_ethcryptokey_raw = sigUtil.encrypt({ | |
"publicKey": Buffer.from(pubkey_ethcrypto_compressed.substring(2), "hex").toString( | |
"base64" | |
), | |
"data": "Secret message", | |
"version": "x25519-xsalsa20-poly1305", | |
}); | |
const encmsg_eth_ethcryptokey = ethUtil.bufferToHex( | |
Buffer.from(JSON.stringify(encmsg_eth_ethcryptokey_raw), "utf8") | |
); | |
console.log("sigUtil: Raw encrypted message (ethcrypto key) is", encmsg_eth_ethcryptokey_raw); | |
console.log("sigUtil: Message encrypted (ethcrypto key) is: ", encmsg_eth_ethcryptokey); | |
// Encrypt message: Use Ethereum with Ethereum (MetaMask) public key | |
console.info("Encrypt message: Use Ethereum with Ethereum (MetaMask) public key"); | |
const encmsg_eth_ethkey_raw = sigUtil.encrypt({ | |
"publicKey": pubkey_eth, | |
"data": "Secret message", | |
"version": "x25519-xsalsa20-poly1305", | |
}); | |
const encmsg_eth_ethkey = ethUtil.bufferToHex( | |
Buffer.from( | |
JSON.stringify( | |
encmsg_eth_ethkey_raw | |
), | |
"utf8" | |
) | |
); | |
console.log("sigUtil: Raw encrypted message (eth key) is", encmsg_eth_ethkey_raw); | |
console.log("sigUtil: Message encrypted (eth key) is: ", encmsg_eth_ethkey); | |
// | |
// Decrypt message | |
// | |
console.warn("Decrypt messages\n================"); | |
// Decrypt message: Use Ethereum with Ethereum public key | |
// console.info("Decrypt message: Use Ethereum with Ethereum public key"); | |
// const decmsg_eth_byEth = await window.ethereum.request({ | |
// "method": "eth_decrypt", | |
// "params": [encmsg_eth_ethkey, selectedAccount], // you must have access to the specified account | |
// }); | |
// console.log("window.Ethereum: Decrypted message from Ethereum is: ", decmsg_eth_byEth); | |
} |
From @Ismael's comment and MetaMask github issue:
- The key from MetaMask's
eth_getEncryptionPublicKey
rpc is NOT the Public Key of my account, but a different key calculated from my private key with the nacl implementation of the X25519_XSalsa20_Poly1305 algorithm, which is different from Ethereum's default algorithm. - MetaMask holds the private key, but it doesn't provide a function to decrypt messages with the private key.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Update:
But message decrypting doesn't work in
public key from eth_getEncryptionPublicKey
+eth_decrypt
.