Skip to content

Commit

Permalink
Implement saving/loading MasterPass in Keychain, fix #50
Browse files Browse the repository at this point in the history
  • Loading branch information
HR committed Aug 3, 2020
1 parent 796fb15 commit 921d6bb
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 22 deletions.
41 changes: 27 additions & 14 deletions app/core/MasterPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,67 @@
* MasterPass functionality
******************************/

const crypto = require('./crypto')
const _ = require('lodash')
const crypto = require('./crypto'),
keytar = require('keytar'),
SERVICE = 'Crypter',
ACCOUNT = 'MasterPass'

// TODO: Make independent from global obj! use param instead

exports.init = async () => {
const MasterPass = await keytar.getPassword(SERVICE, ACCOUNT)
if (!MasterPass) return false
exports.set(MasterPass)
return true
}

exports.save = masterpass => keytar.setPassword(SERVICE, ACCOUNT, masterpass)

// Check MasterPass
exports.check = (masterpass) => {
exports.check = masterpass => {
return new Promise((resolve, reject) => {
// deriveKey using the salt originally used to generate the
// MasterPassKey
crypto.deriveKey(masterpass, global.creds.mpsalt)
.then((mpk) => {
crypto
.deriveKey(masterpass, global.creds.mpsalt)
.then(mpk => {
// generate the hash for the MasterPassKey
return crypto.genPassHash(mpk.key, global.creds.mpksalt)
})
.then((mpk) => {
.then(mpk => {
// check if MasterPassKey hash is equal to the MasterPassKey hash in mdb
// Use timingSafeEqual to protect against timing attacks
const match = crypto.timingSafeEqual(global.creds.mpkhash, mpk.hash)
// return the match and derived key
resolve({match, key: mpk.key})
resolve({ match, key: mpk.key })
})
.catch((err) => {
.catch(err => {
reject(err)
})
})

}

// Set MasterPass
exports.set = (masterpass) => {
exports.set = masterpass => {
return new Promise((resolve, reject) => {
// Derive the MasterPassKey from the supplied masterpass
crypto.deriveKey(masterpass, null)
.then((mp) => {
exports
.save(masterpass)
.then(() => crypto.deriveKey(masterpass, null))
.then(mp => {
// Save the salt used to generate the MasterPassKey
global.creds.mpsalt = mp.salt
// generate the hash for the MasterPassKey
return crypto.genPassHash(mp.key, null)
})
.then((mpk) => {
.then(mpk => {
// Save the salt used to generate the masterpass
global.creds.mpkhash = mpk.hash
global.creds.mpksalt = mpk.salt
// return the derived mpkey
resolve(mpk.key)
})
.catch((err) => {
.catch(err => {
// reject if error occurs
reject(err)
})
Expand Down
13 changes: 6 additions & 7 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const { existsSync } = require('fs-extra')
const { checkUpdate } = require('./utils/update')
// Core
const Db = require('./core/Db')
const MasterPass = require('./core/MasterPass')
// Windows
const crypter = require('./src/crypter')
const masterPassPrompt = require('./src/masterPassPrompt')
Expand Down Expand Up @@ -78,11 +79,8 @@ const init = function () {
}

const initMain = function () {
logger.verbose(`PROMISE: Main initialisation`)
return new Promise(function (resolve, reject) {
// restore the creds object globally
resolve(global.mdb.restoreGlobalObj('creds'))
})
logger.verbose(`initialising Main...`)
return global.mdb.restoreGlobalObj('creds').then(() => MasterPass.init())
}

/**
Expand All @@ -107,9 +105,10 @@ app.on('ready', function () {

// Initialise (open mdb and get creds)
initMain()
.then(() => {
.then(mpLoaded => {
logger.verbose('INIT: MasterPass', mpLoaded ? 'loaded' : 'not saved')
// Obtain MasterPass, derive MasterPassKey and set globally
return masterPassPromptWindow()
return mpLoaded || masterPassPromptWindow()
})
.then(() => {
// Create the Crypter window and open it
Expand Down
2 changes: 2 additions & 0 deletions app/src/masterPassPrompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ exports.window = function (global, callback) {
logger.info('IPCMAIN: PASSWORD MATCHES!')
// Save MasterPassKey (while program is running)
global.MasterPassKey = new MasterPassKey(res.key)
// Save for nexg time
MasterPass.save(masterpass)
// send result match result to masterpassprompt.html
webContents.send('checkMasterPassResult', {
err: null,
Expand Down
2 changes: 1 addition & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ gulp.task('run', electron)

gulp.task('watch', function (done) {
gulp.watch(LESS_FILES, gulp.series('less'))
gulp.watch(['./app/src/*.js', './app/core/*.js'], gulp.series('run'))
gulp.watch(['./app/*.js', './app/src/*.js', './app/core/*.js'], gulp.series('run'))
done()
})

Expand Down

0 comments on commit 921d6bb

Please sign in to comment.