var SEA = require('./sea'); var Gun = SEA.Gun; const queryGunAliases = require('./query') const parseProps = require('./parse') // This is internal User authentication func. const authenticate = async (alias, pass, gunRoot) => { // load all public keys associated with the username alias we want to log in with. const aliases = (await queryGunAliases(alias, gunRoot)) .filter(({ pub, at: { put } = {} } = {}) => !!pub && !!put) // Got any? if (!aliases.length) { throw { err: 'Public key does not exist!' } } let err // then attempt to log into each one until we find ours! // (if two users have the same username AND the same password... that would be bad) const users = await Promise.all(aliases.map(async ({ at: at, pub: pub }, i) => { // attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.) const auth = parseProps(at.put.auth) // NOTE: aliasquery uses `gun.get` which internally SEA.read verifies the data for us, so we do not need to re-verify it here. // SEA.verify(at.put.auth, pub).then(function(auth){ try { const proof = await SEA.work(pass, auth.s) const props = { pub: pub, proof: proof, at: at } // the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force. /* MARK TO @mhelander : pub vs epub!??? */ const salt = auth.salt const sea = await SEA.decrypt(auth.ek, proof) if (!sea) { err = 'Failed to decrypt secret! ' + i +'/'+aliases.length; return } // now we have AES decrypted the private key, from when we encrypted it with the proof at registration. // if we were successful, then that meanswe're logged in! const priv = sea.priv const epriv = sea.epriv const epub = at.put.epub // TODO: 'salt' needed? err = null if(typeof window !== 'undefined'){ var tmp = window.sessionStorage; if(tmp && gunRoot._.opt.remember){ window.sessionStorage.alias = alias; window.sessionStorage.tmp = pass; } } return Object.assign(props, { priv: priv, salt: salt, epub: epub, epriv: epriv }) } catch (e) { err = 'Failed to decrypt secret!' throw { err } } })) var user = Gun.list.map(users, function(acc){ if(acc){ return acc } }) if (!user) { throw { err: err || 'Public key does not exist!' } } return user } module.exports = authenticate;