Comparing version 0.0.2 to 0.0.3
@@ -1,1 +0,1 @@ | ||
module.exports = require('./lib/index.js'); | ||
module.exports = require('./lib/index.js') |
396
lib/ecies.js
@@ -1,40 +0,40 @@ | ||
var crypto = require('crypto'); | ||
var assert = require('assert'); | ||
var ecurve = require('ecurve'); | ||
var BigInt = require('bigi'); | ||
var ecdsa = require('secp256k1'); | ||
var ethUtil = require('ethereumjs-util'); | ||
var xor = require('bitwise-xor'); | ||
var rlp = require('rlp'); | ||
var Mac = require('./mac.js'); | ||
var crypto = require('crypto') | ||
var assert = require('assert') | ||
var ecurve = require('ecurve') | ||
var BigInt = require('bigi') | ||
var ecdsa = require('secp256k1') | ||
var ethUtil = require('ethereumjs-util') | ||
var xor = require('bitwise-xor') | ||
var rlp = require('rlp') | ||
var Mac = require('./mac.js') | ||
var ECIES = module.exports = function(secKey, pubKey, remotePubKey) { | ||
this.secKey = secKey; | ||
this.pubKey = pubKey; | ||
this.remotePubKey = remotePubKey; | ||
this.ephemeralSecKey = crypto.randomBytes(32); | ||
this.ephemeralPubKey = ecdsa.createPublicKey(this.ephemeralSecKey); | ||
this.nonce = crypto.randomBytes(32); | ||
this.ingressMac = new Mac(); | ||
this.egressMac = new Mac(); | ||
this.initiator = true; //did this peer start the connection | ||
this.token = ''; | ||
var ECIES = module.exports = function (secKey, pubKey, remotePubKey) { | ||
this.secKey = secKey | ||
this.pubKey = pubKey | ||
this.remotePubKey = remotePubKey | ||
this.ephemeralSecKey = crypto.randomBytes(32) | ||
this.ephemeralPubKey = ecdsa.createPublicKey(this.ephemeralSecKey) | ||
this.nonce = crypto.randomBytes(32) | ||
this.ingressMac = new Mac() | ||
this.egressMac = new Mac() | ||
this.initiator = true // did this peer start the connection | ||
this.token = '' | ||
Object.defineProperty(this, 'ephemeralSecret', { | ||
get: function() { | ||
get: function () { | ||
if (!this._ephShared) { | ||
this._ephShared = ECIES.ecdh(this.ephemeralSecKey, Buffer.concat([new Buffer([4]), this.remoteEphemeralPubKey])); | ||
this._ephShared = ECIES.ecdh(this.ephemeralSecKey, Buffer.concat([new Buffer([4]), this.remoteEphemeralPubKey])) | ||
} | ||
return this._ephShared; | ||
return this._ephShared | ||
} | ||
}); | ||
}; | ||
}) | ||
} | ||
ECIES.ecdh = function(secKey, pubKey) { | ||
var curve = ecurve.getCurveByName('secp256k1'); | ||
var d = BigInt.fromBuffer(secKey); | ||
var Q = ecurve.Point.decodeFrom(curve, pubKey); | ||
var r = Q.multiply(d).getEncoded(true); | ||
return r.slice(1); | ||
}; | ||
ECIES.ecdh = function (secKey, pubKey) { | ||
var curve = ecurve.getCurveByName('secp256k1') | ||
var d = BigInt.fromBuffer(secKey) | ||
var Q = ecurve.Point.decodeFrom(curve, pubKey) | ||
var r = Q.multiply(d).getEncoded(true) | ||
return r.slice(1) | ||
} | ||
@@ -51,191 +51,193 @@ /** | ||
ECIES.concatKDF = function(keyMaterial, keyLen) { | ||
var s1 = ''; | ||
var key = ''; | ||
var hashBlocksize = 64; | ||
var reps = ((keyLen + 7) * 8) / (hashBlocksize * 8); | ||
var counter = 0; | ||
ECIES.concatKDF = function (keyMaterial, keyLen) { | ||
var s1 = '' | ||
var key = '' | ||
var hashBlocksize = 64 | ||
var reps = ((keyLen + 7) * 8) / (hashBlocksize * 8) | ||
var counter = 0 | ||
while (counter <= reps) { | ||
counter += 1; | ||
var sha256 = crypto.createHash('sha256'); | ||
var cnt = new Buffer(4); | ||
cnt.fill(0); | ||
cnt.writeUInt32BE(counter); | ||
sha256.update(cnt); | ||
sha256.update(keyMaterial); | ||
sha256.update(s1); | ||
key += sha256.digest('hex'); | ||
counter += 1 | ||
var sha256 = crypto.createHash('sha256') | ||
var cnt = new Buffer(4) | ||
cnt.fill(0) | ||
cnt.writeUInt32BE(counter) | ||
sha256.update(cnt) | ||
sha256.update(keyMaterial) | ||
sha256.update(s1) | ||
key += sha256.digest('hex') | ||
} | ||
return new Buffer(key, 'hex'); | ||
}; | ||
return new Buffer(key, 'hex') | ||
} | ||
ECIES.prototype.encryptMessage = function(secKey, data) { | ||
var r = ECIES.ecdh(secKey, this.remotePubKey); | ||
var key = ECIES.concatKDF(r, 32); | ||
var ekey = key.slice(0, 16); //encryption key | ||
var mkeyMaterial = key.slice(16, 32); | ||
var ourPubKey = ecdsa.createPublicKey(secKey); | ||
var IV = new Buffer(16); | ||
IV.fill(0); | ||
ECIES.prototype.encryptMessage = function (secKey, data) { | ||
var r = ECIES.ecdh(secKey, this.remotePubKey) | ||
var key = ECIES.concatKDF(r, 32) | ||
var ekey = key.slice(0, 16) // encryption key | ||
var mkeyMaterial = key.slice(16, 32) | ||
var ourPubKey = ecdsa.createPublicKey(secKey) | ||
var IV = new Buffer(16) | ||
IV.fill(0) | ||
//encrypt | ||
var aes = crypto.createCipheriv('aes-128-ctr', ekey, IV); | ||
var encrypted = aes.update(data); | ||
encrypted = Buffer.concat([IV, encrypted]); | ||
// encrypt | ||
var aes = crypto.createCipheriv('aes-128-ctr', ekey, IV) | ||
var encrypted = aes.update(data) | ||
encrypted = Buffer.concat([IV, encrypted]) | ||
//create key tag | ||
var sha256 = crypto.createHash('sha256'); | ||
sha256.update(mkeyMaterial); | ||
var mkey = sha256.digest(); //MAC key | ||
// create key tag | ||
var sha256 = crypto.createHash('sha256') | ||
sha256.update(mkeyMaterial) | ||
var mkey = sha256.digest() // MAC key | ||
//create tag | ||
var hmac = crypto.createHmac('sha256', mkey); | ||
hmac.update(encrypted); | ||
var tag = hmac.digest(); | ||
// create tag | ||
var hmac = crypto.createHmac('sha256', mkey) | ||
hmac.update(encrypted) | ||
var tag = hmac.digest() | ||
return Buffer.concat([ourPubKey, encrypted, tag]); | ||
}; | ||
return Buffer.concat([ourPubKey, encrypted, tag]) | ||
} | ||
ECIES.prototype.decryptMessage = function(data) { | ||
var pubKey = data.slice(0, 65); | ||
var dataIV = data.slice(65, -32); | ||
var tag = data.slice(-32); | ||
ECIES.prototype.decryptMessage = function (data) { | ||
var pubKey = data.slice(0, 65) | ||
var dataIV = data.slice(65, -32) | ||
var tag = data.slice(-32) | ||
var r = ECIES.ecdh(this.secKey, pubKey); | ||
var key = ECIES.concatKDF(r, 32); | ||
var ekey = key.slice(0, 16); //encryption key | ||
var mkeyMaterial = key.slice(16, 32); | ||
var r = ECIES.ecdh(this.secKey, pubKey) | ||
var key = ECIES.concatKDF(r, 32) | ||
var ekey = key.slice(0, 16) // encryption key | ||
var mkeyMaterial = key.slice(16, 32) | ||
var sha256 = crypto.createHash('sha256'); | ||
sha256.update(mkeyMaterial); | ||
var mkey = sha256.digest(); //MAC key | ||
var sha256 = crypto.createHash('sha256') | ||
sha256.update(mkeyMaterial) | ||
var mkey = sha256.digest() // MAC key | ||
var hmac = crypto.createHmac('sha256', mkey); | ||
hmac.update(dataIV); | ||
//check the tag | ||
assert(hmac.digest('hex') === tag.toString('hex'), 'should have valid tag'); | ||
var hmac = crypto.createHmac('sha256', mkey) | ||
hmac.update(dataIV) | ||
// check the tag | ||
assert(hmac.digest('hex') === tag.toString('hex'), 'should have valid tag') | ||
//decrypt data | ||
var IV = dataIV.slice(0, 16); | ||
var encryptedData = dataIV.slice(16); | ||
var aes = crypto.createDecipheriv('aes-128-ctr', ekey, IV); | ||
return aes.update(encryptedData); | ||
}; | ||
// decrypt data | ||
var IV = dataIV.slice(0, 16) | ||
var encryptedData = dataIV.slice(16) | ||
var aes = crypto.createDecipheriv('aes-128-ctr', ekey, IV) | ||
return aes.update(encryptedData) | ||
} | ||
ECIES.prototype.parseAuth = function(data) { | ||
this.remoteInitMsg = data; | ||
var decypted = this.decryptMessage(data); | ||
assert(decypted.slice(-1)[0] === 0, 'invalid postfix'); | ||
//parse packet | ||
var signature = decypted.slice(0, 64); | ||
const recId = decypted.slice(64, 65); | ||
var hepubk = decypted.slice(65, 65 + 32); | ||
var pubKey = this.remotePubKey = decypted.slice(65 + 32, 65 + 32 + 64); | ||
this.remotePubKey = Buffer.concat([new Buffer([4]), pubKey]); | ||
var nonce = this.remoteNonce = decypted.slice(-33, -1); | ||
pubKey = Buffer.concat([new Buffer([4]), pubKey]); | ||
var r = ECIES.ecdh(this.secKey, pubKey); | ||
var ephemeral = this.remoteEphemeralPubKey = ecdsa.recoverCompact(xor(r, nonce), signature, recId[0]).slice(1); | ||
var he = ethUtil.sha3(ephemeral).toString('hex'); | ||
assert(he.toString('hex') === hepubk.toString('hex'), 'the hash of the ephemeral key should match'); | ||
}; | ||
ECIES.prototype.parseAuth = function (data) { | ||
this.remoteInitMsg = data | ||
var decypted = this.decryptMessage(data) | ||
assert(decypted.slice(-1)[0] === 0, 'invalid postfix') | ||
// parse packet | ||
var signature = decypted.slice(0, 64) | ||
const recId = decypted.slice(64, 65) | ||
var hepubk = decypted.slice(65, 65 + 32) | ||
var pubKey = this.remotePubKey = decypted.slice(65 + 32, 65 + 32 + 64) | ||
this.remotePubKey = Buffer.concat([new Buffer([4]), pubKey]) | ||
var nonce = this.remoteNonce = decypted.slice(-33, -1) | ||
pubKey = Buffer.concat([new Buffer([4]), pubKey]) | ||
var r = ECIES.ecdh(this.secKey, pubKey) | ||
var ephemeral = this.remoteEphemeralPubKey = ecdsa.recover(xor(r, nonce), { | ||
signature: signature, | ||
recovery: recId[0] | ||
}, false).slice(1) | ||
var he = ethUtil.sha3(ephemeral).toString('hex') | ||
assert(he.toString('hex') === hepubk.toString('hex'), 'the hash of the ephemeral key should match') | ||
} | ||
ECIES.prototype.createAuth = function() { | ||
var r = ECIES.ecdh(this.secKey, this.remotePubKey); | ||
var sigr = ecdsa.signCompact(this.ephemeralSecKey, xor(r, this.nonce)); | ||
var ephemeralPubKey = ecdsa.createPublicKey(this.ephemeralSecKey).slice(1); | ||
var he = ethUtil.sha3(ephemeralPubKey); | ||
var data = Buffer.concat([sigr.signature, new Buffer([sigr.recoveryId]), he, this.pubKey.slice(1), this.nonce, new Buffer([0])]); | ||
var encryptionKey = crypto.randomBytes(32); | ||
this.initMsg = this.encryptMessage(encryptionKey, data); | ||
return this.initMsg; | ||
}; | ||
ECIES.prototype.createAuth = function () { | ||
var r = ECIES.ecdh(this.secKey, this.remotePubKey) | ||
var sigr = ecdsa.sign(xor(r, this.nonce), this.ephemeralSecKey) | ||
var ephemeralPubKey = ecdsa.createPublicKey(this.ephemeralSecKey, false).slice(1) | ||
var he = ethUtil.sha3(ephemeralPubKey) | ||
var data = Buffer.concat([sigr.signature, new Buffer([sigr.recovery]), he, this.pubKey.slice(1), this.nonce, new Buffer([0])]) | ||
var encryptionKey = crypto.randomBytes(32) | ||
this.initMsg = this.encryptMessage(encryptionKey, data) | ||
return this.initMsg | ||
} | ||
ECIES.prototype.parseAck = function(data) { | ||
var decypted = this.decryptMessage(data); | ||
assert(decypted.slice(-1)[0] === 0, 'invalid postfix'); | ||
this.remoteEphemeralPubKey = decypted.slice(0, 64); | ||
this.remoteNonce = decypted.slice(64, 96); | ||
this.initiator = false; | ||
this.setupFrame(data); | ||
}; | ||
ECIES.prototype.parseAck = function (data) { | ||
var decypted = this.decryptMessage(data) | ||
assert(decypted.slice(-1)[0] === 0, 'invalid postfix') | ||
this.remoteEphemeralPubKey = decypted.slice(0, 64) | ||
this.remoteNonce = decypted.slice(64, 96) | ||
this.initiator = false | ||
this.setupFrame(data) | ||
} | ||
ECIES.prototype.createAck = function() { | ||
var data = Buffer.concat([this.ephemeralPubKey.slice(1), this.nonce, new Buffer([0])]); | ||
var encryptionKey = crypto.randomBytes(32); | ||
this.initMsg = this.encryptMessage(encryptionKey, data); | ||
this.setupFrame(this.remoteInitMsg); | ||
return this.initMsg; | ||
}; | ||
ECIES.prototype.createAck = function () { | ||
var data = Buffer.concat([this.ephemeralPubKey.slice(1), this.nonce, new Buffer([0])]) | ||
var encryptionKey = crypto.randomBytes(32) | ||
this.initMsg = this.encryptMessage(encryptionKey, data) | ||
this.setupFrame(this.remoteInitMsg) | ||
return this.initMsg | ||
} | ||
ECIES.prototype.parseHeader = function(data) { | ||
//parse header | ||
var header = data.slice(0, 16); | ||
var headerMac = data.slice(16, 32); | ||
this.ingressMac.updateHeader(header); | ||
//check the header's mac | ||
assert(headerMac.toString('hex') === this.ingressMac.digest().toString('hex')); | ||
header = this.ingressAes.update(header); | ||
var size = this._bodySize = ethUtil.bufferToInt(header.slice(0, 3)); | ||
//TODO: do something with the header | ||
header = rlp.decode(header.slice(3)); | ||
return size; | ||
}; | ||
ECIES.prototype.parseHeader = function (data) { | ||
// parse header | ||
var header = data.slice(0, 16) | ||
var headerMac = data.slice(16, 32) | ||
this.ingressMac.updateHeader(header) | ||
// check the header's mac | ||
assert(headerMac.toString('hex') === this.ingressMac.digest().toString('hex')) | ||
header = this.ingressAes.update(header) | ||
var size = this._bodySize = ethUtil.bufferToInt(header.slice(0, 3)) | ||
// TODO: do something with the header | ||
return size | ||
} | ||
ECIES.prototype.createHeader = function(size) { | ||
//parse header | ||
size = ethUtil.pad(ethUtil.intToBuffer(size), 3); | ||
//TODO: the rlp will contain something else someday | ||
var header = Buffer.concat([size, rlp.encode([0, 0])]); | ||
var padNum = 16 - header.length; | ||
var padding = new Buffer(padNum); | ||
padding.fill(0); | ||
header = Buffer.concat([header, padding]); | ||
header = this.egressAes.update(header); | ||
this.egressMac.updateHeader(header); | ||
var tag = this.egressMac.digest(); | ||
return Buffer.concat([header, tag]); | ||
}; | ||
ECIES.prototype.createHeader = function (size) { | ||
// parse header | ||
size = ethUtil.pad(ethUtil.intToBuffer(size), 3) | ||
// TODO: the rlp will contain something else someday | ||
var header = Buffer.concat([size, rlp.encode([0, 0])]) | ||
var padNum = 16 - header.length | ||
var padding = new Buffer(padNum) | ||
padding.fill(0) | ||
header = Buffer.concat([header, padding]) | ||
header = this.egressAes.update(header) | ||
this.egressMac.updateHeader(header) | ||
var tag = this.egressMac.digest() | ||
return Buffer.concat([header, tag]) | ||
} | ||
ECIES.prototype.parseBody = function(data) { | ||
ECIES.prototype.parseBody = function (data) { | ||
if (!this._bodySize) { | ||
throw ('need to parse header first') | ||
throw new Error('need to parse header first') | ||
} | ||
var body = data.slice(0, -16); | ||
var mac = data.slice(-16); | ||
this.ingressMac.updateBody(body); | ||
assert(this.ingressMac.digest().toString('hex') === mac.toString('hex')); | ||
var size = this._bodySize; | ||
this._bodySize = false; | ||
return this.ingressAes.update(body).slice(0, size); | ||
}; | ||
var body = data.slice(0, -16) | ||
var mac = data.slice(-16) | ||
this.ingressMac.updateBody(body) | ||
assert(this.ingressMac.digest().toString('hex') === mac.toString('hex')) | ||
var size = this._bodySize | ||
this._bodySize = false | ||
return this.ingressAes.update(body).slice(0, size) | ||
} | ||
ECIES.prototype.createBody = function(data) { | ||
var padNum = 16 - data.length % 16; | ||
var padding = new Buffer(padNum); | ||
padding.fill(0); | ||
data = Buffer.concat([data, padding]); | ||
var encrypted = this.egressAes.update(data); | ||
this.egressMac.updateBody(encrypted); | ||
var tag = this.egressMac.digest(); | ||
return Buffer.concat([encrypted, tag]); | ||
}; | ||
ECIES.prototype.createBody = function (data) { | ||
var padNum = (16 - data.length % 16) % 16 | ||
var padding = new Buffer(padNum) | ||
padding.fill(0) | ||
data = Buffer.concat([data, padding]) | ||
var encrypted = this.egressAes.update(data) | ||
this.egressMac.updateBody(encrypted) | ||
var tag = this.egressMac.digest() | ||
return Buffer.concat([encrypted, tag]) | ||
} | ||
ECIES.prototype.setupFrame = function(remoteData) { | ||
var nonceMaterial = this.initiator ? Buffer.concat([this.nonce, this.remoteNonce]) : Buffer.concat([this.remoteNonce, this.nonce]); | ||
var hNonce = ethUtil.sha3(nonceMaterial); | ||
var sharedSecret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, hNonce])); | ||
this.token = ethUtil.sha3(sharedSecret); | ||
this.aesSecret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, sharedSecret])); | ||
this.macSecret = this.egressMac.secret = this.ingressMac.secret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, this.aesSecret])); | ||
var IV = new Buffer(16); | ||
IV.fill(0); | ||
this.ingressAes = crypto.createDecipheriv('aes-256-ctr', this.aesSecret, IV); | ||
this.egressAes = crypto.createDecipheriv('aes-256-ctr', this.aesSecret, IV); | ||
var ingressData = Buffer.concat([xor(this.macSecret, this.nonce), remoteData]); | ||
var egressData = Buffer.concat([xor(this.macSecret, this.remoteNonce), this.initMsg]); | ||
this.ingressMac.rawUpdate(ingressData); | ||
this.egressMac.rawUpdate(egressData); | ||
}; | ||
ECIES.prototype.setupFrame = function (remoteData) { | ||
var nonceMaterial = this.initiator ? Buffer.concat([this.nonce, this.remoteNonce]) : Buffer.concat([this.remoteNonce, this.nonce]) | ||
var hNonce = ethUtil.sha3(nonceMaterial) | ||
var sharedSecret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, hNonce])) | ||
this.token = ethUtil.sha3(sharedSecret) | ||
this.aesSecret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, sharedSecret])) | ||
this.macSecret = this.egressMac.secret = this.ingressMac.secret = ethUtil.sha3(Buffer.concat([this.ephemeralSecret, this.aesSecret])) | ||
var IV = new Buffer(16) | ||
IV.fill(0) | ||
this.ingressAes = crypto.createDecipheriv('aes-256-ctr', this.aesSecret, IV) | ||
this.egressAes = crypto.createDecipheriv('aes-256-ctr', this.aesSecret, IV) | ||
var ingressData = Buffer.concat([xor(this.macSecret, this.nonce), remoteData]) | ||
var egressData = Buffer.concat([xor(this.macSecret, this.remoteNonce), this.initMsg]) | ||
this.ingressMac.rawUpdate(ingressData) | ||
this.egressMac.rawUpdate(egressData) | ||
} |
273
lib/index.js
@@ -1,11 +0,11 @@ | ||
const net = require('net'); | ||
const crypto = require('crypto'); | ||
const util = require('util'); | ||
const enableDestroy = require('server-destroy'); | ||
const EventEmitter = require('events').EventEmitter; | ||
const _ = require('underscore'); | ||
const async = require('async'); | ||
const Peer = require('./peer'); | ||
const pjson = require('../package.json'); | ||
const DPT = require('devp2p-dpt'); | ||
const net = require('net') | ||
const crypto = require('crypto') | ||
const util = require('util') | ||
const enableDestroy = require('server-destroy') | ||
const EventEmitter = require('events').EventEmitter | ||
const _ = require('underscore') | ||
const async = require('async') | ||
const Peer = require('./peer') | ||
const pjson = require('../package.json') | ||
const DPT = require('devp2p-dpt') | ||
@@ -23,37 +23,36 @@ /** | ||
*/ | ||
var Network = exports = module.exports = function(options) { | ||
var Network = exports = module.exports = function (options) { | ||
var self = this | ||
var self = this; | ||
// Register as event emitter | ||
EventEmitter.call(this) | ||
//Register as event emitter | ||
EventEmitter.call(this); | ||
//setup defaults | ||
// setup defaults | ||
var optionDefaults = { | ||
timeout: 20000, //10 seconds | ||
timeout: 20000, // 10 seconds | ||
maxPeers: 10, | ||
clientId: 'Ethereum Node.js/' + pjson.version | ||
}; | ||
} | ||
options = options ? options : {}; | ||
_.defaults(options, optionDefaults); | ||
_.defaults(this, options); | ||
options = options || {} | ||
_.defaults(options, optionDefaults) | ||
_.defaults(this, options) | ||
if (!this.secretKey) { | ||
this.secretKey = crypto.randomBytes(32); | ||
this.secretKey = crypto.randomBytes(32) | ||
} | ||
this._peers = {}; //list of peer connected to | ||
this._stopping = false; | ||
this.port = 0; | ||
this.protocolVersion = 3, | ||
this._peers = {} // list of peer connected to | ||
this._stopping = false | ||
this.port = 0 | ||
this.protocolVersion = 4 | ||
Object.defineProperties(this, { | ||
peers: { | ||
get: function() { | ||
return _.values(this._peers); | ||
get: function () { | ||
return _.values(this._peers) | ||
} | ||
} | ||
}); | ||
}) | ||
this.dpt = new DPT({ | ||
@@ -63,18 +62,16 @@ secretKey: this.secretKey, | ||
address: this.publicIp | ||
}); | ||
}) | ||
this.dpt.on('error', function(a, e){ | ||
console.log('dpt error'); | ||
console.log(a); | ||
console.log(e.stack); | ||
}); | ||
this.dpt.on('error', function (a, e) { | ||
console.log(a) | ||
}) | ||
this.dpt.on('newPeer', function(peer){ | ||
self.connect(peer); | ||
this.dpt.on('newPeer', function (peer) { | ||
self.connect(peer) | ||
}) | ||
this.server = net.createServer(this._onConnect.bind(this)); | ||
}; | ||
this.server = net.createServer(this._onConnect.bind(this)) | ||
} | ||
util.inherits(Network, EventEmitter); | ||
util.inherits(Network, EventEmitter) | ||
@@ -87,16 +84,15 @@ /** | ||
*/ | ||
Network.prototype.listen = function(port, host, cb) { | ||
var self = this; | ||
this.host = host ? host : '0.0.0.0'; | ||
this.port = port ? port : 30303; | ||
this._listening = true; | ||
Network.prototype.listen = function (port, host, cb) { | ||
this.host = host || '0.0.0.0' | ||
this.port = port || 30303 | ||
this._listening = true | ||
if (!_.isFunction(cb)) { | ||
cb = function(){}; | ||
cb = function () {} | ||
} | ||
this.dpt.bind(this.port, this.host); | ||
this.dpt.bind(this.port, this.host) | ||
this.server.listen(this.port, this.host, cb) | ||
enableDestroy(this.server); | ||
}; | ||
enableDestroy(this.server) | ||
} | ||
@@ -111,30 +107,27 @@ /** | ||
*/ | ||
Network.prototype.connect = function(peer, cb) { | ||
Network.prototype.connect = function (peer, cb) { | ||
if (!cb) cb = function () {} | ||
if (!cb) cb = function() {}; | ||
var self = this | ||
var openSlots = this.maxPeers - this.peers.length | ||
var self = this; | ||
var openSlots = this.maxPeers - this.peers.length; | ||
// connects to the peer once we have an ID | ||
function onId (err, peer) { | ||
var socket = new net.Socket() | ||
//connects to the peer once we have an ID | ||
function onId(err, peer) { | ||
function onError (e) { | ||
socket.destroy() | ||
cb(e) | ||
} | ||
if (!err) { | ||
var socket = new net.Socket(); | ||
function onError(e) { | ||
socket.destroy(); | ||
cb(e); | ||
} | ||
socket.setTimeout(self.timeout); | ||
socket.on('timeout', onError); | ||
socket.on('error', onError); | ||
socket.on('connect', function() { | ||
self._onConnect(socket, peer.id, true); | ||
socket.removeListener('error', onError); | ||
cb(); | ||
}); | ||
socket.connect(peer.port, peer.address); | ||
socket.on('error', onError) | ||
socket.on('connect', function () { | ||
self._onConnect(socket, peer.id, true) | ||
socket.removeListener('error', onError) | ||
cb() | ||
}) | ||
socket.connect(peer.port, peer.address) | ||
} else { | ||
cb(err); | ||
cb(err) | ||
} | ||
@@ -145,51 +138,51 @@ } | ||
if (!peer.id) { | ||
//ping the peer to get its public key, aka ID | ||
// ping the peer to get its public key, aka ID | ||
this.dpt.ping({ | ||
address: peer.address, | ||
port: peer.port | ||
}, cb); | ||
}, cb) | ||
} else { | ||
onId(null, peer); | ||
onId(null, peer) | ||
} | ||
} else { | ||
cb(); | ||
cb() | ||
} | ||
}; | ||
} | ||
//creates a new peer object and adds it to the peer hash | ||
Network.prototype._onConnect = function(socket, id, outgoing) { | ||
var self = this; | ||
var openSlots = this.maxPeers - this.peers.length; | ||
// creates a new peer object and adds it to the peer hash | ||
Network.prototype._onConnect = function (socket, id, outgoing) { | ||
var self = this | ||
var openSlots = this.maxPeers - this.peers.length | ||
if (openSlots > 0) { | ||
if (!this.publicIp) { | ||
this.publicIp = socket.localAddress; | ||
this.publicIp = socket.localAddress | ||
} | ||
var peer = new Peer(socket, self, id); | ||
var peer = new Peer(socket, self, id) | ||
if(!id){ | ||
peer.on('connection', function(){ | ||
self._peers[peer.id.toString('hex')] = peer; | ||
}); | ||
}else{ | ||
self._peers[id.toString('hex')] = peer; | ||
if (!id) { | ||
peer.on('connection', function () { | ||
self._peers[peer.id.toString('hex')] = peer | ||
}) | ||
} else { | ||
self._peers[id.toString('hex')] = peer | ||
} | ||
//disconnect delete peers | ||
socket.on('close', function() { | ||
self.emit('closing', peer); | ||
//delete refrances to the peer | ||
self._popPeerList(); | ||
delete self._peers[peer.id.toString('hex')]; | ||
}); | ||
// disconnect delete peers | ||
socket.on('close', function () { | ||
self.emit('closing', peer) | ||
// delete refrances to the peer | ||
self._popPeerList() | ||
delete self._peers[peer.id.toString('hex')] | ||
}) | ||
if(outgoing){ | ||
peer.state = 'Ack'; | ||
peer.sendAuth(); | ||
if (outgoing) { | ||
peer.state = 'Ack' | ||
peer.sendAuth() | ||
} | ||
} else { | ||
socket.destroy(); | ||
socket.destroy() | ||
} | ||
}; | ||
} | ||
@@ -201,27 +194,26 @@ /** | ||
*/ | ||
Network.prototype.close = function(cb) { | ||
var self = this; | ||
this._stopping = true; | ||
this.dpt.close(); | ||
Network.prototype.close = function (cb) { | ||
var self = this | ||
this._stopping = true | ||
this.dpt.close() | ||
//disconnect all the peers | ||
async.each(this.peers, function(peer, cb2) { | ||
//TODO add timeouts | ||
peer.socket.once('close', cb2); | ||
//0x08 Client quitting. | ||
peer.sendDisconnect(0x08, function() { | ||
peer.socket.end(); | ||
}); | ||
}, function() { | ||
//disconnect peers | ||
// disconnect all the peers | ||
async.each(this.peers, function (peer, cb2) { | ||
// TODO add timeouts | ||
peer.socket.once('close', cb2) | ||
// 0x08 Client quitting. | ||
peer.sendDisconnect(0x08, function () { | ||
peer.socket.end() | ||
}) | ||
}, function () { | ||
// disconnect peers | ||
if (self._listening) { | ||
self.server.destroy(cb); | ||
// self.server.close(cb); | ||
self.server.destroy(cb) | ||
// self.server.close(cb) | ||
} else if (cb) { | ||
cb(); | ||
cb() | ||
} | ||
}); | ||
}; | ||
}) | ||
} | ||
/** | ||
@@ -232,28 +224,27 @@ * Pops peers off the peer list and connects to them untill we reach maxPeers | ||
*/ | ||
Network.prototype._popPeerList = function() { | ||
Network.prototype._popPeerList = function () { | ||
var openSlots = this.maxPeers - this.peers.length | ||
var self = this | ||
var openSlots = this.maxPeers - this.peers.length; | ||
var self = this; | ||
if (openSlots > 0 && !this._stopping) { | ||
//find peer that we are not already connected to | ||
var peers = self.dpt.kBucket.toArray().filter(function(p){ | ||
return !self._peers[p.id.toString('hex')]; | ||
}); | ||
// find peer that we are not already connected to | ||
var peers = self.dpt.kBucket.toArray().filter(function (p) { | ||
return !self._peers[p.id.toString('hex')] | ||
}) | ||
var i = openSlots; | ||
var i = openSlots | ||
var q = async.queue(function (peer, cb) { | ||
self.connect(peer, function(err){ | ||
if(err){ | ||
i++; | ||
if(peers[i]){ | ||
q.push(peers[i]) | ||
} | ||
self.connect(peer, function (err) { | ||
if (err) { | ||
i++ | ||
if (peers[i]) { | ||
q.push(peers[i]) | ||
} | ||
cb(); | ||
} | ||
cb() | ||
}) | ||
}, openSlots); | ||
}, openSlots) | ||
q.push(peers.slice(0, openSlots)); | ||
q.push(peers.slice(0, openSlots)) | ||
} | ||
}; | ||
} |
@@ -1,35 +0,33 @@ | ||
const sha3 = require('sha3') | ||
const xor = require('bitwise-xor'); | ||
const crypto = require('crypto'); | ||
const sha3 = require('sha3') | ||
const xor = require('bitwise-xor') | ||
const crypto = require('crypto') | ||
var MAC = module.exports = function(secret){ | ||
this.secret = secret; | ||
this.sha3 = new sha3.SHA3Hash(256); | ||
var MAC = module.exports = function (secret) { | ||
this.secret = secret | ||
this.sha3 = new sha3.SHA3Hash(256) | ||
} | ||
}; | ||
/** | ||
* Updates the underlining SHA3 256 | ||
*/ | ||
MAC.prototype.rawUpdate = function(data){ | ||
this.sha3.update(data); | ||
MAC.prototype.rawUpdate = function (data) { | ||
this.sha3.update(data) | ||
} | ||
MAC.prototype.updateHeader = function(data){ | ||
var aes = crypto.createCipheriv('aes-256-ecb', this.secret, ''); | ||
var encrypted = aes.update(this.digest()); | ||
this.sha3.update(xor(encrypted, data)); | ||
MAC.prototype.updateHeader = function (data) { | ||
var aes = crypto.createCipheriv('aes-256-ecb', this.secret, '') | ||
var encrypted = aes.update(this.digest()) | ||
this.sha3.update(xor(encrypted, data)) | ||
} | ||
MAC.prototype.updateBody = function(data){ | ||
this.sha3.update(data); | ||
var prev = this.digest(); | ||
var aes = crypto.createCipheriv('aes-256-ecb', this.secret, ''); | ||
var encrypted = aes.update(prev); | ||
this.sha3.update(xor(encrypted, prev)); | ||
MAC.prototype.updateBody = function (data) { | ||
this.sha3.update(data) | ||
var prev = this.digest() | ||
var aes = crypto.createCipheriv('aes-256-ecb', this.secret, '') | ||
var encrypted = aes.update(prev) | ||
this.sha3.update(xor(encrypted, prev)) | ||
} | ||
MAC.prototype.digest = function(){ | ||
return new Buffer(this.sha3.digest('hex'), 'hex').slice(0, 16); | ||
MAC.prototype.digest = function () { | ||
return new Buffer(this.sha3.digest('hex'), 'hex').slice(0, 16) | ||
} | ||
@@ -1,3 +0,3 @@ | ||
var utils = require('ethereumjs-util'), | ||
codes = require('./codes.js'); | ||
const utils = require('ethereumjs-util') | ||
const codes = require('./codes.js') | ||
@@ -11,28 +11,28 @@ exports.offsets = { | ||
0x05: 'peers' | ||
}; | ||
} | ||
exports.meta = { | ||
version: 2 | ||
}; | ||
} | ||
function encodePeers(peers) { | ||
var peerArray = []; | ||
peers.forEach(function(peer) { | ||
function encodePeers (peers) { | ||
var peerArray = [] | ||
peers.forEach(function (peer) { | ||
if (peer.publicIp && peer.port !== 0) { | ||
var ip = new Buffer(peer.publicIp.split('.')); | ||
var port = new Buffer(2); | ||
port.writeUInt16BE(peer.port, 0); | ||
var id = new Buffer(peer.id, 'hex'); | ||
peerArray.push([ip, port, id]); | ||
var ip = new Buffer(peer.publicIp.split('.')) | ||
var port = new Buffer(2) | ||
port.writeUInt16BE(peer.port, 0) | ||
var id = new Buffer(peer.id, 'hex') | ||
peerArray.push([ip, port, id]) | ||
} | ||
}); | ||
return peerArray; | ||
}) | ||
return peerArray | ||
} | ||
function parseHello(payload) { | ||
//build hello message | ||
var caps = {}; | ||
payload[3].forEach(function(p) { | ||
caps[p[0].toString()] = utils.bufferToInt(p[1]); | ||
}); | ||
function parseHello (payload) { | ||
// build hello message | ||
var caps = {} | ||
payload[3].forEach(function (p) { | ||
caps[p[0].toString()] = utils.bufferToInt(p[1]) | ||
}) | ||
@@ -46,12 +46,12 @@ var hello = { | ||
ip: this.socket.remoteAddress | ||
}; | ||
} | ||
return hello; | ||
return hello | ||
} | ||
function parsePeers(payload) { | ||
var message = []; | ||
//format message | ||
function parsePeers (payload) { | ||
var message = [] | ||
// format message | ||
for (var i = 1; i < payload.length; i++) { | ||
var peer = payload[i]; | ||
var peer = payload[i] | ||
var peerObject = { | ||
@@ -62,14 +62,13 @@ publicIp: peer[0][0] + '.' + peer[0][1] + '.' + peer[0][2] + '.' + peer[0][3], | ||
recTime: new Date() | ||
}; | ||
message.push(peerObject); | ||
} | ||
message.push(peerObject) | ||
} | ||
return message; | ||
return message | ||
} | ||
exports.send = { | ||
hello: function() { | ||
var caps = []; | ||
hello: function () { | ||
var caps = [] | ||
for (var cap in this.network.capabilities) { | ||
caps.push([cap, new Buffer([Number(this.network.capabilities[cap])])]); | ||
caps.push([cap, new Buffer([Number(this.network.capabilities[cap])])]) | ||
} | ||
@@ -83,35 +82,35 @@ | ||
new Buffer(this.network.id, 'hex') | ||
]; | ||
] | ||
return message; | ||
return message | ||
}, | ||
disconnect: function(reason, onDone) { | ||
var self = this; | ||
disconnect: function (reason, onDone) { | ||
var self = this | ||
if (!reason) { | ||
reason = 0x00; | ||
reason = 0x00 | ||
} | ||
//define a on done hook | ||
onDone(function() { | ||
self.socket.end(); | ||
}); | ||
// define a on done hook | ||
onDone(function () { | ||
self.socket.end() | ||
}) | ||
return [reason]; | ||
return [reason] | ||
}, | ||
peers: function(peers) { | ||
peers = encodePeers(peers); | ||
return peers; | ||
peers: function (peers) { | ||
peers = encodePeers(peers) | ||
return peers | ||
} | ||
}; | ||
} | ||
exports.parse = { | ||
hello: parseHello, | ||
disconnect: function(payload) { | ||
disconnect: function (payload) { | ||
return { | ||
reason: codes.disconnect[payload[1][0]], | ||
code: payload[1] | ||
}; | ||
} | ||
}, | ||
peers: parsePeers | ||
}; | ||
} |
366
lib/peer.js
@@ -1,7 +0,7 @@ | ||
const util = require('util'); | ||
const ethUtil = require('ethereumjs-util'); | ||
const EventEmitter = require('events').EventEmitter; | ||
const ECIES = require('./ecies.js'); | ||
const rlp = require('rlp'); | ||
const Stream = require('./stream.js'); | ||
const util = require('util') | ||
const ethUtil = require('ethereumjs-util') | ||
const EventEmitter = require('events').EventEmitter | ||
const ECIES = require('./ecies.js') | ||
const rlp = require('rlp') | ||
const Stream = require('./stream.js') | ||
@@ -15,8 +15,2 @@ const prefix = { | ||
const size = { | ||
HEADER: 32, | ||
AUTH: 307, | ||
ACK: 210 | ||
} | ||
/** | ||
@@ -27,70 +21,70 @@ * @contructor | ||
*/ | ||
var Peer = exports = module.exports = function(socket, network, id) { | ||
var Peer = exports = module.exports = function (socket, network, id) { | ||
// Register as event emitter | ||
EventEmitter.call(this); | ||
EventEmitter.call(this) | ||
this.id = id; | ||
this.socket = socket; | ||
this.network = network; | ||
this.initiator = true; //did this peer start the connection | ||
this.DISCONNECT_REASONS = Peer.disconnectReasons; | ||
this.id = id | ||
this.socket = socket | ||
this.network = network | ||
this.initiator = true // did this peer start the connection | ||
this.DISCONNECT_REASONS = Peer.disconnectReasons | ||
this.eciesSession = new ECIES( | ||
this.network.secretKey, //secert key | ||
Buffer.concat([new Buffer([4]), this.network.dpt.id]) //public key | ||
); | ||
this.network.secretKey, // secert key | ||
Buffer.concat([new Buffer([4]), this.network.dpt.id]) // public key | ||
) | ||
if(id){ | ||
this.eciesSession.remotePubKey = Buffer.concat([new Buffer([4]), this.id]); //remote public key | ||
if (id) { | ||
this.eciesSession.remotePubKey = Buffer.concat([new Buffer([4]), this.id]) // remote public key | ||
} | ||
//the ephemral shared secret | ||
// the ephemral shared secret | ||
Object.defineProperty(this, 'ephemeralSecret', { | ||
get: function() { | ||
get: function () { | ||
if (!this._ephShared) { | ||
this._ephShared = ECIES.ecdh(this.ephemeralSecKey, Buffer.concat([new Buffer([4]), this.remoteEphemeralPubKey])); | ||
this._ephShared = ECIES.ecdh(this.ephemeralSecKey, Buffer.concat([new Buffer([4]), this.remoteEphemeralPubKey])) | ||
} | ||
return this._ephShared; | ||
return this._ephShared | ||
} | ||
}); | ||
}) | ||
Object.defineProperty(this, 'staticSecret', { | ||
get: function() { | ||
get: function () { | ||
if (!this._staticShared) { | ||
this._staticShared = ECIES.ecdh(this.network.secretKey, Buffer.concat([new Buffer([4]), this.id])); | ||
this._staticShared = ECIES.ecdh(this.network.secretKey, Buffer.concat([new Buffer([4]), this.id])) | ||
} | ||
return this._staticShared; | ||
return this._staticShared | ||
} | ||
}); | ||
}) | ||
this.state = 'Auth'; | ||
//Auth, Ack, HelloHeader, HelloFrame, Header, Frame | ||
this.hello = false; //the info given by the hello packet | ||
this.state = 'Auth' | ||
// Auth, Ack, HelloHeader, HelloFrame, Header, Frame | ||
this.hello = false // the info given by the hello packet | ||
this._nextPacketSize = 307; | ||
this._nextPacketSize = 307 | ||
var self = this; | ||
socket.on('error', function(e) { | ||
self.emit('error', e); | ||
}); | ||
var self = this | ||
socket.on('error', function (e) { | ||
self.emit('error', e) | ||
}) | ||
var data = new Buffer([]); | ||
var data = new Buffer([]) | ||
//defines the packet parsing behavoir | ||
socket.on('data', function(newData) { | ||
var more = true; | ||
data = Buffer.concat([data, newData]); | ||
// defines the packet parsing behavoir | ||
socket.on('data', function (newData) { | ||
var more = true | ||
data = Buffer.concat([data, newData]) | ||
while (more) { | ||
if (data.length >= self._nextPacketSize) { | ||
var remainder = data.slice(self._nextPacketSize); | ||
self.parseData(data.slice(0, self._nextPacketSize)); | ||
data = remainder; | ||
var remainder = data.slice(self._nextPacketSize) | ||
self.parseData(data.slice(0, self._nextPacketSize)) | ||
data = remainder | ||
} else { | ||
more = false; | ||
more = false | ||
} | ||
} | ||
}); | ||
}; | ||
}) | ||
} | ||
util.inherits(Peer, EventEmitter); | ||
util.inherits(Peer, EventEmitter) | ||
@@ -113,121 +107,120 @@ Peer.disconnectReasons = { | ||
Peer.prototype.sendAuth = function() { | ||
//public keys need 0x4 appended to them | ||
var self = this; | ||
var msg = this.eciesSession.createAuth(); | ||
this.socket.write(msg, function() { | ||
self.state = 'Ack'; | ||
self._nextPacketSize = 210; | ||
}); | ||
}; | ||
Peer.prototype.sendAuth = function () { | ||
// public keys need 0x4 appended to them | ||
var self = this | ||
var msg = this.eciesSession.createAuth() | ||
this.socket.write(msg, function () { | ||
self.state = 'Ack' | ||
self._nextPacketSize = 210 | ||
}) | ||
} | ||
Peer.prototype.sendAck = function() { | ||
var self = this; | ||
var msg = this.eciesSession.createAck(this.ourEphemeralPubKey, this.id, this.nonce); | ||
this.socket.write(msg, function() { | ||
self.state = 'Header'; | ||
self._nextPacketSize = 32; | ||
self.sendHello(); | ||
}); | ||
}; | ||
Peer.prototype.sendAck = function () { | ||
var self = this | ||
var msg = this.eciesSession.createAck(this.ourEphemeralPubKey, this.id, this.nonce) | ||
this.socket.write(msg, function () { | ||
self.state = 'Header' | ||
self._nextPacketSize = 32 | ||
self.sendHello() | ||
}) | ||
} | ||
Peer.prototype.parseData = function(data) { | ||
Peer.prototype.parseData = function (data) { | ||
switch (this.state) { | ||
case 'Auth': | ||
this.eciesSession.parseAuth(data); | ||
this.id = this.eciesSession.remotePubKey.slice(1); | ||
this.sendAck(); | ||
this.state = 'Header'; | ||
this._nextPacketSize = 32; | ||
break; | ||
this.eciesSession.parseAuth(data) | ||
this.id = this.eciesSession.remotePubKey.slice(1) | ||
this.sendAck() | ||
this.state = 'Header' | ||
this._nextPacketSize = 32 | ||
break | ||
case 'Ack': | ||
this.eciesSession.parseAck(data); | ||
this.state = 'Header'; | ||
this._nextPacketSize = 32; | ||
this.sendHello(); | ||
break; | ||
this.eciesSession.parseAck(data) | ||
this.state = 'Header' | ||
this._nextPacketSize = 32 | ||
this.sendHello() | ||
break | ||
case 'Header': | ||
var size = this.eciesSession.parseHeader(data); | ||
this.state = 'Body'; | ||
var remainder = size % 16; | ||
if(remainder){ | ||
this._nextPacketSize = (16 - remainder) + size + 16; | ||
}else{ | ||
this._nextPacketSize = size + 16; | ||
var size = this.eciesSession.parseHeader(data) | ||
this.state = 'Body' | ||
var remainder = size % 16 | ||
if (remainder) { | ||
this._nextPacketSize = (16 - remainder) + size + 16 | ||
} else { | ||
this._nextPacketSize = size + 16 | ||
} | ||
break; | ||
break | ||
case 'Body': | ||
var body = this.eciesSession.parseBody(data); | ||
//process the body | ||
//pipe out ect | ||
this.state = 'Header'; | ||
this._nextPacketSize = 32; | ||
var body = this.eciesSession.parseBody(data) | ||
// process the body | ||
// pipe out ect | ||
this.state = 'Header' | ||
this._nextPacketSize = 32 | ||
var type = body.slice(0, 1); | ||
//check for base types | ||
var type = body.slice(0, 1) | ||
// check for base types | ||
if (type[0] < 0x10 || type[0] === 0x80) { | ||
this.parseBasePacket(type, body.slice(1)); | ||
}else{ | ||
this.emit('data', body); | ||
this.parseBasePacket(type, body.slice(1)) | ||
} else { | ||
this.emit('data', body) | ||
} | ||
break; | ||
//error | ||
break | ||
// error | ||
} | ||
}; | ||
} | ||
Peer.prototype.parseBasePacket = function(type, data) { | ||
var decoded = rlp.decode(data); | ||
switch (type[0]) { | ||
//hello | ||
case 0x80: | ||
//mark hello | ||
this.hello = this.parseHello(decoded); | ||
this.caps = this.hello.capabilities; | ||
var ourCaps = this.network.capabilities; | ||
var sharedProto = []; | ||
Peer.prototype.parseBasePacket = function (type, data) { | ||
var decoded = rlp.decode(data) | ||
switch (type[0]) { | ||
// hello | ||
case 0x80: | ||
// mark hello | ||
this.hello = this.parseHello(decoded) | ||
this.caps = this.hello.capabilities | ||
var ourCaps = this.network.capabilities | ||
var sharedProto = [] | ||
//disconnect if using differnt protocols versions | ||
for (var cap in this.hello.capabilities) { | ||
if (ourCaps[cap] && ourCaps[cap] !== this.hello.capabilities[cap]) { | ||
this.sendDisconnect(0x07); | ||
}else{ | ||
sharedProto.push(cap); | ||
} | ||
// disconnect if using differnt protocols versions | ||
for (var cap in this.hello.capabilities) { | ||
if (ourCaps[cap] && ourCaps[cap] !== this.hello.capabilities[cap]) { | ||
this.sendDisconnect(0x07) | ||
} else { | ||
sharedProto.push(cap) | ||
} | ||
this.emit('connection', this); | ||
this.network.emit('connection', this); | ||
break; | ||
} | ||
this.emit('connection', this) | ||
this.network.emit('connection', this) | ||
break | ||
//on disconnect | ||
case 1: | ||
this.emit('close'); | ||
this.socket.end(); | ||
break; | ||
// on disconnect | ||
case 1: | ||
this.emit('close') | ||
this.socket.end() | ||
break | ||
//on ping | ||
case 2: | ||
this.sendPong(); | ||
break; | ||
// on ping | ||
case 2: | ||
this.sendPong() | ||
break | ||
case 3: | ||
this.emit('pong'); | ||
break; | ||
case 3: | ||
this.emit('pong') | ||
break | ||
} | ||
}; | ||
} | ||
Peer.prototype.toString = function() { | ||
return this.socket.remoteAddress + ':' + this.socket.remotePort; | ||
}; | ||
Peer.prototype.toString = function () { | ||
return this.socket.remoteAddress + ':' + this.socket.remotePort | ||
} | ||
Peer.prototype.parseHello = function(payload) { | ||
//build hello message | ||
var caps = {}; | ||
payload[2].forEach(function(p) { | ||
caps[p[0].toString()] = ethUtil.bufferToInt(p[1]); | ||
}); | ||
Peer.prototype.parseHello = function (payload) { | ||
// build hello message | ||
var caps = {} | ||
payload[2].forEach(function (p) { | ||
caps[p[0].toString()] = ethUtil.bufferToInt(p[1]) | ||
}) | ||
@@ -240,12 +233,13 @@ var hello = { | ||
id: payload[4].toString('hex') | ||
}; | ||
} | ||
return hello; | ||
}; | ||
return hello | ||
} | ||
Peer.prototype.createHello = function() { | ||
var caps = []; | ||
Peer.prototype.createHello = function () { | ||
var caps = [] | ||
for (var cap in this.network.capabilities) { | ||
caps.push([cap, new Buffer([Number(this.network.capabilities[cap])])]); | ||
caps.push([cap, new Buffer([Number(this.network.capabilities[cap])])]) | ||
} | ||
var message = [ | ||
@@ -257,50 +251,48 @@ this.network.protocolVersion, | ||
this.network.dpt.id | ||
]; | ||
] | ||
var msg = this.parseHello(rlp.decode( rlp.encode(message) ) ); | ||
return Buffer.concat([new Buffer([0x80]), rlp.encode(message)]); | ||
}; | ||
return Buffer.concat([new Buffer([0x80]), rlp.encode(message)]) | ||
} | ||
Peer.prototype.sendHello = function(cb){ | ||
var msg = this.createHello(); | ||
this.sendMessage(msg, cb); | ||
}; | ||
Peer.prototype.sendHello = function (cb) { | ||
var msg = this.createHello() | ||
this.sendMessage(msg, cb) | ||
} | ||
Peer.prototype.sendPing = function(cb){ | ||
var msg = new Buffer([prefix.PING, 0xc0]); | ||
this.sendMessage(msg, cb); | ||
Peer.prototype.sendPing = function (cb) { | ||
var msg = new Buffer([prefix.PING, 0xc0]) | ||
this.sendMessage(msg, cb) | ||
} | ||
Peer.prototype.sendPong = function(cb){ | ||
var msg = new Buffer([prefix.PONG, 0xc0]); | ||
this.sendMessage(msg, cb); | ||
Peer.prototype.sendPong = function (cb) { | ||
var msg = new Buffer([prefix.PONG, 0xc0]) | ||
this.sendMessage(msg, cb) | ||
} | ||
Peer.prototype.sendDisconnect = function(reason){ | ||
if(reason === undefined) | ||
reason = Peer.disconnectReasons.DISCONNECT_REQUESTED; | ||
Peer.prototype.sendDisconnect = function (reason) { | ||
if (reason === undefined) { | ||
reason = Peer.disconnectReasons.DISCONNECT_REQUESTED | ||
} | ||
var msg = new Buffer([prefix.DISCONNECT, rlp.encode[reason]]); | ||
var header = this.eciesSession.createHeader(msg.length); | ||
var body = this.eciesSession.createBody(msg); | ||
this.socket.write(header); | ||
this.socket.end(body); | ||
var msg = new Buffer([prefix.DISCONNECT, rlp.encode[reason]]) | ||
var header = this.eciesSession.createHeader(msg.length) | ||
var body = this.eciesSession.createBody(msg) | ||
this.socket.write(header) | ||
this.socket.end(body) | ||
} | ||
Peer.prototype.sendMessage = function(msg, cb){ | ||
var header = this.eciesSession.createHeader(msg.length); | ||
var body = this.eciesSession.createBody(msg); | ||
this.socket.write(header); | ||
this.socket.write(body, cb); | ||
Peer.prototype.sendMessage = function (msg, cb) { | ||
var header = this.eciesSession.createHeader(msg.length) | ||
var body = this.eciesSession.createBody(msg) | ||
this.socket.write(header) | ||
this.socket.write(body, cb) | ||
} | ||
Peer.prototype.end = function(reason) { | ||
var self = this; | ||
// stream.Duplex.prototype.end.call(this); | ||
Peer.prototype.end = function (reason) { | ||
// stream.Duplex.prototype.end.call(this) | ||
this.sendDisconnect(reason) | ||
}; | ||
} | ||
Peer.prototype.createStream = function(opts){ | ||
return new Stream(opts, this); | ||
Peer.prototype.createStream = function (opts) { | ||
return new Stream(opts, this) | ||
} |
@@ -1,55 +0,52 @@ | ||
const Duplex = require('stream').Duplex; | ||
const util = require('util'); | ||
const Duplex = require('stream').Duplex | ||
const util = require('util') | ||
var Stream = module.exports = function(opts, peer) { | ||
var self = this; | ||
this.peer = peer; | ||
this._packets = []; | ||
self._closed = false; | ||
self._reading = false; | ||
self._prefix = new Buffer([0xff]) | ||
Duplex.call(this, opts); | ||
this.peer.socket.on('end', function(){ | ||
console.log('closeing stream, socket ended'); | ||
self._closed = true; | ||
self.push(null); | ||
}); | ||
var Stream = module.exports = function (opts, peer) { | ||
var self = this | ||
this.peer = peer | ||
this._packets = [] | ||
self._closed = false | ||
self._reading = false | ||
// self._prefix = new Buffer([0xff]) | ||
Duplex.call(this, opts) | ||
this.peer.socket.on('end', function () { | ||
self._closed = true | ||
self.push(null) | ||
}) | ||
this.peer.socket.on('error', function(){ | ||
console.log('closeing stream,error'); | ||
self._closed = true; | ||
self.push(null); | ||
}); | ||
this.peer.socket.on('error', function () { | ||
self._closed = true | ||
self.push(null) | ||
}) | ||
} | ||
util.inherits(Stream, Duplex); | ||
util.inherits(Stream, Duplex) | ||
Stream.prototype._read = function readBytes() { | ||
var self = this; | ||
//change to check type | ||
Stream.prototype._read = function readBytes () { | ||
var self = this | ||
// change to check type | ||
while (this._packets.length) { | ||
var chunk = this._packets.shift(); | ||
if(this._prefix){ | ||
chunk = chunk.slice(1); | ||
var chunk = this._packets.shift() | ||
if (this._prefix) { | ||
chunk = chunk.slice(1) | ||
} | ||
if (!self.push(chunk)) { | ||
break; // false from push, stop reading | ||
break // false from push, stop reading | ||
} | ||
} | ||
if (!self._closed && !self._reading) { | ||
self._reading = true; | ||
this.peer.on('data', function(data){ | ||
self._packets.push(data); | ||
self._read(); | ||
self._reading = true | ||
this.peer.on('data', function (data) { | ||
self._packets.push(data) | ||
self._read() | ||
}) | ||
} | ||
}; | ||
} | ||
} | ||
Stream.prototype._write = function(chunk, enc, cb) { | ||
if(this._prefix){ | ||
chunk = Buffer.concat([this._prefix, chunk]); | ||
Stream.prototype._write = function (chunk, enc, cb) { | ||
if (this._prefix) { | ||
chunk = Buffer.concat([this._prefix, chunk]) | ||
} | ||
this.peer.sendMessage(chunk, cb) | ||
}; | ||
} |
{ | ||
"name": "devp2p", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "A javascript libary implementing RPLx the ethereum p2p protocol", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha ./test" | ||
"test": "standard ./index.js ./lib/*.js && mocha ./test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ethereum/ethereumjs-p2p.git" | ||
"url": "https://github.com/ethereum/node-devp2p.git" | ||
}, | ||
@@ -19,3 +19,3 @@ "keywords": [ | ||
"author": "mjbecze", | ||
"license": "GPL", | ||
"license": "MPL-2.0", | ||
"bugs": { | ||
@@ -26,10 +26,10 @@ "url": "https://github.com/ethereum/ethereumjs-p2p/issues" | ||
"dependencies": { | ||
"async": "^0.9.0", | ||
"async": "^1.4.2", | ||
"bigi": "^1.4.0", | ||
"bitwise-xor": "0.0.0", | ||
"devp2p-dpt": "0.0.2", | ||
"devp2p-dpt": "0.0.3", | ||
"ecurve": "^1.0.1", | ||
"ethereumjs-util": "0.1.0", | ||
"rlp": "0.0.14", | ||
"secp256k1": "0.0.15", | ||
"ethereumjs-util": "2.0.3", | ||
"rlp": "2.0.0", | ||
"secp256k1": "1.1.4", | ||
"server-destroy": "^1.0.0", | ||
@@ -43,4 +43,5 @@ "sha3": "^1.1.0", | ||
"mocha": "^2.1.0", | ||
"standard": "^5.3.1", | ||
"tape": "^4.0.0" | ||
} | ||
} |
@@ -1,56 +0,56 @@ | ||
var ECIES = require('../lib/ecies.js'); | ||
var ecdsa = require('secp256k1'); | ||
var crypto = require('crypto'); | ||
var assert = require('assert'); | ||
var ECIES = require('../lib/ecies.js') | ||
var ecdsa = require('secp256k1') | ||
var crypto = require('crypto') | ||
var assert = require('assert') | ||
var a; | ||
var b; | ||
var a | ||
var b | ||
describe('[Network]: ECIES', function() { | ||
it('should create a new ECIES instance', function(done){ | ||
var privateKey = crypto.randomBytes(32); | ||
var privateKey2 = crypto.randomBytes(32); | ||
var pubKey = ecdsa.createPublicKey(privateKey); | ||
var pubKey2 = ecdsa.createPublicKey(privateKey2); | ||
a = new ECIES(privateKey, pubKey, pubKey2); | ||
b = new ECIES(privateKey2, pubKey2, pubKey); | ||
done(); | ||
}); | ||
describe('[Network]: ECIES', function () { | ||
it('should create a new ECIES instance', function (done) { | ||
var privateKey = crypto.randomBytes(32) | ||
var privateKey2 = crypto.randomBytes(32) | ||
var pubKey = ecdsa.createPublicKey(privateKey) | ||
var pubKey2 = ecdsa.createPublicKey(privateKey2) | ||
a = new ECIES(privateKey, pubKey, pubKey2) | ||
b = new ECIES(privateKey2, pubKey2, pubKey) | ||
done() | ||
}) | ||
it('should encrypt and decrypt', function(done) { | ||
var message = new Buffer('The Magic Words are Squeamish Ossifrage'); | ||
var privateKey = crypto.randomBytes(32); | ||
var encypted = a.encryptMessage(privateKey, message); | ||
var decrypted = b.decryptMessage(encypted); | ||
assert(message.toString() === decrypted.toString()); | ||
done(); | ||
}); | ||
it('should encrypt and decrypt', function (done) { | ||
var message = new Buffer('The Magic Words are Squeamish Ossifrage') | ||
var privateKey = crypto.randomBytes(32) | ||
var encypted = a.encryptMessage(privateKey, message) | ||
var decrypted = b.decryptMessage(encypted) | ||
assert(message.toString() === decrypted.toString()) | ||
done() | ||
}) | ||
it('should create an auth message and parse it', function(done) { | ||
var data = a.createAuth(); | ||
b.parseAuth(data); | ||
done(); | ||
}); | ||
it('should create an auth message and parse it', function (done) { | ||
var data = a.createAuth() | ||
b.parseAuth(data) | ||
done() | ||
}) | ||
it('should create an ack message and parse it', function(done){ | ||
var data = b.createAck(); | ||
a.parseAck(data); | ||
done(); | ||
}); | ||
it('should create an ack message and parse it', function (done) { | ||
var data = b.createAck() | ||
a.parseAck(data) | ||
done() | ||
}) | ||
it('should create a frame header and parse it', function(done){ | ||
var size = 600; | ||
var data = a.createHeader(size); | ||
var out = b.parseHeader(data); | ||
assert(size === out); | ||
done(); | ||
}); | ||
it('should create a frame header and parse it', function (done) { | ||
var size = 600 | ||
var data = a.createHeader(size) | ||
var out = b.parseHeader(data) | ||
assert(size === out) | ||
done() | ||
}) | ||
it('should create a frame body and parse it', function(done){ | ||
var something = new Buffer(600); | ||
var data = a.createBody(something); | ||
var result = b.parseBody(data); | ||
assert(something.toString('hex') === result.toString('hex')); | ||
done(); | ||
}); | ||
}); | ||
it('should create a frame body and parse it', function (done) { | ||
var something = new Buffer(600) | ||
var data = a.createBody(something) | ||
var result = b.parseBody(data) | ||
assert(something.toString('hex') === result.toString('hex')) | ||
done() | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
0
35299
5
14
2
70
1000
3
+ Addedasync@1.5.2(transitive)
+ Addedbn.js@3.3.0(transitive)
+ Addedbrorand@1.1.0(transitive)
+ Addedbrowserify-sha3@0.0.0(transitive)
+ Addeddevp2p-dpt@0.0.3(transitive)
+ Addedelliptic@5.2.1(transitive)
+ Addedethereumjs-util@2.0.22.0.3(transitive)
+ Addedhash.js@1.1.7(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedjs-sha3@0.3.1(transitive)
+ Addedminimalistic-assert@1.0.1(transitive)
+ Addednan@2.22.0(transitive)
+ Addedrlp@2.0.0(transitive)
+ Addedsecp256k1@1.1.31.1.4(transitive)
- Removedasync@0.9.2(transitive)
- Removedbn.js@2.2.0(transitive)
- Removedcrypto-js@3.3.0(transitive)
- Removeddevp2p-dpt@0.0.2(transitive)
- Removedethereumjs-util@0.1.0(transitive)
- Removednan@1.9.0(transitive)
- Removedrlp@0.0.14(transitive)
- Removedsecp256k1@0.0.15(transitive)
Updatedasync@^1.4.2
Updateddevp2p-dpt@0.0.3
Updatedethereumjs-util@2.0.3
Updatedrlp@2.0.0
Updatedsecp256k1@1.1.4