Change seed file with a bip39 mnemonic (#207)
* Change seed file with a bip39 mnemonic * Create helper for bip39 mnemonic * Prod mode on lamassu-update-to-mnemonic script * Fix standard styling issues
This commit is contained in:
parent
809bf5a2a9
commit
d97a33565f
10 changed files with 98 additions and 34 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -30,6 +30,7 @@ raqia.json
|
|||
|
||||
scratch/
|
||||
seeds/
|
||||
mnemonics/
|
||||
certs/
|
||||
lamassu.json
|
||||
|
||||
|
|
|
|||
9
bin/bip39
Executable file
9
bin/bip39
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
||||
|
||||
const seed = process.argv[2]
|
||||
|
||||
console.log(mnemonicHelpers.fromSeed(seed))
|
||||
|
|
@ -16,12 +16,13 @@ OFAC_DATA_DIR=$CONFIG_DIR/ofac
|
|||
mkdir -p $CERT_DIR
|
||||
mkdir -p $CONFIG_DIR >> $LOG_FILE 2>&1
|
||||
|
||||
echo "Generating seed..."
|
||||
SEEDS_DIR=seeds
|
||||
SEED_FILE=$SEEDS_DIR/seed.txt
|
||||
mkdir -p $SEEDS_DIR >> $LOG_FILE 2>&1
|
||||
SEED=$(openssl rand -hex 32)
|
||||
echo $SEED > $SEED_FILE
|
||||
echo "Generating mnemonic..."
|
||||
MNEMONIC_DIR=$CONFIG_DIR/mnemonics
|
||||
MNEMONIC_FILE=$MNEMONIC_DIR/mnemonic.txt
|
||||
mkdir -p $MNEMONIC_DIR >> $LOG_FILE 2>&1
|
||||
SEED=$(openssl-1.0 rand -hex 32)
|
||||
MNEMONIC=$($PWD/bin/bip39 $SEED)
|
||||
echo "$MNEMONIC" > $MNEMONIC_FILE
|
||||
|
||||
echo "Generating SSL certificates..."
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ touch $OFAC_DATA_DIR/etags.json
|
|||
cat <<EOF > $CONFIG_DIR/lamassu.json
|
||||
{
|
||||
"postgresql": "psql://postgres:$POSTGRES_PASS@localhost/lamassu",
|
||||
"seedPath": "$SEED_FILE",
|
||||
"mnemonicPath": "$MNEMONIC_FILE",
|
||||
"caPath": "$CA_PATH",
|
||||
"certPath": "$SERVER_CERT_PATH",
|
||||
"keyPath": "$SERVER_KEY_PATH",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
const bip39 = require('bip39')
|
||||
|
||||
const options = require('../lib/options')
|
||||
|
||||
const seed = fs.readFileSync(options.seedPath, 'utf8').trim()
|
||||
|
||||
const words = bip39.entropyToMnemonic(seed).split(' ')
|
||||
|
||||
for (let i = 0; i < words.length; i += 6) {
|
||||
console.log(words.slice(i, i + 6).join(' '))
|
||||
}
|
||||
const mnemonic = fs.readFileSync(options.mnemonicPath, 'utf8').trim()
|
||||
console.log(mnemonic)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ set -e
|
|||
export LOG_FILE=/tmp/update.$(date +"%Y%m%d").log
|
||||
export NPM_BIN=$(npm -g bin)
|
||||
|
||||
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
|
||||
|
||||
rm -f ${LOG_FILE}
|
||||
|
||||
decho () {
|
||||
|
|
@ -55,6 +57,9 @@ decho "running migration"
|
|||
lamassu-migrate >> ${LOG_FILE} 2>&1
|
||||
lamassu-migrate-config >> ${LOG_FILE} 2>&1
|
||||
|
||||
decho "update to mnemonic"
|
||||
$SCRIPTPATH/bin/lamassu-update-to-mnemonic --prod
|
||||
|
||||
decho "updating supervisor conf"
|
||||
perl -i -pe 's/command=.*/command=$ENV{NPM_BIN}\/lamassu-server/g' /etc/supervisor/conf.d/lamassu-server.conf >> ${LOG_FILE} 2>&1
|
||||
perl -i -pe 's/command=.*/command=$ENV{NPM_BIN}\/lamassu-admin-server/g' /etc/supervisor/conf.d/lamassu-admin-server.conf >> ${LOG_FILE} 2>&1
|
||||
|
|
|
|||
30
bin/lamassu-update-to-mnemonic
Executable file
30
bin/lamassu-update-to-mnemonic
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
||||
const options = require('../lib/options-loader')()
|
||||
|
||||
if (!options.opts.mnemonicPath && options.opts.seedPath) {
|
||||
const seed = fs.readFileSync(options.opts.seedPath, 'utf8').trim()
|
||||
const mnemonic = mnemonicHelpers.fromSeed(seed)
|
||||
|
||||
if (process.argv[2] === '--prod') {
|
||||
options.opts.mnemonicPath = path.resolve('etc', 'lamassu', 'mnemonics', 'mnemonic.txt')
|
||||
} else {
|
||||
options.opts.mnemonicPath = path.resolve(os.homedir(), '.lamassu', 'mnemonics', 'mnemonic.txt')
|
||||
}
|
||||
|
||||
if (!fs.existsSync(path.dirname(options.opts.mnemonicPath))) {
|
||||
fs.mkdirSync(path.dirname(options.opts.mnemonicPath))
|
||||
}
|
||||
|
||||
if (!fs.existsSync(options.opts.mnemonicPath)) {
|
||||
fs.writeFileSync(options.opts.mnemonicPath, mnemonic, 'utf8')
|
||||
}
|
||||
|
||||
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"seedPath": "/etc/lamassu/seeds/seed.txt",
|
||||
"mnemonicPath": "/etc/lamassu/mnemonics/mnemonic.txt",
|
||||
"caPath": "/etc/ssl/certs/Lamassu_OP_Root_CA.pem",
|
||||
"certPath": "/etc/ssl/certs/Lamassu_OP.pem",
|
||||
"keyPath": "/etc/ssl/private/Lamassu_OP.key",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const pify = require('pify')
|
|||
const fs = pify(require('fs'))
|
||||
|
||||
const db = require('../db')
|
||||
const mnemonicHelpers = require('../mnemonic-helpers')
|
||||
const configManager = require('../config-manager')
|
||||
const options = require('../options')
|
||||
const logger = require('../logger')
|
||||
|
|
@ -129,17 +130,19 @@ function sendRadar (data) {
|
|||
|
||||
function mapRecord (info) {
|
||||
const timestamp = new Date().toISOString()
|
||||
return Promise.all([getMachines(info), fs.readFile(options.seedPath, 'utf8')])
|
||||
.then(([machines, hex]) => ({
|
||||
operatorId: computeOperatorId(Buffer.from(hex.trim(), 'hex')),
|
||||
operator: {
|
||||
name: null,
|
||||
phone: null,
|
||||
email: null
|
||||
},
|
||||
timestamp,
|
||||
machines
|
||||
}))
|
||||
return Promise.all([getMachines(info), fs.readFile(options.mnemonicPath, 'utf8')])
|
||||
.then(([machines, mnemonic]) => {
|
||||
return {
|
||||
operatorId: computeOperatorId(mnemonicHelpers.toEntropyBuffer(mnemonic)),
|
||||
operator: {
|
||||
name: null,
|
||||
phone: null,
|
||||
email: null
|
||||
},
|
||||
timestamp,
|
||||
machines
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function update (info) {
|
||||
|
|
|
|||
19
lib/mnemonic-helpers.js
Normal file
19
lib/mnemonic-helpers.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
const bip39 = require('bip39')
|
||||
const os = require('os')
|
||||
|
||||
function fromSeed (seed) {
|
||||
const words = bip39.entropyToMnemonic(seed).split(' ')
|
||||
|
||||
let mnemonic = ''
|
||||
for (let i = 0; i < words.length; i += 6) {
|
||||
mnemonic += words.slice(i, i + 6).join(' ') + os.EOL
|
||||
}
|
||||
return mnemonic
|
||||
}
|
||||
|
||||
function toEntropyBuffer (mnemonic) {
|
||||
const hex = bip39.mnemonicToEntropy(mnemonic.split('\n').join(' ').trim())
|
||||
return Buffer.from(hex.trim(), 'hex')
|
||||
}
|
||||
|
||||
module.exports = { toEntropyBuffer, fromSeed }
|
||||
|
|
@ -6,6 +6,7 @@ const configManager = require('./config-manager')
|
|||
const pify = require('pify')
|
||||
const fs = pify(require('fs'))
|
||||
|
||||
const mnemonicHelpers = require('./mnemonic-helpers')
|
||||
const options = require('./options')
|
||||
const ph = require('./plugin-helper')
|
||||
const layer2 = require('./layer2')
|
||||
|
|
@ -24,20 +25,20 @@ function httpError (msg, code) {
|
|||
}
|
||||
|
||||
function computeSeed (masterSeed) {
|
||||
return hkdf(masterSeed, 32, {salt: 'lamassu-server-salt', info: 'wallet-seed'}).toString('hex')
|
||||
return hkdf(masterSeed, 32, { salt: 'lamassu-server-salt', info: 'wallet-seed' }).toString('hex')
|
||||
}
|
||||
|
||||
function fetchWallet (settings, cryptoCode) {
|
||||
return fs.readFile(options.seedPath, 'utf8')
|
||||
.then(hex => {
|
||||
const masterSeed = Buffer.from(hex.trim(), 'hex')
|
||||
return fs.readFile(options.mnemonicPath, 'utf8')
|
||||
.then(mnemonic => {
|
||||
const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
|
||||
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
|
||||
const wallet = ph.load(ph.WALLET, plugin)
|
||||
const rawAccount = settings.accounts[plugin]
|
||||
const account = _.set('seed', computeSeed(masterSeed), rawAccount)
|
||||
if (_.isFunction(wallet.run)) wallet.run(account)
|
||||
|
||||
return {wallet, account}
|
||||
return { wallet, account }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ const lastBalance = {}
|
|||
function _balance (settings, cryptoCode) {
|
||||
return fetchWallet(settings, cryptoCode)
|
||||
.then(r => r.wallet.balance(r.account, cryptoCode))
|
||||
.then(balance => ({balance, timestamp: Date.now()}))
|
||||
.then(balance => ({ balance, timestamp: Date.now() }))
|
||||
.then(r => {
|
||||
lastBalance[cryptoCode] = r
|
||||
return r
|
||||
|
|
@ -103,7 +104,7 @@ function mergeStatus (a, b) {
|
|||
if (!a) return b
|
||||
if (!b) return a
|
||||
|
||||
return {status: mergeStatusMode(a.status, b.status)}
|
||||
return { status: mergeStatusMode(a.status, b.status) }
|
||||
}
|
||||
|
||||
function mergeStatusMode (a, b) {
|
||||
|
|
@ -169,7 +170,7 @@ function getStatus (settings, tx, machineId) {
|
|||
|
||||
const status = isAuthorized ? 'authorized' : unauthorizedStatus
|
||||
|
||||
return {status}
|
||||
return { status }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue