Browse Source

migrate to blake2b and sodium

v4
Mathias Buus 7 years ago
parent
commit
7eda09cff3
  1. 16
      blake2b.js
  2. 23
      example.js
  3. 24
      index.js
  4. 6
      package.json
  5. 9
      query-stream.js
  6. 26
      test.js

16
blake2b.js

@ -0,0 +1,16 @@
var sodium = require('sodium-universal')
blake2b.batch = blake2bBatch
module.exports = blake2b
function blake2b (buf) {
var out = Buffer.allocUnsafe(32)
sodium.crypto_generichash(out, buf)
return out
}
function blake2bBatch (batch) {
var out = Buffer.allocUnsafe(32)
sodium.crypto_generichash_batch(out, batch)
return out
}

23
example.js

@ -1,21 +1,24 @@
var dht = require('./')
var crypto = require('crypto')
var blake2b = require('./blake2b')
var node = dht({
bootstrap: 'dht.mafintosh.com:10000'
bootstrap: 'localhost:49737',
ephemeral: !!process.argv[2]
})
var values = {}
node.on('closest:store', function (query, cb) {
node.on('update:store', function (query, cb) {
console.log('(onupdate)')
if (!query.value) return cb()
var key = sha256(query.value).toString('hex')
var key = blake2b(query.value).toString('hex')
values[key] = query.value
console.log('Storing', key, '-->', query.value.toString())
cb()
})
node.on('query:lookup', function (query, cb) {
console.log('(onquery)')
var value = values[query.target.toString('hex')]
cb(null, value)
})
@ -23,15 +26,15 @@ node.on('query:lookup', function (query, cb) {
if (process.argv.length > 3) {
var val = process.argv.slice(3).join(' ')
if (process.argv[2] === 'put') {
node.closest({command: 'store', target: sha256(val), value: val}, function (err) {
node.update({command: 'store', target: blake2b(Buffer.from(val)), value: val}, function (err) {
if (err) throw err
console.log('Inserted', sha256(val).toString('hex'))
console.log('Inserted', blake2b(Buffer.from(val)).toString('hex'))
})
}
if (process.argv[2] === 'get') {
node.query({command: 'lookup', target: new Buffer(val, 'hex')})
node.query({command: 'lookup', target: Buffer.from(val, 'hex')})
.on('data', function (data) {
if (data.value && sha256(data.value).toString('hex') === val) {
if (data.value && blake2b(data.value).toString('hex') === val) {
console.log(val, '-->', data.value.toString())
this.destroy()
}
@ -41,7 +44,3 @@ if (process.argv.length > 3) {
})
}
}
function sha256 (val) {
return crypto.createHash('sha256').update(val).digest()
}

24
index.js

@ -1,14 +1,14 @@
var udp = require('udp-request')
var crypto = require('crypto')
var KBucket = require('k-bucket')
var inherits = require('inherits')
var events = require('events')
var peers = require('ipv4-peers')
var bufferEquals = require('buffer-equals')
var collect = require('stream-collector')
var sodium = require('sodium-universal')
var nodes = peers.idLength(32)
var messages = require('./messages')
var queryStream = require('./query-stream')
var blake2b = require('./blake2b')
module.exports = DHT
@ -21,7 +21,7 @@ function DHT (opts) {
var self = this
this.concurrency = opts.concurrency || 16
this.id = opts.id || crypto.randomBytes(32)
this.id = opts.id || randomBytes(32)
this.ephemeral = !!opts.ephemeral
this.nodes = new KBucket({localNodeId: this.id, arbiter: arbiter})
this.nodes.on('ping', onnodeping)
@ -42,7 +42,7 @@ function DHT (opts) {
this._bootstrapped = false
this._pendingRequests = []
this._tick = 0
this._secrets = [crypto.randomBytes(32), crypto.randomBytes(32)]
this._secrets = [randomBytes(32), randomBytes(32)]
this._secretsInterval = setInterval(rotateSecrets, 5 * 60 * 1000)
this._tickInterval = setInterval(tick, 5 * 1000)
this._top = null
@ -146,7 +146,7 @@ DHT.prototype.address = function () {
}
DHT.prototype._rotateSecrets = function () {
var secret = crypto.randomBytes(32)
var secret = randomBytes(32)
this._secrets[1] = this._secrets[0]
this._secrets[0] = secret
}
@ -205,8 +205,8 @@ DHT.prototype._onrequest = function (request, peer) {
if (validateId(request.id)) this._addNode(request.id, peer, request.roundtripToken)
if (request.roundtripToken) {
if (!bufferEquals(request.roundtripToken, this._token(peer, 0))) {
if (!bufferEquals(request.roundtripToken, this._token(peer, 1))) {
if (!request.roundtripToken.equals(this._token(peer, 0))) {
if (!request.roundtripToken.equals(this._token(peer, 1))) {
request.roundtripToken = null
}
}
@ -370,11 +370,11 @@ DHT.prototype._reping = function (oldContacts, newContact) {
}
DHT.prototype._token = function (peer, i) {
return crypto.createHash('sha256').update(this._secrets[i]).update(peer.host).digest()
return blake2b.batch([this._secrets[i], Buffer.from(peer.host)])
}
DHT.prototype._addNode = function (id, peer, token) {
if (bufferEquals(id, this.id)) return
if (id.equals(this.id)) return
var node = this.nodes.get(id)
var fresh = !node
@ -459,3 +459,9 @@ function add (self, node) {
self._top = node
}
}
function randomBytes (n) {
var buf = Buffer.allocUnsafe(n)
sodium.randombytes_buf(buf)
return buf
}

6
package.json

@ -4,21 +4,21 @@
"description": "Make RPC calls over a Kademlia based DHT.",
"main": "index.js",
"dependencies": {
"buffer-equals": "^1.0.4",
"duplexify": "^3.5.0",
"inherits": "^2.0.3",
"ipv4-peers": "^1.1.1",
"k-bucket": "^3.2.1",
"protocol-buffers-encodings": "^1.1.0",
"readable-stream": "^2.1.5",
"sodium-universal": "^2.0.0",
"stream-collector": "^1.0.1",
"udp-request": "^1.3.0",
"xor-distance": "^1.0.0"
},
"devDependencies": {
"protocol-buffers": "^3.2.1",
"standard": "^8.6.0",
"tape": "^4.6.3"
"standard": "^11.0.1",
"tape": "^4.9.0"
},
"repository": {
"type": "git",

9
query-stream.js

@ -1,10 +1,9 @@
var stream = require('readable-stream')
var inherits = require('inherits')
var nodes = require('ipv4-peers').idLength(32)
var bufferEquals = require('buffer-equals')
var xor = require('xor-distance')
var BLANK = new Buffer([
var BLANK = Buffer.from([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
])
@ -227,14 +226,14 @@ QueryStream.prototype._send = function (node, force, useToken) {
}
QueryStream.prototype._addPending = function (node, ref) {
if (bufferEquals(node.id, this._dht.id)) return
if (node.id.equals(this._dht.id)) return
node.distance = xor(this.target, node.id)
node.referrer = ref
insertSorted(node, this._k, this._pending)
}
QueryStream.prototype._addClosest = function (res, peer) {
if (!res.id || !res.roundtripToken || bufferEquals(res.id, this._dht.id)) return
if (!res.id || !res.roundtripToken || res.id.equals(this._dht.id)) return
var prev = getNode(res.id, this._pending)
@ -265,7 +264,7 @@ function getNode (id, list) {
// technically this would be faster with binary search (against distance)
// but this list is always small, so meh
for (var i = 0; i < list.length; i++) {
if (bufferEquals(list[i].id, id)) return list[i]
if (list[i].id.equals(id)) return list[i]
}
return null

26
test.js

@ -1,6 +1,6 @@
var tape = require('tape')
var dht = require('./')
var crypto = require('crypto')
var blake2b = require('./blake2b')
tape('simple update', function (t) {
bootstrap(function (port, node) {
@ -9,7 +9,7 @@ tape('simple update', function (t) {
a.on('update:echo', function (data, callback) {
t.ok(data.roundtripToken, 'has roundtrip token')
t.same(data.value, new Buffer('Hello, World!'), 'expected data')
t.same(data.value, Buffer.from('Hello, World!'), 'expected data')
callback(null, data.value)
})
@ -17,7 +17,7 @@ tape('simple update', function (t) {
var data = {
command: 'echo',
target: a.id,
value: new Buffer('Hello, World!')
value: Buffer.from('Hello, World!')
}
b.update(data, function (err, responses) {
@ -27,7 +27,7 @@ tape('simple update', function (t) {
t.error(err, 'no errors')
t.same(responses.length, 1, 'one response')
t.same(responses[0].value, new Buffer('Hello, World!'), 'echoed data')
t.same(responses[0].value, Buffer.from('Hello, World!'), 'echoed data')
t.end()
})
})
@ -41,7 +41,7 @@ tape('simple query', function (t) {
a.on('query:hello', function (data, callback) {
t.same(data.value, null, 'expected data')
callback(null, new Buffer('world'))
callback(null, Buffer.from('world'))
})
a.ready(function () {
@ -57,7 +57,7 @@ tape('simple query', function (t) {
t.error(err, 'no errors')
t.same(responses.length, 1, 'one response')
t.same(responses[0].value, new Buffer('world'), 'responded')
t.same(responses[0].value, Buffer.from('world'), 'responded')
t.end()
})
})
@ -86,7 +86,7 @@ tape('targeted query', function (t) {
client.query({
command: 'echo',
value: new Buffer('hi'),
value: Buffer.from('hi'),
target: client.id
}, {
node: {
@ -101,7 +101,7 @@ tape('targeted query', function (t) {
t.error(err, 'no error')
t.same(responses.length, 1, 'one response')
t.same(responses[0].value, new Buffer('hi'), 'echoed')
t.same(responses[0].value, Buffer.from('hi'), 'echoed')
t.end()
})
})
@ -131,7 +131,7 @@ tape('targeted update', function (t) {
client.update({
command: 'echo',
value: new Buffer('hi'),
value: Buffer.from('hi'),
target: client.id
}, {
node: {
@ -146,7 +146,7 @@ tape('targeted update', function (t) {
t.error(err, 'no error')
t.same(responses.length, 1, 'one response')
t.same(responses[0].value, new Buffer('hi'), 'echoed')
t.same(responses[0].value, Buffer.from('hi'), 'echoed')
t.end()
})
})
@ -163,10 +163,10 @@ tape('swarm query', function (t) {
function done () {
t.pass('created swarm')
var key = crypto.createHash('sha256').update('hello').digest()
var key = blake2b(Buffer.from('hello'))
var me = dht({bootstrap: port})
me.update({command: 'kv', target: key, value: new Buffer('hello')}, function (err, responses) {
me.update({command: 'kv', target: key, value: Buffer.from('hello')}, function (err, responses) {
t.error(err, 'no error')
t.same(closest, 20, '20 closest nodes')
t.same(responses.length, 20, '20 responses')
@ -175,7 +175,7 @@ tape('swarm query', function (t) {
stream.on('data', function (data) {
if (data.value) {
t.same(data.value, new Buffer('hello'), 'echoed value')
t.same(data.value, Buffer.from('hello'), 'echoed value')
t.end()
swarm.forEach(function (node) {
node.destroy()

Loading…
Cancel
Save