|
|
|
@ -5,6 +5,7 @@ var Crypto = require("../../www/bower_components/chainpad-crypto"); |
|
|
|
var Mailbox = Crypto.Mailbox; |
|
|
|
var Nacl = require("tweetnacl"); |
|
|
|
var nThen = require("nthen"); |
|
|
|
var Pinpad = require("../../www/common/pinpad"); |
|
|
|
var Rpc = require("../../www/common/rpc"); |
|
|
|
var Hash = require("../../www/common/common-hash"); |
|
|
|
var CpNetflux = require("../../www/bower_components/chainpad-netflux"); |
|
|
|
@ -32,15 +33,6 @@ var createMailbox = function (config, cb) { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
var createRoster = function (config, cb) { |
|
|
|
Roster.create({ |
|
|
|
network: config.network, |
|
|
|
channel: config.channel, |
|
|
|
owners: config.owners, |
|
|
|
crypto: config.crypto, |
|
|
|
}, cb); |
|
|
|
}; |
|
|
|
|
|
|
|
process.on('unhandledRejection', function (err) { |
|
|
|
console.error(err); |
|
|
|
}); |
|
|
|
@ -61,10 +53,6 @@ var makeEdKeys = function () { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
var makeRosterHash = function () { |
|
|
|
return Hash.createRandomHash('pad', '');//.replace(/\/pad\//, '/roster/');
|
|
|
|
}; |
|
|
|
|
|
|
|
var EMPTY_ARRAY_HASH = 'slspTLTetp6gCkw88xE5BIAbYBXllWvQGahXCx/h1gQOlE7zze4W0KRlA8puZZol8hz5zt3BPzUqPJgTjBXWrw=='; |
|
|
|
|
|
|
|
var createUser = function (config, cb) { |
|
|
|
@ -91,26 +79,6 @@ var createUser = function (config, cb) { |
|
|
|
user.mailbox = Mailbox.createEncryptor(user.curveKeys); |
|
|
|
user.mailboxChannel = Hash.createChannelId(); |
|
|
|
|
|
|
|
//console.log(config.rosterHash);
|
|
|
|
//console.log(Hash.parseTypeHash('pad', config.rosterHash));
|
|
|
|
|
|
|
|
user.roster = Hash.getSecrets('pad', config.rosterHash, ''); |
|
|
|
console.log(user.roster); |
|
|
|
var crypto = Crypto.createEncryptor(user.roster.keys); |
|
|
|
|
|
|
|
console.log(crypto); |
|
|
|
|
|
|
|
createRoster({ |
|
|
|
network: network, |
|
|
|
channel: user.roster.channel, |
|
|
|
owners: [ user.edKeys.edPublic ], |
|
|
|
crypto: crypto, |
|
|
|
validateKey: user.roster.validateKey, |
|
|
|
}, w(function (err, roster) { |
|
|
|
if (err) { return void console.error(err); } |
|
|
|
user.roster = roster; |
|
|
|
})); |
|
|
|
|
|
|
|
// create an anon rpc for alice
|
|
|
|
Rpc.createAnonymous(network, w(function (err, rpc) { |
|
|
|
if (err) { |
|
|
|
@ -121,7 +89,7 @@ var createUser = function (config, cb) { |
|
|
|
user.anonRpc = rpc; |
|
|
|
})); |
|
|
|
|
|
|
|
Rpc.create(network, user.edKeys.edPrivate, user.edKeys.edPublic, w(function (err, rpc) { |
|
|
|
Pinpad.create(network, user.edKeys, w(function (err, rpc) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
user.shutdown(); |
|
|
|
@ -131,7 +99,7 @@ var createUser = function (config, cb) { |
|
|
|
user.rpc = rpc; |
|
|
|
})); |
|
|
|
|
|
|
|
Rpc.create(network, config.teamEdKeys.edPrivate, config.teamEdKeys.edPublic, w(function (err, rpc) { |
|
|
|
Pinpad.create(network, config.teamEdKeys, w(function (err, rpc) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
user.shutdown(); |
|
|
|
@ -139,15 +107,25 @@ var createUser = function (config, cb) { |
|
|
|
} |
|
|
|
user.team_rpc = rpc; |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
user.rpc.reset([], w(function (err, hash) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
user.shutdown(); |
|
|
|
return console.log("RESET_ERR"); |
|
|
|
} |
|
|
|
if (!hash || hash !== EMPTY_ARRAY_HASH) { |
|
|
|
throw new Error("EXPECTED EMPTY ARRAY HASH"); |
|
|
|
} |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
// some basic sanity checks...
|
|
|
|
user.rpc.send('GET_HASH', user.edKeys.edPublic, w(function (err, hash) { |
|
|
|
user.rpc.getServerHash(w(function (err, hash) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err); |
|
|
|
} |
|
|
|
|
|
|
|
if (!hash || hash[0] !== EMPTY_ARRAY_HASH) { |
|
|
|
if (hash !== EMPTY_ARRAY_HASH) { |
|
|
|
console.error("EXPECTED EMPTY ARRAY HASH"); |
|
|
|
process.exit(1); |
|
|
|
} |
|
|
|
@ -185,58 +163,56 @@ var createUser = function (config, cb) { |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
// pin your mailbox
|
|
|
|
user.rpc.send('PIN', [user.mailboxChannel], w(function (err, data) { |
|
|
|
user.rpc.pin([user.mailboxChannel], w(function (err, hash) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err); |
|
|
|
} |
|
|
|
try { |
|
|
|
if (data[0] === EMPTY_ARRAY_HASH) { throw new Error("PIN_DIDNT_WORK"); } |
|
|
|
user.latestPinHash = data[0]; |
|
|
|
} catch (err2) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err2); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('PIN_RESPONSE', hash); |
|
|
|
|
|
|
|
if (hash[0] === EMPTY_ARRAY_HASH) { throw new Error("PIN_DIDNT_WORK"); } |
|
|
|
user.latestPinHash = hash; |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
user.team_rpc.send('GET_HASH', config.teamEdKeys.edPublic, w(function (err, hash) { |
|
|
|
}).nThen(function () { |
|
|
|
/* |
|
|
|
// XXX race condition because both users try to pin things...
|
|
|
|
user.team_rpc.getServerHash(w(function (err, hash) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
if (!hash || hash[0] !== EMPTY_ARRAY_HASH) { |
|
|
|
console.error("EXPECTED EMPTY ARRAY HASH"); |
|
|
|
process.exit(1); |
|
|
|
} |
|
|
|
})); |
|
|
|
*/ |
|
|
|
}).nThen(function () { |
|
|
|
// TODO check your quota usage
|
|
|
|
|
|
|
|
}).nThen(function (w) { |
|
|
|
user.rpc.send('UNPIN', [user.mailboxChannel], w(function (err, data) { |
|
|
|
user.rpc.unpin([user.mailboxChannel], w(function (err, hash) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err); |
|
|
|
} |
|
|
|
try { |
|
|
|
if (data[0] !== EMPTY_ARRAY_HASH) { throw new Error("UNPIN_DIDNT_WORK"); } |
|
|
|
user.latestPinHash = data[0]; |
|
|
|
} catch (err2) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err2); |
|
|
|
|
|
|
|
if (hash[0] !== EMPTY_ARRAY_HASH) { |
|
|
|
console.log('UNPIN_RESPONSE', hash); |
|
|
|
throw new Error("UNPIN_DIDNT_WORK"); |
|
|
|
} |
|
|
|
user.latestPinHash = hash[0]; |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
// clean up the pin list to avoid lots of accounts on the server
|
|
|
|
user.rpc.send("REMOVE_PINS", undefined, w(function (err, data) { |
|
|
|
user.rpc.removePins(w(function (err) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void cb(err); |
|
|
|
} |
|
|
|
if (!data || data[0] !== 'OK') { |
|
|
|
w.abort(); |
|
|
|
return void cb("REMOVE_PINS_DIDNT_WORK"); |
|
|
|
} |
|
|
|
})); |
|
|
|
}).nThen(function () { |
|
|
|
user.cleanup = function (cb) { |
|
|
|
@ -252,20 +228,102 @@ var createUser = function (config, cb) { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
var alice, bob; |
|
|
|
var alice, bob, oscar; |
|
|
|
|
|
|
|
var sharedConfig = { |
|
|
|
teamEdKeys: makeEdKeys(), |
|
|
|
teamCurveKeys: makeCurveKeys(), |
|
|
|
rosterChannel: Hash.createChannelId(), |
|
|
|
//rosterHash: makeRosterHash(),
|
|
|
|
}; |
|
|
|
|
|
|
|
nThen(function (w) { |
|
|
|
// oscar will be the owner of the team
|
|
|
|
createUser(sharedConfig, w(function (err, _oscar) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void console.log(err); |
|
|
|
} |
|
|
|
oscar = _oscar; |
|
|
|
oscar.name = 'oscar'; |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
// TODO oscar creates the team roster
|
|
|
|
//Roster = Roster;
|
|
|
|
|
|
|
|
// user edPublic (for ownership)
|
|
|
|
// user curve keys (for encryption and authentication)
|
|
|
|
|
|
|
|
// roster curve keys (for encryption and decryption)
|
|
|
|
// roster signing/validate keys (ed)
|
|
|
|
|
|
|
|
nThen(function (w) { |
|
|
|
var sharedConfig = { |
|
|
|
teamEdKeys: makeEdKeys(), |
|
|
|
rosterHash: makeRosterHash(), |
|
|
|
// channel
|
|
|
|
// network
|
|
|
|
// owners:
|
|
|
|
|
|
|
|
var team = { |
|
|
|
curve: sharedConfig.teamCurveKeys, |
|
|
|
ed: sharedConfig.teamEdKeys, |
|
|
|
}; |
|
|
|
|
|
|
|
Roster.create({ |
|
|
|
network: oscar.network, |
|
|
|
channel: sharedConfig.rosterChannel, |
|
|
|
owners: [ |
|
|
|
oscar.edKeys.edPublic |
|
|
|
], |
|
|
|
keys: { |
|
|
|
myCurvePublic: oscar.curveKeys.curvePublic, |
|
|
|
myCurvePrivate: oscar.curveKeys.curvePrivate, |
|
|
|
|
|
|
|
teamCurvePublic: team.curve.curvePublic, |
|
|
|
teamCurvePrivate: team.curve.curvePrivate, |
|
|
|
|
|
|
|
teamEdPrivate: team.ed.edPrivate, |
|
|
|
teamEdPublic: team.ed.edPublic, |
|
|
|
}, |
|
|
|
anon_rpc: oscar.anonRpc, |
|
|
|
lastKnownHash: void 0, |
|
|
|
}, w(function (err, roster) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void console.trace(err); |
|
|
|
} |
|
|
|
oscar.roster = roster; |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
var roster = oscar.roster; |
|
|
|
|
|
|
|
roster.on('change', function () { |
|
|
|
setTimeout(function () { |
|
|
|
|
|
|
|
console.log("\nCHANGE"); |
|
|
|
console.log("roster.getState()", roster.getState()); |
|
|
|
console.log(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
var state = roster.getState(); |
|
|
|
console.log("CURRENT ROSTER STATE:", state); |
|
|
|
|
|
|
|
roster.init({ |
|
|
|
name: oscar.name, |
|
|
|
//profile: '',
|
|
|
|
// mailbox: '',
|
|
|
|
//title: '',
|
|
|
|
}, w(function (err) { |
|
|
|
if (err) { return void console.error(err); } |
|
|
|
})); |
|
|
|
}).nThen(function (w) { |
|
|
|
console.log("ALICE && BOB"); |
|
|
|
createUser(sharedConfig, w(function (err, _alice) { |
|
|
|
if (err) { |
|
|
|
w.abort(); |
|
|
|
return void console.log(err); |
|
|
|
} |
|
|
|
alice = _alice; |
|
|
|
alice.name = 'alice'; |
|
|
|
console.log("Initialized Alice"); |
|
|
|
})); |
|
|
|
createUser(sharedConfig, w(function (err, _bob) { |
|
|
|
if (err) { |
|
|
|
@ -273,7 +331,39 @@ nThen(function (w) { |
|
|
|
return void console.log(err); |
|
|
|
} |
|
|
|
bob = _bob; |
|
|
|
bob.name = 'bob'; |
|
|
|
console.log("Initialized Bob"); |
|
|
|
})); |
|
|
|
}).nThen(function () { |
|
|
|
// TODO oscar adds alice and bob to the team as members
|
|
|
|
var roster = oscar.roster; |
|
|
|
|
|
|
|
var data = {}; |
|
|
|
data[alice.curveKeys.curvePublic] = { |
|
|
|
name: alice.name, |
|
|
|
role: 'MEMBER', |
|
|
|
}; |
|
|
|
data[bob.curveKeys.curvePublic] = { |
|
|
|
name: bob.name, |
|
|
|
role: 'MEMBER', |
|
|
|
}; |
|
|
|
|
|
|
|
roster.add(data, function (err) { |
|
|
|
if (err) { |
|
|
|
return void console.error(err); |
|
|
|
} |
|
|
|
console.log("SENT ADD COMMAND"); |
|
|
|
}); |
|
|
|
}).nThen(function () { |
|
|
|
// TODO alice and bob describe themselves...
|
|
|
|
|
|
|
|
}).nThen(function () { |
|
|
|
// TODO Oscar promotes Alice to 'ADMIN'
|
|
|
|
|
|
|
|
}).nThen(function () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}).nThen(function (w) { |
|
|
|
var message = alice.mailbox.encrypt(JSON.stringify({ |
|
|
|
type: "CHEESE", |
|
|
|
|