peer checking againt by key ring
This commit is contained in:
parent
da59c3666b
commit
e88dc7afb3
9 changed files with 199 additions and 138 deletions
|
|
@ -19,27 +19,42 @@ var Key = bitcore.Key;
|
|||
|
||||
function Network(opts) {
|
||||
var self = this;
|
||||
opts = opts || {};
|
||||
this.peerId = opts.peerId;
|
||||
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
||||
this.debug = opts.debug || 3;
|
||||
this.maxPeers = opts.maxPeers || 10;
|
||||
this.opts = {
|
||||
key: opts.key
|
||||
};
|
||||
this.connections = {};
|
||||
this.copayerForPeer = {};
|
||||
opts = opts || {};
|
||||
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
||||
this.debug = opts.debug || 3;
|
||||
this.maxPeers = opts.maxPeers || 10;
|
||||
this.opts = { key: opts.key };
|
||||
|
||||
// For using your own peerJs server
|
||||
['port', 'host', 'path', 'debug'].forEach(function(k) {
|
||||
if (opts[k]) self.opts[k] = opts[k];
|
||||
});
|
||||
this.connectedPeers = [];
|
||||
this.started = false;
|
||||
this.cleanUp();
|
||||
}
|
||||
|
||||
Network.parent = EventEmitter;
|
||||
|
||||
Network.prototype.cleanUp = function() {
|
||||
this.started = false;
|
||||
this.connectedPeers = [];
|
||||
this.peerId = null;
|
||||
this.copayerId = null;
|
||||
this.signingKey = null;
|
||||
this.allowedCopayerIds=null;
|
||||
this.authenticatedPeers=[];
|
||||
this.copayerForPeer={};
|
||||
this.connections={};
|
||||
if (this.peer) {
|
||||
console.log('## DESTROYING PEER INSTANCE'); //TODO
|
||||
this.peer.disconnect();
|
||||
this.peer.destroy();
|
||||
this.peer = null;
|
||||
}
|
||||
this.closing = 0;
|
||||
};
|
||||
|
||||
Network.parent=EventEmitter;
|
||||
|
||||
// Array helpers
|
||||
Network._arrayDiff = function(a, b) {
|
||||
var seen = [];
|
||||
|
|
@ -83,9 +98,16 @@ Network.prototype.connectedCopayers = function() {
|
|||
return ret;
|
||||
};
|
||||
|
||||
Network.prototype._onClose = function(peerId) {
|
||||
Network.prototype._deletePeer = function(peerId) {
|
||||
if (this.connections[peerId]) {
|
||||
this.connections[peerId].close();
|
||||
}
|
||||
delete this.connections[peerId];
|
||||
this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers);
|
||||
};
|
||||
|
||||
Network.prototype._onClose = function(peerId) {
|
||||
this._deletePeer(peerId);
|
||||
this._notifyNetworkChange();
|
||||
};
|
||||
|
||||
|
|
@ -99,7 +121,7 @@ Network.prototype._connectToCopayers = function(copayerIds) {
|
|||
};
|
||||
|
||||
Network.prototype._sendHello = function(copayerId) {
|
||||
console.log('#### SENDING HELLO TO ', copayerId);
|
||||
console.log('### SENDING HELLO TO ', copayerId);
|
||||
this.send(copayerId, {
|
||||
type: 'hello',
|
||||
copayerId: this.copayerId,
|
||||
|
|
@ -107,7 +129,7 @@ Network.prototype._sendHello = function(copayerId) {
|
|||
};
|
||||
|
||||
Network.prototype._sendCopayers = function(copayerIds) {
|
||||
console.log('#### SENDING PEER LIST: ', this.connectedPeers,this.connectedCopayers(), ' TO ', copayerIds?copayerIds: 'ALL');
|
||||
console.log('### SENDING PEER LIST: ', this.connectedPeers,this.connectedCopayers(), ' TO ', copayerIds?copayerIds: 'ALL');
|
||||
this.send(copayerIds, {
|
||||
type: 'copayers',
|
||||
copayers: this.connectedCopayers(),
|
||||
|
|
@ -128,6 +150,8 @@ Network.prototype._addCopayer = function(copayerId, isInbound) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Network.prototype._onData = function(data, isInbound, peerId) {
|
||||
var sig, payload;
|
||||
try {
|
||||
|
|
@ -136,45 +160,53 @@ Network.prototype._onData = function(data, isInbound, peerId) {
|
|||
payload= dataObj.payload;
|
||||
|
||||
} catch (e) {
|
||||
console.log('### ERROR ON DATA: "%s" ', data, isInbound, e);
|
||||
console.log('### ERROR IN DATA: "%s" ', data, isInbound, e);
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
};
|
||||
|
||||
console.log('### RECEIVED INBOUND?:%s TYPE: %s FROM %s: sig:%s',
|
||||
isInbound, payload.type, peerId, sig, payload);
|
||||
var self=this;
|
||||
console.log('### RECEIVED INBOUND?:%s TYPE: %s FROM %s',
|
||||
isInbound, payload.type, peerId, payload);
|
||||
|
||||
// TODO _func
|
||||
if(payload.type === 'hello') {
|
||||
var thisSig = this._sign(payload, this.copayerId);
|
||||
var thisSig = this._signHMAC(payload, this.copayerId);
|
||||
if (thisSig !== sig) {
|
||||
console.log('#### Peer sent WRONG hello. Closing connection.');
|
||||
console.log('#### Peer sent WRONG hello signature. Closing connection.');
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
}
|
||||
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
|
||||
console.log('#### Peer is not on the allowedCopayerIds. Closing connection',
|
||||
this.allowedCopayerIds, payload.copayerId);
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('#### Peer sent signed hello. Setting it up.'); //TODO
|
||||
this._addCopayer(payload.copayerId, isInbound);
|
||||
this._setPeerAuthenticated(peerId);
|
||||
this._notifyNetworkChange( isInbound ? payload.copayerId : null);
|
||||
this.emit('open');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.copayerForPeer[peerId]) {
|
||||
console.log('### Discarting message from unknow peer: ', peerId); //TODO
|
||||
//copayerForPeer is populated also in 'copayers' message, so we need authenticatedPeer
|
||||
if (isInbound && (!this.copayerForPeer[peerId] || !this.authenticatedPeers[peerId])) {
|
||||
console.log('### Closing connection from unknown/unauthenticated peer: ', peerId);
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// check sig
|
||||
if (this.copayerForPeer[peerId]) {
|
||||
var copayerIdBuf = new Buffer(this.copayerForPeer[peerId],'hex');
|
||||
if (!bitcore.Message.verifyWithPubKey( copayerIdBuf, JSON.stringify(payload),
|
||||
new Buffer(sig,'hex'))) {
|
||||
|
||||
console.log('[WebRTC.js.152] SIGNATURE VERIFICATION FAILED!!'); //TODO
|
||||
// TODO close connection
|
||||
return;
|
||||
}
|
||||
var copayerIdBuf = new Buffer(this.copayerForPeer[peerId],'hex');
|
||||
if (!bitcore.Message.verifyWithPubKey( copayerIdBuf, JSON.stringify(payload),
|
||||
new Buffer(sig,'hex'))) {
|
||||
console.log('[WebRTC.js.152] SIGNATURE VERIFICATION FAILED!!'); //TODO
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
}
|
||||
|
||||
var self=this;
|
||||
switch(payload.type) {
|
||||
case 'copayers':
|
||||
this._addCopayer(this.copayerForPeer[peerId], false);
|
||||
|
|
@ -192,24 +224,27 @@ Network.prototype._onData = function(data, isInbound, peerId) {
|
|||
Network.prototype._checkAnyPeer = function() {
|
||||
if (!this.connectedPeers.length) {
|
||||
console.log('EMIT openError: no more peers, not even you!');
|
||||
this._cleanUp();
|
||||
this.cleanUp();
|
||||
this.emit('openError');
|
||||
}
|
||||
}
|
||||
if (this.connectedPeers.length === 1) {
|
||||
this.emit('onlyYou');
|
||||
}
|
||||
};
|
||||
|
||||
Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
|
||||
var self = this;
|
||||
|
||||
dataConn.on('open', function() {
|
||||
if (!Network._inArray(dataConn.peer, self.connectedPeers)
|
||||
&& ! self.connections[dataConn.peer]) {
|
||||
&& !self.connections[dataConn.peer]) {
|
||||
|
||||
self.connections[dataConn.peer] = dataConn;
|
||||
|
||||
console.log('### DATA CONNECTION READY: %s (inbound: %s) AUTHENTICATING...',
|
||||
dataConn.peer, isInbound);
|
||||
|
||||
// The connection peer send hello (with signature)
|
||||
// The connecting peer send hello (with signature)
|
||||
if(!isInbound)
|
||||
self._sendHello(self.copayerForPeer[dataConn.peer]);
|
||||
}
|
||||
|
|
@ -236,7 +271,6 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
|
|||
};
|
||||
|
||||
Network.prototype._notifyNetworkChange = function(newCopayerId) {
|
||||
console.log('[WebRTC.js.164:_notifyNetworkChange:]', newCopayerId); //TODO
|
||||
this.emit('networkChange', newCopayerId);
|
||||
};
|
||||
|
||||
|
|
@ -276,11 +310,21 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
|
|||
|
||||
Network.prototype._addCopayerMap = function(peerId, copayerId) {
|
||||
if (!this.copayerForPeer[peerId]) {
|
||||
console.log('ADDING COPAYER MAPPING: %s => %s', peerId, copayerId); //TODO
|
||||
this.copayerForPeer[peerId]=copayerId;
|
||||
if(Object.keys(this.copayerForPeer).length < this.maxPeers) {
|
||||
console.log('Adding peer/copayer', peerId, copayerId); //TODO
|
||||
this.copayerForPeer[peerId]=copayerId;
|
||||
}
|
||||
else {
|
||||
console.log('### maxPeerLimit of %d reached. Refusing to add more copayers.', this.maxPeers); //TODO
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Network.prototype._setPeerAuthenticated = function(peerId) {
|
||||
this.authenticatedPeers[peerId] = 1;
|
||||
};
|
||||
|
||||
Network.prototype.setCopayerId = function(copayerId) {
|
||||
if (this.started) {
|
||||
throw new Error('network already started: can not change peerId')
|
||||
|
|
@ -303,14 +347,16 @@ Network.prototype.setSigningKey = function(keyHex) {
|
|||
};
|
||||
|
||||
Network.prototype.peerFromCopayer = function(hex) {
|
||||
return util.sha256(new Buffer(hex,'hex')).toString('hex');
|
||||
var SIN = bitcore.SIN;
|
||||
return new SIN(new Buffer(hex,'hex')).toString();
|
||||
};
|
||||
|
||||
Network.prototype.start = function(opts, openCallback) {
|
||||
opts = opts || {};
|
||||
var self = this;
|
||||
if (this.started) return openCallback();
|
||||
opts.connectedPeers = opts.connectedPeers || [];
|
||||
|
||||
if (this.started) return openCallback();
|
||||
|
||||
this.maxPeers = opts.maxPeers || this.maxPeers;
|
||||
|
||||
if (!this.copayerId)
|
||||
this.setCopayerId(opts.copayerId);
|
||||
|
|
@ -320,7 +366,8 @@ Network.prototype.start = function(opts, openCallback) {
|
|||
console.log('CREATING PEER INSTANCE:', this.peerId); //TODO
|
||||
this.peer = new Peer(this.peerId, this.opts);
|
||||
this._setupPeerHandlers(openCallback);
|
||||
for (var i = 0; i < opts.connectedPeers.length; i++) {
|
||||
opts.connectedPeers = opts.connectedPeers || [];
|
||||
for (var i = 0; i<opts.connectedPeers.length; i++) {
|
||||
var otherPeerId = opts.connectedPeers[i];
|
||||
this.connectTo(otherPeerId);
|
||||
}
|
||||
|
|
@ -328,26 +375,28 @@ Network.prototype.start = function(opts, openCallback) {
|
|||
};
|
||||
|
||||
|
||||
Network.prototype._sign = function(payload, copayerId) {
|
||||
Network.prototype._signHMAC = function(payload, copayerId) {
|
||||
var str = JSON.stringify(payload);
|
||||
if (payload.type !=='hello')
|
||||
throw new Error ('HMAC only for hello messages')
|
||||
return util.sha512hmac(
|
||||
new Buffer(str),
|
||||
new Buffer(copayerId,'hex')
|
||||
).toString('hex');
|
||||
};
|
||||
|
||||
Network.prototype._signECDSA = function(payload) {
|
||||
var ret='';
|
||||
var str = JSON.stringify(payload);
|
||||
if (payload.type ==='hello') {
|
||||
ret = (
|
||||
util.sha512hmac(
|
||||
new Buffer(str),
|
||||
new Buffer(copayerId,'hex')
|
||||
)).toString('hex');
|
||||
}
|
||||
else {
|
||||
if (!this.signingKey)
|
||||
throw new Error ('no key to sign messages :(');
|
||||
ret = bitcore.Message.sign(
|
||||
str,
|
||||
this.signingKey
|
||||
).toString('hex');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (!this.signingKey)
|
||||
throw new Error ('no key to sign messages :(');
|
||||
|
||||
return bitcore.Message.sign(
|
||||
str,
|
||||
this.signingKey
|
||||
).toString('hex');
|
||||
};
|
||||
|
||||
Network.prototype.getOnlinePeerIDs = function() {
|
||||
return this.connectedPeers;
|
||||
};
|
||||
|
|
@ -356,13 +405,13 @@ Network.prototype.getPeer = function() {
|
|||
return this.peer;
|
||||
};
|
||||
|
||||
Network.prototype._sendToOne = function(copayerId, payload, cb) {
|
||||
Network.prototype._sendToOne = function(copayerId, payload, sig, cb) {
|
||||
var peerId = this.peerFromCopayer(copayerId);
|
||||
if (peerId !== this.peerId) {
|
||||
var dataConn = this.connections[peerId];
|
||||
if (dataConn) {
|
||||
var str = JSON.stringify({
|
||||
sig: this._sign(payload, copayerId),
|
||||
sig: sig,
|
||||
payload: payload
|
||||
});
|
||||
dataConn.send(str);
|
||||
|
|
@ -381,17 +430,26 @@ Network.prototype.send = function(copayerIds, payload, cb) {
|
|||
payload.isBroadcast = 1;
|
||||
}
|
||||
|
||||
var sig;
|
||||
if (payload.type === 'hello') {
|
||||
var hisId = copayerIds;
|
||||
sig=this._signHMAC(payload,hisId);
|
||||
}
|
||||
else {
|
||||
sig=this._signECDSA(payload);
|
||||
}
|
||||
|
||||
if (Array.isArray(copayerIds)) {
|
||||
var l = copayerIds.length;
|
||||
var i = 0;
|
||||
copayerIds.forEach(function(copayerId) {
|
||||
self._sendToOne(copayerId, payload, function () {
|
||||
self._sendToOne(copayerId, payload, sig, function () {
|
||||
if (++i === l && typeof cb === 'function') cb();
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (typeof copayerIds === 'string')
|
||||
self._sendToOne(copayerIds, payload, cb);
|
||||
self._sendToOne(copayerIds, payload, sig, cb);
|
||||
};
|
||||
|
||||
Network.prototype.connectTo = function(copayerId) {
|
||||
|
|
@ -399,7 +457,7 @@ Network.prototype.connectTo = function(copayerId) {
|
|||
var peerId = this.peerFromCopayer(copayerId);
|
||||
this._addCopayerMap(peerId,copayerId);
|
||||
|
||||
console.log('### STARTING CONNECTION TO:', peerId, copayerId);
|
||||
console.log('### STARTING CONNECTION TO:\n\t'+ peerId+"\n\t"+ copayerId);
|
||||
var dataConn = this.peer.connect(peerId, {
|
||||
serialization: 'none',
|
||||
reliable: true,
|
||||
|
|
@ -408,28 +466,21 @@ Network.prototype.connectTo = function(copayerId) {
|
|||
self._setupConnectionHandlers(dataConn, false);
|
||||
};
|
||||
|
||||
Network.prototype._cleanUp = function() {
|
||||
var self = this;
|
||||
self.connectedPeers = [];
|
||||
self.started = false;
|
||||
self.peerId = null;
|
||||
self.copayerId = null;
|
||||
self.signingKey = null;
|
||||
if (self.peer) {
|
||||
console.log('## DESTROYING PEER INSTANCE'); //TODO
|
||||
self.peer.disconnect();
|
||||
self.peer.destroy();
|
||||
self.peer = null;
|
||||
Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) {
|
||||
if (!this.allowedCopayerIds)
|
||||
console.log('[webrtc] #### LOCKING INCOMMING CONNECTIONS');
|
||||
|
||||
this.allowedCopayerIds={};
|
||||
for(var i in allowedCopayerIdsArray) {
|
||||
this.allowedCopayerIds[ allowedCopayerIdsArray[i] ] = 1;
|
||||
}
|
||||
self.closing = 0;
|
||||
};
|
||||
|
||||
|
||||
Network.prototype.disconnect = function(cb, forced) {
|
||||
var self = this;
|
||||
self.closing = 1;
|
||||
self.send(null, { type: 'disconnect' }, function(){
|
||||
self._cleanUp();
|
||||
self.cleanUp();
|
||||
if (typeof cb === 'function') cb();
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue