blockmason / lndr

Lending on the Blockchain
https://lndr.io/
9 stars 6 forks source link

local keygen, wallet management and tx signing #2

Closed aupiff closed 6 years ago

aupiff commented 6 years ago

We want this prototyped quickly, so we may opt for a JS solution using some combination of the projects in EthereumJS. Specifically,

After we prototype something running in nodejs (our Haskell CLI would make a subprocess call to this node code), we could work to create Haskell equivalents. Integrating the JS code into the mobile application will be particularly easy.

If we want meta-mask like seed-phrase functionality, we can use this library: https://github.com/MetaMask/KeyringController

aupiff commented 6 years ago

I just thought of a terminal application that does the sort of keygen and signing that we're interested in, testrpc. Referencing its source code might be useful.

aupiff commented 6 years ago

Another useful library: https://github.com/ethereumjs/ethereumjs-util

I think keygen is as simple as this:

const keythereum = require("keythereum");
const ethUtil = require("ethereumjs-util");

privKey = keythereum.create().privateKey;
address = ethUtil.bufferToHex(
      ethUtil.privateToAddress(privKey)
);

For one-off keys and testing this is good. For a nice user experience and deterministic wallets, we'll use higher-level libraries like KeyringController.

aupiff commented 6 years ago

Signing is straightforward as well.

let signature = ethUtil.ecsign(messageBuffer, privKey);

This ecsign function is exactly like the one in our js tests, but it uses the secp256k1 library for signing instead of web3.

exports.ecsign = function (msgHash, privateKey) {
  const sig = secp256k1.sign(msgHash, privateKey)

  const ret = {}
  ret.r = sig.signature.slice(0, 32)
  ret.s = sig.signature.slice(32, 64)
  ret.v = sig.recovery + 27
  return ret
}

Well, ethereumjs-util is a little cleaner because it operates on byte buffers instead of hex strings...

aupiff commented 6 years ago

For completeness, I wanted to mention that ethereumjs-util also includes an ecrecover function. This would be useful for testing that signatures are generated correctly or for P2P exchanges of unilateral CreditRecords.

/**
 * ECDSA public key recovery from signature
 * @param {Buffer} msgHash
 * @param {Number} v
 * @param {Buffer} r
 * @param {Buffer} s
 * @return {Buffer} publicKey
 */
exports.ecrecover = function (msgHash, v, r, s) {
  const signature = Buffer.concat([exports.setLength(r, 32), exports.setLength(s, 32)], 64)
  const recovery = v - 27
  if (recovery !== 0 && recovery !== 1) {
    throw new Error('Invalid signature v value')
  }
  const senderPubKey = secp256k1.recover(msgHash, signature, recovery)
  return secp256k1.publicKeyConvert(senderPubKey, false).slice(1)
}

https://github.com/ethereumjs/ethereumjs-util/blob/926f2d742c9d9e7853ef226a67e6ecd9179409b2/index.js#L362-L378

aupiff commented 6 years ago

I've figured out most of this in Haskell already and the mobile team understands what needs to be done in JS. Issue #8 will track the CLI's progress in integrating keygen, wallet & signing features.