diff --git a/package-lock.json b/package-lock.json index d8ba3d2..9fb0946 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2567,6 +2567,22 @@ "xhr-request-promise": "0.1.2" } }, + "eth-sig-util": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", + "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", + "requires": { + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "ethereumjs-util": "5.2.0" + } + }, + "ethereumjs-abi": { + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "requires": { + "bn.js": "4.11.8", + "ethereumjs-util": "5.2.0" + } + }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", diff --git a/package.json b/package.json index 7b048d4..b6a9486 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "compression": "^1.7.1", "cors": "^2.8.4", "dotenv": "^4.0.0", + "eth-sig-util": "^1.4.2", "ethereumjs-util": "^5.2.0", "express": "^4.16.2", "file-type": "^7.7.1", diff --git a/src/config.js b/src/config.js index a1e614c..6521957 100644 --- a/src/config.js +++ b/src/config.js @@ -10,12 +10,18 @@ if (dotenvResult.error) { // this is the message that will be signed by MetaMask and checked against when // authenticating users -const personalMessageToSign = 'Please sign this message to authenticate with the Codex Title Registry.' +const typedDataToSign = [ + { + type: 'string', + name: 'Sign In', + value: 'Please sign this message to authenticate with the Codex Title Registry.', + }, +] const fullConfig = { development: { - personalMessageToSign, + typedDataToSign, mongodb: { dbUris: { @@ -55,7 +61,7 @@ const fullConfig = { staging: { - personalMessageToSign, + typedDataToSign, mongodb: { dbUris: { diff --git a/src/routes/auth-token/create.js b/src/routes/auth-token/create.js index 9d9d951..b050cfb 100644 --- a/src/routes/auth-token/create.js +++ b/src/routes/auth-token/create.js @@ -1,14 +1,12 @@ import Joi from 'joi' import jwt from 'jsonwebtoken' -import ethUtil from 'ethereumjs-util' +import ethSigUtil from 'eth-sig-util' import RestifyErrors from 'restify-errors' import models from '../../models' import config from '../../config' import logger from '../../services/logger' -const hashedPersonalMessage = ethUtil.hashPersonalMessage(ethUtil.toBuffer(config.personalMessageToSign)) - export default { method: 'post', @@ -16,15 +14,7 @@ export default { parameters: Joi.object().keys({ - // NOTE: the length of the signedData may change if the ethereumjs-util - // package is ever updated and the fromRpcSignature method changes it's - // length validation, as indicated by a comment in the source - // - // see: https://github.com/ethereumjs/ethereumjs-util/blob/fde15dd/index.js - // - // NOTE: signedData should not have the 0x prefix as Joi will validate it as - // a raw Buffer - signedData: Joi.binary().encoding('hex').length(65).required(), + signedData: Joi.string().required(), userAddress: Joi.string().regex(/^0x[0-9a-f]{40}$/i, 'ethereum address').lowercase().required(), @@ -36,17 +26,16 @@ export default { handler(request, response) { - // see: https://hackernoon.com/never-use-passwords-again-with-ethereum-and-metamask-b61c7e409f0d + // see: https://medium.com/metamask/scaling-web3-with-signtypeddata-91d6efc8b290 try { - const { v, r, s } = ethUtil.fromRpcSig(ethUtil.toBuffer(request.parameters.signedData)) - const publicKey = ethUtil.ecrecover(hashedPersonalMessage, v, r, s) - - const userAddressBuffer = ethUtil.toBuffer(request.parameters.userAddress) - const senderAddressBuffer = ethUtil.publicToAddress(publicKey) + const recoveredAddress = ethSigUtil.recoverTypedSignature({ + sig: request.parameters.signedData, + data: config.typedDataToSign, + }) - if (!senderAddressBuffer.equals(userAddressBuffer)) { + if (recoveredAddress !== request.parameters.userAddress) { // throw a blank error here since it'll just get picked up by the catch // below anyway throw new Error()