Which function should be used to sign message locally? Which function is the most secure?

1 Answer 1


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.


  1. No node? eth.accounts.sign
  2. Node with unlocked account? eth.sign
  3. Node with locked account? eth.personal.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(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(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.


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 and eth.accounts.sign compatible? Can you recover the signers address regardless of which of these two the message has been signed with?
    – J. Hesters
    Commented Dec 3, 2019 at 13:50
  • 1
    It 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 approach defunct in web3.py. For simple things, I would recommend: EIP 191 with the 0x01 version byte, or for more complex signatures, EIP 712 . Both are available in eth-account: eth-account.readthedocs.io/en/stable/… and eth-account.readthedocs.io/en/stable/… respectively.
    – carver
    Commented Dec 3, 2019 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.