Which function should be used to sign message locally? Which function is the most secure?
1 Answer
Which one you should use depends on whether you're running a node (like geth
or parity
), and whether that node has an unlocked account.
Scenarios:
- No node?
eth.accounts.sign
- Node with unlocked account?
eth.sign
- Node with locked account?
eth.personal.sign
eth.sign
eth.sign(dataToSign, address [, callback])
is a convenience function that accepts an address that your node controls, and returns a Promise for a string that is the signature. It will only work on accounts that are already unlocked.
Signs data using a specific account. This account needs to be unlocked.
A risk factor is leaving your account unlocked. That means that any process capable of interacting with your node has arbitrary access to act on your behalf.
eth.personal.sign
eth.personal.sign(dataToSign, address, password [, callback])
is nearly the same, but allows you to include a password for accounts that are locked.
Signs data using a specific account.
A risk factor is passing your account password around in plaintext. Anything with access to that variable has your password.
eth.accounts.sign
eth.accounts.sign(data, privateKey)
is a lower-level tool that allows you to pass in the private-key directly. It is synchronous, and returns more details than just the signature.
Signs arbitrary data. This data is before UTF-8 HEX decoded and enveloped as follows:
"\x19Ethereum Signed Message:\n" + message.length + message
.
A risk factor is passing your private key around in plaintext. Anything with access to that variable can do arbitrary things with your account.
Security
You're right to be paranoid, but the problems are less likely to come from the web3.js library itself, and more likely to come from how you store the variables, and ports you leave open for access. Note that web3.js v1 is still in beta, and I'm not sure when they last had a security audit.
Be very careful, and get your code audited by well-respected security professionals.
-
Are
eth.personal.sign
andeth.accounts.sign
compatible? Can you recover the signers address regardless of which of these two the message has been signed with? Dec 3, 2019 at 13:50 -
1It is meant to be, yes, but not every node implements
eth.personal.sign
the same, unfortunately. I can't recommend this approach anymore, and we started calling this signing approachdefunct
in web3.py. For simple things, I would recommend: EIP 191 with the0x01
version byte, or for more complex signatures, EIP 712 . Both are available ineth-account
: eth-account.readthedocs.io/en/stable/… and eth-account.readthedocs.io/en/stable/… respectively.– carverDec 3, 2019 at 19:58