diff --git a/index.js b/index.js index 23bd82b071..828abf5519 100644 --- a/index.js +++ b/index.js @@ -359,6 +359,19 @@ exports.ecsign = function (msgHash, privateKey) { return ret } +/** + * Returns the keccak-256 hash of `message`, prefixed with the header used by the `eth_sign` RPC call. + * The output of this function can be fed into `ecsign` to produce the same signature as the `eth_sign` + * call for a given `message`, or fed to `ecrecover` along with a signature to recover the public key + * used to produce the signature. + * @param message + * @returns {Buffer} hash + */ +exports.hashPersonalMessage = function (message) { + var prefix = exports.toBuffer('\u0019Ethereum Signed Message:\n' + message.length.toString()) + return exports.sha3(Buffer.concat([prefix, message])) +} + /** * ECDSA public key recovery from signature * @param {Buffer} msgHash diff --git a/test/index.js b/test/index.js index b3351889ec..b449204964 100644 --- a/test/index.js +++ b/test/index.js @@ -479,6 +479,13 @@ describe('ecrecover', function () { }) }) +describe('hashPersonalMessage', function () { + it('should produce a deterministic hash', function () { + var h = ethUtils.hashPersonalMessage(Buffer.from('Hello world')) + assert.deepEqual(h, Buffer.from('8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', 'hex')) + }) +}) + describe('isValidSignature', function () { it('should fail on an invalid signature (shorter r))', function () { var r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1ab', 'hex')