diff --git a/data/dbs/file/db.js b/data/dbs/file/db.js
index d0df685..95f1fb7 100644
--- a/data/dbs/file/db.js
+++ b/data/dbs/file/db.js
@@ -87,6 +87,110 @@ definitions.push(
);
+definitions.push(
+ {
+ "name": "Toyota",
+ "model": {
+ "@events": {
+ "door_open": {
+ "type": "object",
+ "fields": {
+ "timestamp": {
+ "description": "The time of event",
+ "type": "numeric"
+ },
+ }
+ },
+ },
+ "@properties": {
+ "speed": {
+ "type": "object",
+ "fields": {
+ "unit": {
+ "description": "The unit identifier in KmH or MpH",
+ "type": "string"
+ },
+ "value": {
+ "description": "The speed value",
+ "type": "numeric"
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "fields": {
+ "latitude": {
+ "description": "The latitude part of the location",
+ "type": "string"
+ },
+ "longitude": {
+ "description": "The longitude part of the location",
+ "type": "numeric"
+ }
+ }
+ }
+ },
+ "@actions": {
+ "unlock": null,
+ "lock": null
+ }
+ }
+ }
+);
+
+
+definitions.push(
+ {
+ "name": "Ford",
+ "model": {
+ "@events": {
+ "door_open": {
+ "type": "object",
+ "fields": {
+ "timestamp": {
+ "description": "The time of event",
+ "type": "numeric"
+ },
+ }
+ },
+ },
+ "@properties": {
+ "speed": {
+ "type": "object",
+ "fields": {
+ "unit": {
+ "description": "The unit identifier in KmH or MpH",
+ "type": "string"
+ },
+ "value": {
+ "description": "The speed value",
+ "type": "numeric"
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "fields": {
+ "latitude": {
+ "description": "The latitude part of the location",
+ "type": "string"
+ },
+ "longitude": {
+ "description": "The longitude part of the location",
+ "type": "numeric"
+ }
+ }
+ }
+ },
+ "@actions": {
+ "unlock": null,
+ "lock": null
+ }
+ }
+ }
+);
+
+
exports.find_thing = function find_thing(name, callback) {
var thing = null;
for (i = 0; i < definitions.length; i++) {
diff --git a/examples/p2p_demo/config.js b/examples/p2p_demo/config.js
index c039b95..5ea78c7 100644
--- a/examples/p2p_demo/config.js
+++ b/examples/p2p_demo/config.js
@@ -19,8 +19,20 @@ var config = {
},
servers: {
p2p: {
- address: 'localhost',
- port: 31300
+ nodes: [
+ {
+ address: 'localhost',
+ port: 31300,
+ nick: "wotseed01",
+ seeds: []
+ },
+ {
+ address: 'localhost',
+ port: 31301,
+ nick: "wotseed02",
+ seeds: [{ address: 'localhost', port: 31300 }]
+ }
+ ]
}
},
// The application database configuration. The ./data/dbs directory includes the database implementations
diff --git a/examples/p2p_demo/demo.js b/examples/p2p_demo/demo.js
index b01fb03..d1f0ff8 100644
--- a/examples/p2p_demo/demo.js
+++ b/examples/p2p_demo/demo.js
@@ -1,201 +1,193 @@
// set this global config variable first
global.appconfig = require('./config');
-// define what things will be handled by this demo
-global.is_door12_defined = true;
-global.is_switch12_defined = true;
-
var events = require("events");
var logger = require('../../logger');
var db = require('../../data/db')();
var wot = require('../../framework');
-var eventh = require('../../libs/events/thingevents');
-//var simulator = require('./simulator');
+var uuid = require('uuid');
+var PeerNetwork = require('../../libs/transport/p2p/wotkad/peer_network');
+var simulator = require('./simulator');
+var config = global.appconfig;
+
+var peernet = new PeerNetwork();
var device = function (thing_name) {
- var self = this;
+ var self = this;
+ this.name = thing_name;
self.property_get = function (property, callback) {
- logger.debug("get property from CoAP device: " + property );
- var msg = {
- type: 'property_get',
- name: thing_name,
- property: property
- };
+ logger.debug("get property from the P2P network: " + property);
- adapter.send({ host: self.host, port: self.port }, msg, function (err, result) {
- if (err) {
- return callback(err);
- }
+ if (!this.node) {
+ return callback("peer node is not initialised");
+ }
- if (result && result.property && result.property == property && result.hasOwnProperty('value')) {
- callback(null, result.value);
- }
- else {
- callback("Invalid CoAP property_get response");
- }
- });
+ var key = thing_name + "/property/" + property;
+ this.node.get(key, callback);
}
self.setProperty = function (property, value) {
logger.debug("send patch to device: " + property + ", value " + value);
- var msg = {
- type: 'patch',
- name: thing_name,
- property: property,
- value: value
- };
+ var key = thing_name + "/patch/" + property;
- adapter.send({ host: self.host, port: self.port }, msg, function (err, result) {
- // TODO handles the result
- });
+ // TODO
}
self.action = function (action) {
logger.debug("invoke action " + action + " at device simulator");
- var msg = {
- type: 'action',
- name: thing_name,
- action: action
- };
+ var key = thing_name + "/action/" + action;
- adapter.send({ host: self.host, port: self.port }, msg, function (err, result) {
- // TODO handles the result
- });
+ // TODO
+ }
+
+ self.is_msg_fordevice = function (keymsg) {
+ var elements = keymsg.split("/");
+ if (elements&& elements[0] == this.name ) {
+ return {result: true, type: elements[1], value: elements[2] };
+ }
+
+ return false;
}
- // create the CoAP adapter
- self.init = function(callback) {
- db.find_adapter(thing_name, "coap", function (err, data) {
+ // create the P2P peer node
+ self.init = function ( model, address, port, callback) {
+ this.model = model;
+
+ var seedaddr = config.servers.p2p.nodes[0].address;
+ var seedport = config.servers.p2p.nodes[0].port;
+ options = {
+ address: address,
+ port: port,
+ nick: uuid.v4(),
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: [{ address: seedaddr, port: seedport }]
+ };
+ this.node = peernet.create_peer(options);
+
+ this.node.on('connect', function (err, value) {
if (err) {
- return callback(err);
+ return logger.error("peer connect error %j", err, {});
}
- //start the CoAP client/server
- if (!data || !data.device || !data.protocol || !data.host) {
- return callback("Invalid adapter configuration data");
- }
-
- self.host = data.host;
- self.port = data.port;
+ logger.debug("peer " + self.name + " %j connected to overlay network", value, {});
- adapter.init(data, function (err) {
- callback(err);
+ peernet.on('data', function (key) {
+ var keyres = self.is_msg_fordevice(key);
+ if (keyres && keyres.result == true) {
+ self.node.get(key, function (err, value) {
+ if (err) {
+ return logger.error("peer get error %j", err, {});
+ }
+
+ logger.debug(self.name + ' P2P update type: ' + keyres.type + ', ' + keyres.value + ' value is : ' + value);
+ });
+ }
});
-
+
});
+
+ callback();
}
self.unbind = function (callback) {
- adapter.unbind(function (err) {
- callback(err);
- });
+ // TODO remove the node from the overlay network
+ callback();
}
- return self;
-
+ return self;
};
//
// The implementations of the things
//
-var door_device = new device("door12");
-var switch_device = new device("switch12");
+var toyota_car = new device("Toyota");
+var ford_car = new device("Ford");
var things = [
{
"thing": function (callback) {
- db.find_thing("door12", callback);
+ db.find_thing("Toyota", callback);
},
"implementation": {
start: function (thing) {
- door_device.init(function (err) {
+ toyota_car.init(thing.model, '127.0.0.1', 65520, function (err) {
if (err) {
- return logger.error("CoAP door12 adapter initialisation error: " + err);
+ return logger.error("P2P thing Toyota initialisation error: " + err);
}
});
},
stop: function (thing) {
- door_device.unbind(function (err) {
+ toyota_car.unbind(function (err) {
if (err) {
- return logger.error("CoAP adapter unbind error: " + err);
+ return logger.error("P2P thing Toyota unbind error: " + err);
}
});
},
property_get: function (property, callback) {
- door_device.property_get(property, function (err, value) {
+ toyota_car.property_get(property, function (err, value) {
if (err) {
callback(err);
- return logger.error("CoAP adapter door12 " + property + " property_get error: " + err);
+ return logger.error("P2P thing Toyota " + property + " property_get error: " + err);
}
+ logger.debug('peer Toyota thing received key: ' + key + ' value: ' + value);
+
callback(null, value);
});
- },
- // must be the property set handler implemented here otherwise
- // the client is unable to set the property
- patch: function (thing, property, value) {
- door_device.setProperty(property, value);
- },
- unlock: function (thing) {
- logger.info('at implementation ' + thing.name + ' "unlock action invoked -> call the device');
- door_device.action('unlock');
- },
- lock: function (thing) {
- logger.info('at implementation ' + thing.name + ' "lock" action invoked -> call the device');
- door_device.action('lock');
}
}
},
{
"thing": function (callback) {
- db.find_thing("switch12", callback);
- },
+ db.find_thing("Ford", callback);
+ },
"implementation": {
start: function (thing) {
- switch_device.init(function (err) {
+ ford_car.init(thing.model, '127.0.0.1', 65521, function (err) {
if (err) {
- return logger.error("CoAP switch12 adapter initialisation error: " + err);
+ return logger.error("P2P thing Ford initialisation error: " + err);
}
});
},
- stop: function (thing) {
- switch_device.unbind(function (err) {
+ stop: function (thing) {
+ ford_car.unbind(function (err) {
if (err) {
- return logger.error("CoAP adapter unbind error: " + err);
+ return logger.error("P2P thing Ford unbind error: " + err);
}
});
},
property_get: function (property, callback) {
- switch_device.property_get(property, function (err, value) {
+ ford_car.property_get(property, function (err, value) {
if (err) {
callback(err);
- return logger.error("CoAP adapter switch12 " + property + " property_get error: " + err);
+ return logger.error("P2P thing Ford " + property + " property_get error: " + err);
}
+ logger.debug('peer Ford thing received key: ' + key + ' value: ' + value);
+
callback(null, value);
});
- },
- patch: function (thing, property, value) {
- switch_device.setProperty(property, value);
}
}
- }
+ }
];
// call the framework initialisation method and pass an array of things definitions to the framework
// for this demo the things are defined here
try {
- logger.debug("Calling framework init()");
- wot.init(things);
+ logger.debug("Initialising framework");
+ wot.transport_init();
+ wot.things_init(things);
+ // start the device device simulator
+ simulator.start();
}
catch (e) {
logger.error("Error in initialising framework " + e.message);
}
-
-// start the device P2P simulator
-//simulator.start();
diff --git a/examples/p2p_demo/kaddht_demo.js b/examples/p2p_demo/kaddht_demo.js
index 605c49b..10ca8f6 100644
--- a/examples/p2p_demo/kaddht_demo.js
+++ b/examples/p2p_demo/kaddht_demo.js
@@ -52,16 +52,6 @@ function onPut(err) {
return log.error("onPut error %j", err, {});
}
- //node1.get('door12/events/bell', function (err, value) {
- // if (err) {
- // return log.error("error %j", err);
- // }
- // log.debug('----------------------------------------------------');
- // log.debug('node1 received door12/events/bell value is : ' + value);
- // log.debug('----------------------------------------------------');
-
- //});
-
node2.get('door12/events/bell', function (err, value) {
if (err) {
return log.error("error %j", err, {});
@@ -72,14 +62,6 @@ function onPut(err) {
addnode();
- //if (!is_modified) {
- // // now modify the data
- // is_modified = true;
- // node2.put('door12/events/bell', 'beep2 from node2', onPut);
- //}
- //else {
- // //putloop();
- //}
});
}
diff --git a/examples/p2p_demo/peer_demo.js b/examples/p2p_demo/peer_demo.js
index f3e1b5f..d6d7597 100644
--- a/examples/p2p_demo/peer_demo.js
+++ b/examples/p2p_demo/peer_demo.js
@@ -1,51 +1,87 @@
var PeerNetwork = require('../../libs/transport/p2p/wotkad/peer_network');
var logger = require('../../logger');
+var peernet = new PeerNetwork();
-var peers = new PeerNetwork();
-
+// create the overlay network with node1
var options = {
+ address: '127.0.0.1',
+ port: 65529,
+ nick: 'seed1',
+ alg: {},
+ private_key: {},
+ public_key: {}
+};
+var seed1 = peernet.create_peer(options);
+
+options = {
address: '127.0.0.1',
port: 65530,
- nick: 'node1'
+ nick: 'seed2',
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: [{ address: '127.0.0.1', port: 65529 }]
};
-var peer1 = peers.create_peer(options);
+var seed2 = peernet.create_peer(options);
+// connect to the overlay network
options = {
address: '127.0.0.1',
port: 65531,
nick: 'node2',
- seeds: [{ address: '127.0.0.1', port: 65530 }],
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: [{ address: '127.0.0.1', port: 65529 }]
};
-var peer2 = peers.create_peer(options);
+var peer2 = peernet.create_peer(options);
options = {
address: '127.0.0.1',
port: 65532,
nick: 'node3',
- seeds: [{ address: '127.0.0.1', port: 65530 }],
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: [{ address: '127.0.0.1', port: 65530 }]
};
-var peer3 = peers.create_peer(options);
+var peer3 = peernet.create_peer(options);
-peer3.on('connect', function (err, value) {
+peer2.on('connect', function (err, value) {
if (err) {
- return logger.error("peer connect error %j", err, {});
+ return logger.error("peer connect error %j", err, {});
}
-
- logger.debug("peer %j connected to overlay network", value, {});
+
+ logger.debug("peer peer2 %j connected to overlay network", value, {});
peer2.put('door12/events/bell', 'beep1 from peer2', function (err) {
if (err) {
return logger.error("onPut error %j", err, {});
}
+
+ });
+
+});
+
+peer3.on('connect', function (err, value) {
+ if (err) {
+ return logger.error("peer connect error %j", err, {});
+ }
- peer3.get('door12/events/bell', function (err, value) {
- if (err) {
- return logger.error("error %j", err, {});
- }
- logger.debug('--------------------------------------------------------------------------------------------------------');
- logger.debug('peer3 received door12/events/bell value is : ' + value);
- logger.debug('--------------------------------------------------------------------------------------------------------');
- });
+ logger.debug("peer peer3 %j connected to overlay network", value, {});
+
+ peernet.on('data', function (key) {
+ if (key == 'door12/events/bell') {
+ peer3.get('door12/events/bell', function (err, value) {
+ if (err) {
+ return logger.error("peer get error %j", err, {});
+ }
+ logger.debug('--------------------------------------------------------------------------------------------------------');
+ logger.debug('peer3 received door12/events/bell value is : ' + value);
+ logger.debug('--------------------------------------------------------------------------------------------------------');
+ });
+ }
});
+
});
\ No newline at end of file
diff --git a/examples/p2p_demo/simulator.js b/examples/p2p_demo/simulator.js
new file mode 100644
index 0000000..f6c8ce2
--- /dev/null
+++ b/examples/p2p_demo/simulator.js
@@ -0,0 +1,123 @@
+var logger = require('../../logger');
+var PeerNetwork = require('../../libs/transport/p2p/wotkad/peer_network');
+var config = global.appconfig;
+
+var peernet = new PeerNetwork();
+
+var device_node = function (thing, address, port) {
+ var self = this;
+ this.name = thing.name;
+
+ logger.debug("starting P2P device simulator for " + this.name);
+
+
+
+ var seedaddr = config.servers.p2p.nodes[0].address;
+ var seedport = config.servers.p2p.nodes[0].port;
+ options = {
+ address: address,
+ port: port,
+ nick: this.name,
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: [{ address: seedaddr, port: seedport }]
+ };
+ this.node = peernet.create_peer(options);
+
+ this.put = function(prop, value) {
+ var key = thing.name + prop;
+ this.node.put(key, value, function (err) {
+ if (err) {
+ return logger.error("device_node put error %j", err, {});
+ }
+ });
+ }
+
+ return self;
+}
+
+var toyota_device = {};
+var toyota_prop_values = {};
+toyota_prop_values["speed"] = 0;
+toyota_prop_values["location"] = 0;
+
+var car1 = {
+ "name": "Toyota",
+ "model": {
+ "events": {
+
+ },
+ // for patch include the writable properties from the data/dbs/file/db.js file
+ "properties": {
+ "get": function (property) {
+ return toyota_prop_values[property];
+ },
+ "speed": function (value){
+ var setspeedval = function () {
+ var speed = 50;
+ speed += Math.floor(Math.random() * 15);
+
+ //send to the WoT P2P network
+ toyota_device.put("/property/speed", speed);
+
+ toyota_prop_values["speed"] = speed;
+ };
+ setInterval(setspeedval, 5000);
+ },
+ "location": function () {
+ },
+ },
+ "actions": {
+
+ }
+ }
+};
+
+
+var ford_device = {};
+var ford_prop_values = {};
+ford_prop_values["speed"] = 0;
+ford_prop_values["location"] = 0;
+
+var car2 = {
+ "name": "Ford",
+ "model": {
+ "events": {
+
+ },
+ // for patch include the writable properties from the data/dbs/file/db.js file
+ "properties": {
+ "get": function (property) {
+ return ford_prop_values[property];
+ },
+ "speed": function (value) {
+ var setspeedval = function () {
+ var speed = 70;
+ speed += Math.floor(Math.random() * 15);
+
+ //send to the WoT P2P network
+ ford_device.put("/property/speed", speed);
+
+ ford_prop_values["speed"] = speed;
+ };
+ setInterval(setspeedval, 6000);
+ },
+ "location": function () {
+ },
+ },
+ "actions": {
+
+ }
+ }
+};
+
+
+exports.start = function start() {
+ logger.debug('Start device simulator to communicate with WoT via a P2P network');
+ toyota_device = new device_node(car1, 'localhost', 60000);
+ car1.model.properties.speed();
+
+ ford_device = new device_node(car2, 'localhost', 60001);
+ car2.model.properties.speed();
+}
diff --git a/framework.js b/framework.js
index 3817236..583608f 100644
--- a/framework.js
+++ b/framework.js
@@ -13,4 +13,20 @@ exports.init = function init(things) {
logger.debug("WoT Framework is initialised");
-}
\ No newline at end of file
+}
+
+exports.things_init = function things_init(things) {
+ // call the thing handler to start handling the things
+ thing_handler.init(things);
+
+ logger.debug("WoT Framework things are initialised");
+}
+
+
+exports.transport_init = function transport_init() {
+ // start the servers
+ server_handler.init();
+
+ logger.debug("WoT Framework transport is initialised");
+
+}
diff --git a/libs/crypto/crypto_handler.js b/libs/crypto/crypto_handler.js
new file mode 100644
index 0000000..4ffddd1
--- /dev/null
+++ b/libs/crypto/crypto_handler.js
@@ -0,0 +1,21 @@
+
+function CryptoHandler(alg, initstr) {
+ if (!(this instanceof CryptoHandler)) {
+ return new CryptoHandler();
+ }
+
+ this.alg = alg;
+}
+
+CryptoHandler.prototype.sign = function () {
+ var self = this;
+
+}
+
+
+CryptoHandler.prototype.verify = function () {
+
+}
+
+
+module.exports = CryptoHandler;
\ No newline at end of file
diff --git a/libs/crypto/ecc/EccDsa.js b/libs/crypto/ecc/EccDsa.js
new file mode 100644
index 0000000..d4ac86c
--- /dev/null
+++ b/libs/crypto/ecc/EccDsa.js
@@ -0,0 +1,337 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+var crypto = require('crypto');
+var assert = require('assert');
+
+var ecurve = require('./ecurvelib/index');
+var ECPointFp = ecurve.ECPointFp;
+var BigInteger = require('bigi');
+
+module.exports = (function () {
+ var _ecparams = ecurve.getECParams('secp256k1');
+ var methods = {
+ hmacSHA256: hmacSHA256,
+ calcPubKeyRecoveryParam: calcPubKeyRecoveryParam, deterministicGenerateK: deterministicGenerateK,
+ recoverPubKey: recoverPubKey, sign: sign, verify: verify, verifyRaw: verifyRaw
+ }
+
+ function attachECParams(ecdsa, ecparams) {
+ Object.keys(methods).forEach(function (method) {
+ ecdsa[method] = methods[method].bind(null, ecparams);
+ })
+ }
+
+ function _ecdsa(curveName) {
+ if (!curveName)
+ var ecparams = ecurve.getECParams('secp256k1')
+ else
+ var ecparams = ecurve.getECParams(curveName)
+
+ var ecdsa = {}
+ //attach other non-ecparams functions
+ Object.keys(_ecdsa).forEach(function (k) {
+ ecdsa[k] = _ecdsa[k]
+ })
+
+ ecdsa.ecparams = ecparams
+ attachECParams(ecdsa, ecparams)
+
+ return ecdsa
+ }
+
+ //attach ecparams
+ _ecdsa.ecparams = _ecparams
+
+ //attach functions
+ _ecdsa.parseSig = parseSig
+ _ecdsa.parseSigCompact = parseSigCompact
+ _ecdsa.serializeSig = serializeSig
+ _ecdsa.serializeSigCompact = serializeSigCompact
+
+ attachECParams(_ecdsa, _ecparams)
+
+ return _ecdsa
+})();
+
+
+
+/**
+ * Calculate pubkey extraction parameter.
+ *
+ * When extracting a pubkey from a signature, we have to
+ * distinguish four different cases. Rather than putting this
+ * burden on the verifier, Bitcoin includes a 2-bit value with the
+ * signature.
+ *
+ * This function simply tries all four cases and returns the value
+ * that resulted in a successful pubkey recovery.
+ */
+function hmacSHA256(v, k) {
+ return crypto.createHmac('sha256', k).update(v).digest()
+}
+
+function calcPubKeyRecoveryParam(ecparams, e, signature, Q) {
+ for (var i = 0; i < 4; i++) {
+ var Qprime = recoverPubKey(ecparams, e, signature, i)
+
+ if (Qprime.equals(Q)) {
+ return i
+ }
+ }
+
+ throw new Error('Unable to find valid recovery factor')
+}
+
+function deterministicGenerateK(ecparams, hash, D) {
+ assert(Buffer.isBuffer(hash), 'Hash must be a Buffer, not ' + hash)
+ assert.equal(hash.length, 32, 'Hash must be 256 bit')
+ assert(BigInteger.isBigInteger(D, true), 'Private key must be a BigInteger')
+
+ var x = D.toBuffer(32);
+ var k = new Buffer(32);
+ var v = new Buffer(32);
+ k.fill(0);
+ v.fill(1);
+
+ k = hmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k);
+ v = hmacSHA256(v, k);
+
+ k = hmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k);
+ v = hmacSHA256(v, k);
+ v = hmacSHA256(v, k);
+
+ var n = ecparams.n;
+ var kB = BigInteger.fromBuffer(v).mod(n);
+ assert(kB.compareTo(BigInteger.ONE) > 0, 'Invalid k value');
+ assert(kB.compareTo(ecparams.n) < 0, 'Invalid k value');
+
+ return kB;
+}
+
+function parseSig(buffer) {
+ assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence')
+ assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
+
+ assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer')
+ var rLen = buffer.readUInt8(3)
+ var rB = buffer.slice(4, 4 + rLen)
+
+ var offset = 4 + rLen
+ assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)')
+ var sLen = buffer.readUInt8(1 + offset)
+ var sB = buffer.slice(2 + offset)
+ offset += 2 + sLen
+
+ assert.equal(offset, buffer.length, 'Invalid DER encoding')
+
+ return { r: BigInteger.fromDERInteger(rB), s: BigInteger.fromDERInteger(sB) }
+}
+
+function parseSigCompact(buffer) {
+ assert.equal(buffer.length, 65, 'Invalid signature length')
+ var i = buffer.readUInt8(0) - 27
+
+ // At most 3 bits
+ assert.equal(i, i & 7, 'Invalid signature parameter')
+ var compressed = !!(i & 4)
+
+ // Recovery param only
+ i = i & 3
+
+ var r = BigInteger.fromBuffer(buffer.slice(1, 33))
+ var s = BigInteger.fromBuffer(buffer.slice(33))
+
+ return {
+ signature: {
+ r: r,
+ s: s
+ },
+ i: i,
+ compressed: compressed
+ }
+}
+
+/**
+ * Recover a public key from a signature.
+ *
+ * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
+ * Key Recovery Operation".
+ *
+ * http://www.secg.org/download/aid-780/sec1-v2.pdf
+ */
+function recoverPubKey(ecparams, e, signature, i) {
+ assert.strictEqual(i & 3, i, 'The recovery param is more than two bits')
+
+ var r = signature.r
+ var s = signature.s
+
+ // A set LSB signifies that the y-coordinate is odd
+ // By reduction, the y-coordinate is even if it is clear
+ var isYEven = !(i & 1)
+
+ // The more significant bit specifies whether we should use the
+ // first or second candidate key.
+ var isSecondKey = i >> 1
+
+ var n = ecparams.n
+ var G = ecparams.g
+ var curve = ecparams.curve
+ var p = curve.q
+ var a = curve.a.toBigInteger()
+ var b = curve.b.toBigInteger()
+
+ // We precalculate (p + 1) / 4 where p is the field order
+ if (!curve.P_OVER_FOUR) {
+ curve.P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2)
+ }
+
+ // 1.1 Compute x
+ var x = isSecondKey ? r.add(n) : r
+
+ // 1.3 Convert x to point
+ var alpha = x.pow(3).add(a.multiply(x)).add(b).mod(p)
+ var beta = alpha.modPow(curve.P_OVER_FOUR, p)
+
+ // If beta is even, but y isn't, or vice versa, then convert it,
+ // otherwise we're done and y == beta.
+ var y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta
+
+ // 1.4 Check that nR isn't at infinity
+ var R = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+ R.validate()
+
+ // 1.5 Compute -e from e
+ var eNeg = e.negate().mod(n)
+
+ // 1.6 Compute Q = r^-1 (sR - eG)
+ // Q = r^-1 (sR + -eG)
+ var rInv = r.modInverse(n)
+
+ var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv)
+ Q.validate()
+
+ if (!verifyRaw(ecparams, e, signature, Q)) {
+ throw new Error("Pubkey recovery unsuccessful")
+ }
+
+ return Q
+}
+
+function serializeSig(signature) {
+ //var rBa = r.toByteArraySigned();
+ //var sBa = s.toByteArraySigned();
+ var rBa = signature.r.toDERInteger()
+ var sBa = signature.s.toDERInteger()
+
+
+ var sequence = [];
+ sequence.push(0x02); // INTEGER
+ sequence.push(rBa.length);
+ sequence = sequence.concat(rBa);
+
+ sequence.push(0x02); // INTEGER
+ sequence.push(sBa.length);
+ sequence = sequence.concat(sBa);
+
+ sequence.unshift(sequence.length);
+ sequence.unshift(0x30); // SEQUENCE
+
+ return sequence;
+}
+
+function serializeSigCompact(signature, i, compressed) {
+ if (compressed) {
+ i += 4
+ }
+
+ i += 27
+
+ var buffer = new Buffer(65)
+ buffer.writeUInt8(i, 0)
+
+ signature.r.toBuffer(32).copy(buffer, 1)
+ signature.s.toBuffer(32).copy(buffer, 33)
+
+ return buffer
+}
+
+function sign(ecparams, hash, privateKey) {
+ if (Buffer.isBuffer(privateKey))
+ var D = BigInteger.fromBuffer(privateKey)
+ else
+ var D = privateKey//big integer for legacy compatiblity
+
+ var k = deterministicGenerateK(ecparams, hash, D)
+
+ var n = ecparams.n
+ var G = ecparams.g
+ var Q = G.multiply(k)
+ var e = BigInteger.fromBuffer(hash)
+
+ var r = Q.getX().toBigInteger().mod(n)
+ assert.notEqual(r.signum(), 0, 'Invalid R value')
+
+ var s = k.modInverse(n).multiply(e.add(D.multiply(r))).mod(n)
+ assert.notEqual(s.signum(), 0, 'Invalid S value')
+
+ var N_OVER_TWO = n.shiftRight(1)
+
+ // enforce low S values, see bip62: 'low s values in signatures'
+ if (s.compareTo(N_OVER_TWO) > 0) {
+ s = n.subtract(s)
+ }
+
+ return { r: r, s: s }
+}
+
+function verify(ecparams, hash, signature, pubkey) {
+ assert(signature.r && signature.s, "Invalid signature.")
+
+ var Q;
+ if (Buffer.isBuffer(pubkey)) {
+ Q = ECPointFp.decodeFrom(ecparams.curve, pubkey);
+ } else {
+ throw new Error("Invalid format for pubkey value, must be Buffer");
+ }
+ var e = BigInteger.fromBuffer(hash);
+
+ return verifyRaw(ecparams, e, { r: signature.r, s: signature.s }, Q);
+}
+
+function verifyRaw(ecparams, e, signature, Q) {
+ var n = ecparams.n
+ var G = ecparams.g
+
+ var r = signature.r
+ var s = signature.s
+
+ if (r.signum() === 0 || r.compareTo(n) >= 0) return false
+ if (s.signum() === 0 || s.compareTo(n) >= 0) return false
+
+ var c = s.modInverse(n)
+
+ var u1 = e.multiply(c).mod(n)
+ var u2 = r.multiply(c).mod(n)
+
+ var point = G.multiplyTwo(u1, Q, u2)
+ var v = point.getX().toBigInteger().mod(n)
+
+ return v.equals(r)
+}
\ No newline at end of file
diff --git a/libs/crypto/ecc/EccKey.js b/libs/crypto/ecc/EccKey.js
new file mode 100644
index 0000000..3d84fda
--- /dev/null
+++ b/libs/crypto/ecc/EccKey.js
@@ -0,0 +1,161 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var crypto = require('crypto');
+var ecurve = require('ecurve');
+var ecparams = ecurve.getCurveByName('secp256k1');
+var BigInteger = require('bigi');
+var ks = require('./KeyString');
+var ecdsa = require('./EccDsa');
+
+function EccKey(bytes, compressed) {
+ if (!(this instanceof EccKey)) {
+ return new EccKey(bytes, compressed)
+ }
+
+ if (typeof compressed == 'boolean')
+ this._compressed = compressed
+ else
+ this._compressed = true
+
+ if (bytes)
+ this.privateKey = bytes
+}
+
+
+Object.defineProperty(EccKey.prototype, 'privateKey', {
+ enumerable: true, configurable: true,
+ get: function () {
+ return this.key
+ },
+ set: function (bytes) {
+ if (typeof bytes != 'string') {
+ throw new Error("The private key input must be a string");
+ }
+
+ var byteArr;
+ var hash = crypto.createHash('sha256').update(bytes).digest();
+ if (Buffer.isBuffer(hash)) {
+ this.key = hash;
+ byteArr = [].slice.call(hash)
+ }
+ else {
+ throw new Error('Error generating private key hash');
+ }
+
+ if (this.key.length != 32)
+ throw new Error("private key bytes must have a length of 32")
+
+ //_exportKey => privateKey + (0x01 if compressed)
+ if (this._compressed)
+ this._exportKey = Buffer.concat([ this.key, new Buffer([0x01]) ])
+ else
+ this._exportKey = Buffer.concat([ this.key ]) //clone key as opposed to passing a reference (relevant to Node.js only)
+
+ this.keyBigInteger = BigInteger.fromByteArrayUnsigned(byteArr)
+
+ //reset
+ this._publicPoint = null
+ this._pubKeyHash = null
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'privateExportKey', {
+ get: function () {
+ return this._exportKey
+ }
+})
+
+
+Object.defineProperty(EccKey.prototype, 'pubKeyHash', {
+ get: function () {
+ if (this._pubKeyHash) return this._pubKeyHash
+ this._pubKeyHash = crypto.createHash('rmd160').update(this.publicKey).digest()
+ return this._pubKeyHash
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'publicKey', {
+ get: function () {
+ return new Buffer(this.publicPoint.getEncoded(this.compressed))
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'publicPoint', {
+ get: function () {
+ if (!this._publicPoint) {
+ this._publicPoint = ecparams.G.multiply(this.keyBigInteger)
+ }
+ return this._publicPoint
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'compressed', {
+ get: function () {
+ return this._compressed
+ },
+ set: function (val) {
+ var c = !!val
+ if (c === this._compressed) return
+
+ //reset key stuff
+ var pk = this.privateKey
+ this._compressed = c
+ this.privateKey = pk
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'publicKeyStr', {
+ get: function () {
+ return this.publicKey.toString('hex')
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'pubKeyHashStr', {
+ get: function () {
+ return this.pubKeyHash.toString('hex')
+ }
+})
+
+Object.defineProperty(EccKey.prototype, 'pubKeyEncode', {
+ get: function () {
+ return ks.encode(this.publicKey);
+ }
+})
+
+
+EccKey.prototype.toString = function (format) {
+ return this.privateKey.toString('hex')
+}
+
+EccKey.prototype.sign = function sign(text, account) {
+ var buffer = new Buffer(text, "utf-8");
+ var hash = crypto.createHash('sha256').update(buffer).digest();
+ var signbuffer = ecdsa.sign(hash, this.privateKey);
+ var ser1 = ecdsa.serializeSig(signbuffer);
+ var ser2 = new Buffer(ser1);
+ var signatureb64 = ser2.toString('base64');
+ var hashstr = hash.toString('hex');
+ var encodedKey = this.pubKeyEncode;
+ return { hash: hashstr, signature: signatureb64, account: account, pkchecksum: encodedKey.checksum };
+}
+
+module.exports = EccKey;
+
diff --git a/libs/crypto/ecc/EccVerify.js b/libs/crypto/ecc/EccVerify.js
new file mode 100644
index 0000000..f8e5aa7
--- /dev/null
+++ b/libs/crypto/ecc/EccVerify.js
@@ -0,0 +1,70 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var ecdsa = require('./EccDsa');
+var ks = require('./KeyString');
+
+function EccVerify(base64Pk, checksum, hash, signature, pk_checksum) {
+ if (!base64Pk || !checksum) {
+ throw new Error("Invalid contract verify parameters");
+ return;
+ }
+ if (!hash) {
+ throw new Error("Invalid transaction hash buffer");
+ return;
+ }
+ if (!signature) {
+ throw new Error("Invalid transaction signature buffer");
+ return;
+ }
+ if (!pk_checksum) {
+ throw new Error("Invalid transaction public key checksum buffer");
+ return;
+ }
+
+ if (checksum != pk_checksum) {
+ throw new Error("Public key checksums do not match ");
+ return;
+ }
+
+ var msghash = new Buffer(hash, 'hex');
+
+ //var signBuffer = new Buffer(signature, 'hex');
+ var signBuffer = null;
+ try {
+ signBuffer = new Buffer(signature, 'base64');
+ }
+ catch (e) {
+ signBuffer = null;
+ }
+ if (!signBuffer) {
+ throw new Error("Invalid signature buffer.");
+ return;
+ }
+
+ var signature = ecdsa.parseSig(signBuffer);
+
+ var publickey = ks.decode(base64Pk, checksum);
+ var valid = ecdsa.verify(msghash, signature, publickey);
+ return valid;
+}
+
+module.exports = EccVerify;
+
diff --git a/libs/crypto/ecc/KeyString.js b/libs/crypto/ecc/KeyString.js
new file mode 100644
index 0000000..0220d42
--- /dev/null
+++ b/libs/crypto/ecc/KeyString.js
@@ -0,0 +1,75 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var crypto = require('crypto');
+var assert = require('assert');
+
+function encode(payload) {
+ if (!payload || !Buffer.isBuffer(payload)) {
+ throw new Error("Invalid KeyString encode paramater");
+ }
+ var chksum = sha256x2(payload).slice(0, 4);
+ var result = {
+ key: payload.toString('hex'),
+ checksum: chksum.toString('hex')
+ };
+ return result;
+}
+
+function decode(hexkey, checksum) {
+ if (!hexkey || !checksum || hexkey.constructor != String || checksum.constructor != String) {
+ throw new Error("Invalid KeyString decode paramater");
+ }
+
+ var buffer, newChecksum;
+ try {
+ buffer = new Buffer(hexkey, 'hex');
+ newChecksum = sha256x2(buffer).slice(0, 4)
+ }
+ catch (err) {
+ throw new Error('Encoding key failed. Error: ' + err);
+ }
+
+ if (checksum !== newChecksum.toString('hex'))
+ throw new Error('Invalid checksum')
+
+ return buffer;
+}
+
+function isValid(hexkey, checksum) {
+ try {
+ decode(hexkey, checksum)
+ } catch (e) {
+ return false
+ }
+ return true;
+}
+
+
+function sha256x2(buffer) {
+ var sha = crypto.createHash('sha256').update(buffer).digest()
+ return crypto.createHash('sha256').update(sha).digest()
+}
+
+module.exports = {
+ encode: encode,
+ decode: decode,
+ isValid: isValid
+}
\ No newline at end of file
diff --git a/libs/crypto/ecc/ecurvelib/curve.js b/libs/crypto/ecc/ecurvelib/curve.js
new file mode 100644
index 0000000..54977cf
--- /dev/null
+++ b/libs/crypto/ecc/ecurvelib/curve.js
@@ -0,0 +1,51 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var BigInteger = require('bigi')
+
+var ECFieldElementFp = require('./field-element')
+var ECPointFp = require('./point')
+
+module.exports = ECCurveFp
+
+function ECCurveFp(q,a,b) {
+ this._q = q;
+ this._a = this.fromBigInteger(a);
+ this._b = this.fromBigInteger(b);
+ this.infinity = new ECPointFp(this, null, null);
+};
+
+Object.defineProperty(ECCurveFp.prototype, 'q', {get: function() { return this._q}})
+Object.defineProperty(ECCurveFp.prototype, 'a', {get: function() { return this._a}})
+Object.defineProperty(ECCurveFp.prototype, 'b', {get: function() { return this._b}})
+
+ECCurveFp.prototype.equals = function(other) {
+ if(other == this) return true;
+ return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b));
+};
+
+ECCurveFp.prototype.getInfinity = function() {
+ return this.infinity;
+};
+
+ECCurveFp.prototype.fromBigInteger = function(x) {
+ return new ECFieldElementFp(this.q, x);
+};
+
diff --git a/libs/crypto/ecc/ecurvelib/field-element.js b/libs/crypto/ecc/ecurvelib/field-element.js
new file mode 100644
index 0000000..cf12a9d
--- /dev/null
+++ b/libs/crypto/ecc/ecurvelib/field-element.js
@@ -0,0 +1,65 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+
+module.exports = ECFieldElementFp
+
+function ECFieldElementFp(q,x) {
+ this.x = x;
+ // TODO if(x.compareTo(q) >= 0) error
+ this.q = q;
+};
+
+ECFieldElementFp.prototype.equals = function(other) {
+ if(other == this) return true;
+ return (this.q.equals(other.q) && this.x.equals(other.x));
+};
+
+ECFieldElementFp.prototype.toBigInteger = function() {
+ return this.x;
+};
+
+ECFieldElementFp.prototype.negate = function() {
+ return new ECFieldElementFp(this.q, this.x.negate().mod(this.q));
+};
+
+ECFieldElementFp.prototype.add = function(b) {
+ return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
+};
+
+ECFieldElementFp.prototype.subtract = function(b) {
+ return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
+};
+
+ECFieldElementFp.prototype.multiply = function(b) {
+ return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
+};
+
+ECFieldElementFp.prototype.square = function() {
+ return new ECFieldElementFp(this.q, this.x.square().mod(this.q));
+};
+
+ECFieldElementFp.prototype.divide = function feFpDivide(b) {
+ return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
+};
+
+ECFieldElementFp.prototype.getByteLength = function () {
+ return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
+};
\ No newline at end of file
diff --git a/libs/crypto/ecc/ecurvelib/index.js b/libs/crypto/ecc/ecurvelib/index.js
new file mode 100644
index 0000000..a6cd2ee
--- /dev/null
+++ b/libs/crypto/ecc/ecurvelib/index.js
@@ -0,0 +1,35 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var ECFieldElementFp = require('./field-element')
+var ECPointFp = require('./point')
+var ECCurveFp = require('./curve')
+var getECParams = require('./names')
+
+//for legacy compatibility, remove in the future
+ECCurveFp.ECPointFp = ECPointFp
+
+module.exports = {
+ ECCurveFp: ECCurveFp,
+ ECFieldElementFp: ECFieldElementFp,
+ ECPointFp: ECPointFp,
+ getECParams: getECParams
+}
+
diff --git a/libs/crypto/ecc/ecurvelib/names.js b/libs/crypto/ecc/ecurvelib/names.js
new file mode 100644
index 0000000..641208e
--- /dev/null
+++ b/libs/crypto/ecc/ecurvelib/names.js
@@ -0,0 +1,213 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var BigInteger = require('bigi');
+
+var ECCurveFp = require('./curve');
+var ECPointFp = require('./point')
+
+
+// Named EC curves
+
+// ----------------
+// X9ECParameters
+
+// constructor
+function X9ECParameters(curve,g,n,h) {
+ this._curve = curve;
+ this._g = g;
+ this._n = n;
+ this._h = h;
+}
+
+Object.defineProperty(X9ECParameters.prototype, 'curve', {get: function() { return this._curve }})
+Object.defineProperty(X9ECParameters.prototype, 'g', {get: function() { return this._g }})
+Object.defineProperty(X9ECParameters.prototype, 'n', {get: function() { return this._n }})
+Object.defineProperty(X9ECParameters.prototype, 'h', {get: function() { return this._h }})
+
+
+// ----------------
+// SECNamedCurves
+
+function fromHex(s) { return new BigInteger(s, 16); }
+
+var namedCurves = {
+ secp128r1: function() {
+ // p = 2^128 - 2^97 - 1
+ var p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ var a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
+ var b = fromHex("E87579C11079F43DD824993C2CEE5ED3");
+ //byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
+ var n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "161FF7528B899B2D0C28607CA52C5B86"
+ + "CF5AC8395BAFEB13C02DA292DDED7A83");*/
+
+ var x = BigInteger.fromHex("161FF7528B899B2D0C28607CA52C5B86")
+ var y = BigInteger.fromHex("CF5AC8395BAFEB13C02DA292DDED7A83")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp160k1: function() {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ var a = BigInteger.ZERO;
+ var b = fromHex("7");
+ //byte[] S = null;
+ var n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ + "938CF935318FDCED6BC28286531733C3F03C4FEE");*/
+
+ var x = BigInteger.fromHex("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB")
+ var y = BigInteger.fromHex("938CF935318FDCED6BC28286531733C3F03C4FEE")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp160r1: function() {
+ // p = 2^160 - 2^31 - 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
+ var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
+ var b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
+ //byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
+ var n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "4A96B5688EF573284664698968C38BB913CBFC82"
+ + "23A628553168947D59DCC912042351377AC5FB32");*/
+
+ var x = BigInteger.fromHex("4A96B5688EF573284664698968C38BB913CBFC82")
+ var y = BigInteger.fromHex("23A628553168947D59DCC912042351377AC5FB32")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp192k1: function() {
+ // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
+ var a = BigInteger.ZERO;
+ var b = fromHex("3");
+ //byte[] S = null;
+ var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D");*/
+
+ var x = BigInteger.fromHex("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D")
+ var y = BigInteger.fromHex("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp192r1: function() {
+ // p = 2^192 - 2^64 - 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
+ var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
+ var b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
+ //byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+
+ var x = BigInteger.fromHex("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")
+ var y = BigInteger.fromHex("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp224r1: function() {
+ // p = 2^224 - 2^96 + 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
+ var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
+ var b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
+ //byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34");*/
+
+ var x = BigInteger.fromHex("B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")
+ var y = BigInteger.fromHex("BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp256k1: function() {
+ // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
+ var a = BigInteger.ZERO;
+ var b = fromHex("7");
+ //byte[] S = null;
+ var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");*/
+
+ var x = BigInteger.fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
+ var y = BigInteger.fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+ return new X9ECParameters(curve, G, n, h);
+ },
+
+ secp256r1: function() {
+ // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+ var p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
+ var a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
+ var b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
+ //byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ var n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+ var h = BigInteger.ONE;
+ var curve = new ECCurveFp(p, a, b);
+ /*var G = curve.decodePointHex("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");*/
+
+ var x = BigInteger.fromHex("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")
+ var y = BigInteger.fromHex("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")
+ var G = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+
+ return new X9ECParameters(curve, G, n, h);
+ }
+}
+
+module.exports = function getSECCurveByName(name) {
+ return (typeof namedCurves[name] == 'function')? namedCurves[name]() : null;
+}
diff --git a/libs/crypto/ecc/ecurvelib/point.js b/libs/crypto/ecc/ecurvelib/point.js
new file mode 100644
index 0000000..893fe1f
--- /dev/null
+++ b/libs/crypto/ecc/ecurvelib/point.js
@@ -0,0 +1,334 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+var assert = require('assert')
+
+var BigInteger = require('bigi')
+
+module.exports = ECPointFp
+
+
+function ECPointFp(curve,x,y,z) {
+ this.curve = curve;
+ this.x = x;
+ this.y = y;
+ // Projective coordinates: either zinv == null or z * zinv == 1
+ // z and zinv are just BigIntegers, not fieldElements
+ if(z == null) {
+ this.z = BigInteger.ONE;
+ }
+ else {
+ this.z = z;
+ }
+
+ this.zinv = null;
+ this.compressed = true
+};
+
+ECPointFp.prototype.getX = function() {
+ if(this.zinv == null) {
+ this.zinv = this.z.modInverse(this.curve.q);
+ }
+ return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+};
+
+ECPointFp.prototype.getY = function() {
+ if(this.zinv == null) {
+ this.zinv = this.z.modInverse(this.curve.q);
+ }
+ return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+};
+
+ECPointFp.prototype.equals = function(other) {
+ if(other == this) return true;
+ if(this.isInfinity()) return other.isInfinity();
+ if(other.isInfinity()) return this.isInfinity();
+ var u, v;
+ // u = Y2 * Z1 - Y1 * Z2
+ u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
+ if(!u.equals(BigInteger.ZERO)) return false;
+ // v = X2 * Z1 - X1 * Z2
+ v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
+ return v.equals(BigInteger.ZERO);
+};
+
+ECPointFp.prototype.isInfinity = function() {
+ if((this.x == null) && (this.y == null)) return true;
+ return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
+};
+
+ECPointFp.prototype.negate = function() {
+ return new ECPointFp(this.curve, this.x, this.y.negate(), this.z);
+};
+
+ECPointFp.prototype.add = function(b) {
+ if(this.isInfinity()) return b;
+ if(b.isInfinity()) return this;
+
+ // u = Y2 * Z1 - Y1 * Z2
+ var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q);
+ // v = X2 * Z1 - X1 * Z2
+ var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q);
+
+ if(BigInteger.ZERO.equals(v)) {
+ if(BigInteger.ZERO.equals(u)) {
+ return this.twice(); // this == b, so double
+ }
+ return this.curve.getInfinity(); // this = -b, so infinity
+ }
+
+ var THREE = new BigInteger("3");
+ var x1 = this.x.toBigInteger();
+ var y1 = this.y.toBigInteger();
+ var x2 = b.x.toBigInteger();
+ var y2 = b.y.toBigInteger();
+
+ var v2 = v.square();
+ var v3 = v2.multiply(v);
+ var x1v2 = x1.multiply(v2);
+ var zu2 = u.square().multiply(this.z);
+
+ // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
+ var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q);
+ // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
+ var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q);
+ // z3 = v^3 * z1 * z2
+ var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q);
+
+ return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+};
+
+ECPointFp.prototype.twice = function() {
+ if(this.isInfinity()) return this;
+ if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity();
+
+ // TODO: optimized handling of constants
+ var THREE = new BigInteger("3");
+ var x1 = this.x.toBigInteger();
+ var y1 = this.y.toBigInteger();
+
+ var y1z1 = y1.multiply(this.z);
+ var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q);
+ var a = this.curve.a.toBigInteger();
+
+ // w = 3 * x1^2 + a * z1^2
+ var w = x1.square().multiply(THREE);
+ if(!BigInteger.ZERO.equals(a)) {
+ w = w.add(this.z.square().multiply(a));
+ }
+ w = w.mod(this.curve.q);
+ // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
+ var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q);
+ // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
+ var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q);
+ // z3 = 8 * (y1 * z1)^3
+ var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q);
+
+ return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+};
+
+// Simple NAF (Non-Adjacent Form) multiplication algorithm
+// TODO: modularize the multiplication algorithm
+ECPointFp.prototype.multiply = function(k) {
+ if(this.isInfinity()) return this;
+ if(k.signum() == 0) return this.curve.getInfinity();
+
+ var e = k;
+ var h = e.multiply(new BigInteger("3"));
+
+ var neg = this.negate();
+ var R = this;
+
+ var i;
+ for(i = h.bitLength() - 2; i > 0; --i) {
+ R = R.twice();
+
+ var hBit = h.testBit(i);
+ var eBit = e.testBit(i);
+
+ if (hBit != eBit) {
+ R = R.add(hBit ? this : neg);
+ }
+ }
+
+ return R;
+};
+
+// Compute this*j + x*k (simultaneous multiplication)
+ECPointFp.prototype.multiplyTwo = function(j,x,k) {
+ var i;
+ if(j.bitLength() > k.bitLength()) {
+ i = j.bitLength() - 1;
+ } else {
+ i = k.bitLength() - 1;
+ }
+
+ var R = this.curve.getInfinity();
+ var both = this.add(x);
+ while(i >= 0) {
+ R = R.twice();
+ if(j.testBit(i)) {
+ if(k.testBit(i)) {
+ R = R.add(both);
+ } else {
+ R = R.add(this);
+ }
+ } else {
+ if(k.testBit(i)) {
+ R = R.add(x);
+ }
+ }
+ --i;
+ }
+
+ return R;
+};
+
+ECPointFp.prototype.getEncoded = function(doCompress) {
+ if (this.isInfinity()) return [0]; // Infinity point encoded is simply '00'
+ var x = this.getX().toBigInteger();
+ var y = this.getY().toBigInteger();
+
+ var compressed = this.compressed
+ if (typeof doCompress == 'boolean')
+ compressed = doCompress
+
+ // Determine size of q in bytes
+ var byteLength = Math.floor((this.curve.q.bitLength() + 7) / 8);
+
+ // Get value as a 32-byte Buffer
+ // Fixed length based on a patch by bitaddress.org and Casascius
+ var enc = [].slice.call(x.toBuffer(byteLength))
+
+ if (compressed) {
+ if (y.isEven()) {
+ // Compressed even pubkey
+ // M = 02 || X
+ enc.unshift(0x02);
+ } else {
+ // Compressed uneven pubkey
+ // M = 03 || X
+ enc.unshift(0x03);
+ }
+ } else {
+ // Uncompressed pubkey
+ // M = 04 || X || Y
+ enc.unshift(0x04);
+ enc = enc.concat([].slice.call(y.toBuffer(byteLength)))
+ }
+ return new Buffer(enc);
+};
+
+ECPointFp.decodeFrom = function(curve, buffer) {
+ var type = buffer.readUInt8(0);
+ var compressed = (type !== 4)
+ var x = BigInteger.fromBuffer(buffer.slice(1, 33))
+ var y = null
+
+ if (compressed) {
+ assert.equal(buffer.length, 33, 'Invalid sequence length')
+ assert(type === 0x02 || type === 0x03, 'Invalid sequence tag')
+
+ var isYEven = (type === 0x02)
+ var a = curve.a.toBigInteger()
+ var b = curve.b.toBigInteger()
+ var p = curve.q
+
+ // We precalculate (p + 1) / 4 where p is the field order
+ if (!curve.P_OVER_FOUR) {
+ curve.P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2)
+ }
+
+ // Convert x to point
+ var alpha = x.pow(3).add(a.multiply(x)).add(b).mod(p)
+ var beta = alpha.modPow(curve.P_OVER_FOUR, p)
+
+ // If beta is even, but y isn't, or vice versa, then convert it,
+ // otherwise we're done and y == beta.
+ y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta
+
+ } else {
+ assert.equal(buffer.length, 65, 'Invalid sequence length')
+
+ y = BigInteger.fromBuffer(buffer.slice(33))
+ }
+
+ var pt = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
+ pt.compressed = compressed
+ return pt
+};
+
+ECPointFp.prototype.isOnCurve = function () {
+ if (this.isInfinity()) return true;
+ var x = this.getX().toBigInteger();
+ var y = this.getY().toBigInteger();
+ var a = this.curve.a.toBigInteger();
+ var b = this.curve.b.toBigInteger();
+ var n = this.curve.q;
+ var lhs = y.multiply(y).mod(n);
+ var rhs = x.multiply(x).multiply(x)
+ .add(a.multiply(x)).add(b).mod(n);
+ return lhs.equals(rhs);
+};
+
+ECPointFp.prototype.toString = function () {
+ if (this.isInfinity()) return '(INFINITY)';
+ return '('+this.getX().toBigInteger().toString()+','+
+ this.getY().toBigInteger().toString()+')';
+};
+
+/**
+ * Validate an elliptic curve point.
+ *
+ * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
+ */
+ECPointFp.prototype.validate = function () {
+ var n = this.curve.q;
+
+ // Check Q != O
+ if (this.isInfinity()) {
+ throw new Error("Point is at infinity.");
+ }
+
+ // Check coordinate bounds
+ var x = this.getX().toBigInteger();
+ var y = this.getY().toBigInteger();
+ if (x.compareTo(BigInteger.ONE) < 0 ||
+ x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
+ throw new Error('x coordinate out of bounds');
+ }
+ if (y.compareTo(BigInteger.ONE) < 0 ||
+ y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
+ throw new Error('y coordinate out of bounds');
+ }
+
+ // Check y^2 = x^3 + ax + b (mod n)
+ if (!this.isOnCurve()) {
+ throw new Error("Point is not on the curve.");
+ }
+
+ // Check nQ = 0 (Q is a scalar multiple of G)
+ if (this.multiply(n).isInfinity()) {
+ // TODO: This check doesn't work - fix.
+ throw new Error("Point is not a scalar multiple of G.");
+ }
+
+ return true;
+};
\ No newline at end of file
diff --git a/libs/crypto/ecc/readme.md b/libs/crypto/ecc/readme.md
new file mode 100644
index 0000000..90448ea
--- /dev/null
+++ b/libs/crypto/ecc/readme.md
@@ -0,0 +1,4 @@
+# WoT ECC crypto implementation.
+
+Based on source files from https://github.com/cryptocoinjs
+
diff --git a/libs/message/jose/jwt.js b/libs/message/jose/jwt.js
new file mode 100644
index 0000000..e851ebf
--- /dev/null
+++ b/libs/message/jose/jwt.js
@@ -0,0 +1,181 @@
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+https://github.com/hokaccha/node-jwt-simple/blob/master/lib/jwt.js
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+
+
+var crypto = require('crypto');
+
+
+/**
+ * support algorithm mapping
+ */
+var algorithmMap = {
+ ES256: 'ES256',
+ ES384: 'ES384',
+ ES512: 'ES512'
+};
+
+
+/**
+ * expose object
+ */
+var jwt = module.exports;
+
+
+/**
+ * version
+ */
+jwt.version = '0.2.0';
+
+/**
+ * Decode jwt
+ *
+ * @param {Object} token
+ * @param {String} key
+ * @param {Boolean} noVerify
+ * @param {String} algorithm
+ * @return {Object} payload
+ * @api public
+ */
+jwt.decode = function jwt_decode(token, key, noVerify, algorithm) {
+ // check token
+ if (!token) {
+ throw new Error('No token supplied');
+ }
+ // check segments
+ var segments = token.split('.');
+ if (segments.length !== 3) {
+ throw new Error('Not enough or too many segments');
+ }
+
+ // All segment should be base64
+ var headerSeg = segments[0];
+ var payloadSeg = segments[1];
+ var signatureSeg = segments[2];
+
+ // base64 decode and parse JSON
+ var header = JSON.parse(base64urlDecode(headerSeg));
+ var payload = JSON.parse(base64urlDecode(payloadSeg));
+
+ if (!noVerify) {
+ var signingMethod = algorithmMap[algorithm || header.alg];
+ if (!signingMethod ) {
+ throw new Error('Algorithm not supported');
+ }
+
+ // verify signature. `sign` will return base64 string.
+ var signingInput = [headerSeg, payloadSeg].join('.');
+ if (!verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
+ throw new Error('Signature verification failed');
+ }
+ }
+
+ return payload;
+};
+
+
+/**
+ * Encode jwt
+ *
+ * @param {Object} payload
+ * @param {String} key
+ * @param {String} algorithm
+ * @return {String} token
+ * @api public
+ */
+jwt.encode = function jwt_encode(payload, key, algorithm) {
+ // Check key
+ if (!key) {
+ throw new Error('Require key');
+ }
+
+ // Check algorithm, default is HS256
+ if (!algorithm) {
+ algorithm = 'HS256';
+ }
+
+ var signingMethod = algorithmMap[algorithm];
+ if (!signingMethod ) {
+ throw new Error('Algorithm not supported');
+ }
+
+ // header, typ is fixed value.
+ var header = { typ: 'JWT', alg: algorithm };
+
+ // create segments, all segments should be base64 string
+ var segments = [];
+ segments.push(base64urlEncode(JSON.stringify(header)));
+ segments.push(base64urlEncode(JSON.stringify(payload)));
+ segments.push(sign(segments.join('.'), key, signingMethod, signingType));
+
+ return segments.join('.');
+};
+
+
+/**
+ * private util functions
+ */
+
+function verify(input, key, method, type, signature) {
+ if (type === "hmac") {
+ return (signature === sign(input, key, method, type));
+ }
+ else if (type == "sign") {
+ return crypto.createVerify(method)
+ .update(input)
+ .verify(key, base64urlUnescape(signature), 'base64');
+ }
+ else {
+ throw new Error('Algorithm type not recognized');
+ }
+}
+
+function sign(input, key, method, type) {
+ var base64str;
+ if (type === "hmac") {
+ base64str = crypto.createHmac(method, key).update(input).digest('base64');
+ }
+ else if (type == "sign") {
+ base64str = crypto.createSign(method).update(input).sign(key, 'base64');
+ }
+ else {
+ throw new Error('Algorithm type not recognized');
+ }
+
+ return base64urlEscape(base64str);
+}
+
+function base64urlDecode(str) {
+ return new Buffer(base64urlUnescape(str), 'base64').toString();
+}
+
+function base64urlUnescape(str) {
+ str += new Array(5 - str.length % 4).join('=');
+ return str.replace(/\-/g, '+').replace(/_/g, '/');
+}
+
+function base64urlEncode(str) {
+ return base64urlEscape(new Buffer(str).toString('base64'));
+}
+
+function base64urlEscape(str) {
+ return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
+}
\ No newline at end of file
diff --git a/libs/message/message.js b/libs/message/message.js
index 5f28270..83ea39b 100644
--- a/libs/message/message.js
+++ b/libs/message/message.js
@@ -1 +1,46 @@
-
\ No newline at end of file
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+var assert = require('assert');
+var crypto = require('crypto');
+
+
+function WoTMessage(private_key, payload, options) {
+ if (!(this instanceof WoTMessage)) {
+ return new WoTMessage(private_key, payload, options);
+ }
+
+ if (!options || !options.alg) {
+ // default algorithm is ECC
+ options.alg = 'ECC';
+ }
+
+ // currently only ECC is supported
+ assert(options.alg == "ECC", "In this version only elliptic curve cryptography algorithms supported");
+
+ // TODO create a json web token
+ return payload;
+}
+
+WoTMessage.prototype.verify = function (public_key, message) {
+
+ return true;
+}
+
+module.exports = WoTMessage;
diff --git a/libs/transport/p2p/wotkad/kaddht.js b/libs/transport/p2p/wotkad/kaddht.js
index 552d294..ce1da68 100644
--- a/libs/transport/p2p/wotkad/kaddht.js
+++ b/libs/transport/p2p/wotkad/kaddht.js
@@ -1,5 +1,20 @@
-/**
-* @module kad
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -15,25 +30,26 @@ var Node = require('./lib/node');
* @param {function} onConnect
*/
module.exports = function createNode(options, onConnect) {
- if (options.seeds) {
- assert(Array.isArray(options.seeds), 'Invalid `options.seeds` supplied');
- } else {
- options.seeds = [];
- }
+ if (options.seeds) {
+ assert(Array.isArray(options.seeds), 'Invalid `options.seeds` supplied');
+ }
+ else {
+ options.seeds = [];
+ }
- for (var i = 0; i < options.seeds.length; i++) {
- var seed = options.seeds[i];
- }
+ for (var i = 0; i < options.seeds.length; i++) {
+ var seed = options.seeds[i];
+ }
- var node = new Node(options);
+ var node = new Node(options);
- async.eachSeries(options.seeds, connectToSeed, onConnect);
+ async.eachSeries(options.seeds, connectToSeed, onConnect);
- function connectToSeed(seed, done) {
- node.connect(seed, done);
- }
+ function connectToSeed(seed, done) {
+ node.connect(seed, done);
+ }
- return node;
+ return node;
};
module.exports.Bucket = require('./lib/bucket');
diff --git a/libs/transport/p2p/wotkad/lib/bucket.js b/libs/transport/p2p/wotkad/lib/bucket.js
index 746e35f..401b100 100644
--- a/libs/transport/p2p/wotkad/lib/bucket.js
+++ b/libs/transport/p2p/wotkad/lib/bucket.js
@@ -1,7 +1,23 @@
-/**
-* @module kad/bucket
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
+
'use strict';
var _ = require('lodash');
@@ -55,17 +71,17 @@ Bucket.prototype.getContact = function(index) {
* @param {object} contact
*/
Bucket.prototype.addContact = function(contact) {
- assert(contact instanceof Contact, 'Invalid contact supplied');
+ assert(contact instanceof Contact, 'Invalid contact supplied');
- if (!this.hasContact(contact.nodeID)) {
- var index = _.sortedIndex(this._contacts, contact, function(contact) {
- return contact.lastSeen;
- });
+ if (!this.hasContact(contact.nodeID)) {
+ var index = _.sortedIndex(this._contacts, contact, function(contact) {
+ return contact.lastSeen;
+ });
- this._contacts.splice(index, 0, contact);
- }
+ this._contacts.splice(index, 0, contact);
+ }
- return this;
+ return this;
};
/**
@@ -104,15 +120,15 @@ Bucket.prototype.hasContact = function(nodeID) {
* @param {object} contact
*/
Bucket.prototype.indexOf = function(contact) {
- assert(contact instanceof Contact, 'Invalid contact supplied');
+ assert(contact instanceof Contact, 'Invalid contact supplied');
- for (var i = 0; i < this.getSize(); i++) {
- if (this.getContact(i).nodeID === contact.nodeID) {
- return i;
+ for (var i = 0; i < this.getSize(); i++) {
+ if (this.getContact(i).nodeID === contact.nodeID) {
+ return i;
+ }
}
- }
- return -1;
+ return -1;
};
module.exports = Bucket;
diff --git a/libs/transport/p2p/wotkad/lib/constants.js b/libs/transport/p2p/wotkad/lib/constants.js
index 0758990..9774693 100644
--- a/libs/transport/p2p/wotkad/lib/constants.js
+++ b/libs/transport/p2p/wotkad/lib/constants.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/constants
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
diff --git a/libs/transport/p2p/wotkad/lib/contact.js b/libs/transport/p2p/wotkad/lib/contact.js
index 854fcc2..f6ed02d 100644
--- a/libs/transport/p2p/wotkad/lib/contact.js
+++ b/libs/transport/p2p/wotkad/lib/contact.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/contact
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -14,18 +29,21 @@ var utils = require('./utils');
*/
function Contact(options) {
- assert(this instanceof Contact, 'Invalid instance was supplied');
- assert(options instanceof Object, 'Invalid options were supplied');
+ assert(this instanceof Contact, 'Invalid instance was supplied');
+ assert(options instanceof Object, 'Invalid options were supplied');
- Object.defineProperty(this, 'nodeID', {
- value: options.nodeID || this._createNodeID(),
- configurable: false,
- enumerable: true
- });
+ Object.defineProperty(
+ this,
+ 'nodeID', {
+ value: options.nodeID || this._createNodeID(),
+ configurable: false,
+ enumerable: true
+ }
+ );
- assert(utils.isValidKey(this.nodeID), 'Invalid nodeID was supplied');
+ assert(utils.isValidKey(this.nodeID), 'Invalid nodeID was supplied');
- this.seen();
+ this.seen();
}
/**
@@ -33,7 +51,7 @@ function Contact(options) {
* #seen
*/
Contact.prototype.seen = function() {
- this.lastSeen = Date.now();
+ this.lastSeen = Date.now();
};
/* istanbul ignore next */
@@ -42,7 +60,7 @@ Contact.prototype.seen = function() {
* #_createNodeID
*/
Contact.prototype._createNodeID = function() {
- throw new Error('Method not implemented');
+ throw new Error('Method not implemented');
};
module.exports = Contact;
diff --git a/libs/transport/p2p/wotkad/lib/item.js b/libs/transport/p2p/wotkad/lib/item.js
index 1639c7e..110b2b2 100644
--- a/libs/transport/p2p/wotkad/lib/item.js
+++ b/libs/transport/p2p/wotkad/lib/item.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/item
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -7,6 +22,7 @@
var assert = require('assert');
var constants = require('./constants');
var utils = require('./utils');
+var crypto = require('crypto');
/**
* Represents an item to store
@@ -17,23 +33,29 @@ var utils = require('./utils');
* @param {number} timestamp - optional
*/
function Item(key, value, publisher, timestamp) {
- if (!(this instanceof Item)) {
- return new Item(key, value, publisher, timestamp);
- }
-
- assert.ok(typeof key === 'string', 'Invalid key supplied');
- assert.ok(value, 'Invalid value supplied');
- assert(utils.isValidKey(publisher), 'Invalid publisher nodeID supplied');
-
- if (timestamp) {
- assert(typeof timestamp === 'number', 'Invalid timestamp supplied');
- assert(Date.now() >= timestamp, 'Timestamp cannot be in the future');
- }
-
- this.key = key;
- this.value = value;
- this.publisher = publisher;
- this.timestamp = timestamp || Date.now();
+ if (!(this instanceof Item)) {
+ return new Item(key, value, publisher, timestamp);
+ }
+
+ assert.ok(typeof key === 'string', 'Invalid key supplied');
+ assert.ok(value, 'Invalid value supplied');
+ assert(utils.isValidKey(publisher), 'Invalid publisher nodeID supplied');
+
+ if (timestamp) {
+ assert(typeof timestamp === 'number', 'Invalid timestamp supplied');
+ assert(Date.now() >= timestamp, 'Timestamp cannot be in the future');
+ }
+
+ var obj = [key, value];
+ var str = JSON.stringify(obj);
+ var buffer = new Buffer(str);
+ var hashval = crypto.createHash('sha1').update(buffer).digest();
+ this.hash = hashval.toString('hex');
+
+ this.key = key;
+ this.value = value;
+ this.publisher = publisher;
+ this.timestamp = timestamp || Date.now();
}
module.exports = Item;
diff --git a/libs/transport/p2p/wotkad/lib/message.js b/libs/transport/p2p/wotkad/lib/message.js
index 19c4fb7..27f819a 100644
--- a/libs/transport/p2p/wotkad/lib/message.js
+++ b/libs/transport/p2p/wotkad/lib/message.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/message
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -17,15 +32,15 @@ var Contact = require('./contact');
* @param {object} fromContact
*/
function Message(type, params, fromContact) {
- if (!(this instanceof Message)) {
- return new Message(type, params, fromContact);
- }
+ if (!(this instanceof Message)) {
+ return new Message(type, params, fromContact);
+ }
- assert(constants.MESSAGE_TYPES.indexOf(type) !== -1, 'Invalid message type');
- assert(fromContact instanceof Contact, 'Invalid contact supplied');
+ assert(constants.MESSAGE_TYPES.indexOf(type) !== -1, 'Invalid message type');
+ assert(fromContact instanceof Contact, 'Invalid contact supplied');
- this.type = type;
- this.params = merge(params, fromContact);
+ this.type = type;
+ this.params = merge(params, fromContact);
}
/**
@@ -33,7 +48,7 @@ function Message(type, params, fromContact) {
* #serialize
*/
Message.prototype.serialize = function() {
- return new Buffer(JSON.stringify(this), 'utf8');
+ return new Buffer(JSON.stringify(this), 'utf8');
};
module.exports = Message;
diff --git a/libs/transport/p2p/wotkad/lib/node.js b/libs/transport/p2p/wotkad/lib/node.js
index efad9dd..00d898d 100644
--- a/libs/transport/p2p/wotkad/lib/node.js
+++ b/libs/transport/p2p/wotkad/lib/node.js
@@ -1,5 +1,20 @@
-/**
-* @module kademlia/node
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -81,9 +96,8 @@ Node.prototype.connect = function(options, callback) {
async.waterfall(
[
this._updateContact.bind(this, seed),
- this._findNode.bind(
- this, this._self.nodeID),
- this._refreshBucketsBeyondClosest.bind(this)
+ this._findNode.bind(this, this._self.nodeID),
+ this._refreshBucketsBeyondClosest.bind(this)
],
function (err) {
if (err) {
@@ -150,12 +164,18 @@ Node.prototype._putValidatedKeyValue = function(key, value, callback) {
node._log.error('failed to find nodes - reason: %s', err.message);
return callback(err);
}
+
+ //for (var i = 0; i < contacts.length; i++) {
+ // if (!(contacts[i] instanceof Contact)) {
+ // throw new Error('Invalid contact');
+ // }
+ //}
if (contacts.length === 0) {
node._log.error('no contacts are available');
contacts = node._getNearestContacts(key, constants.K, node._self.nodeID);
}
-
+
//node._log.debug('found %d contacts for STORE operation', contacts.length);
async.each(contacts, function (contact, done) {
@@ -226,44 +246,47 @@ Node.prototype._startReplicationInterval = function() {
* #_replicate
*/
Node.prototype._replicate = function() {
- var self = this;
- var stream = this._storage.createReadStream();
-
- this._log.info('starting local database replication');
+ var self = this;
+ var stream = this._storage.createReadStream();
- stream.on('data', function(data) {
- if (typeof data.value === 'string') {
- try {
- data.value = JSON.parse(data.value);
- } catch(err) {
- return self._log.error('failed to parse value from %s', data.value);
- }
- }
+ this._log.info('starting local database replication');
- // if we are not the publisher, then replicate every T_REPLICATE
- if (data.value.publisher !== self._self.nodeID) {
- self.put(data.key, data.value.value, function(err) {
- if (err) {
- self._log.error('failed to replicate item at key %s', data.key);
+ stream.on('data', function(data) {
+ if (typeof data.value === 'string') {
+ try {
+ data.value = JSON.parse(data.value);
+ }
+ catch (err) {
+ return self._log.error('failed to parse value from %s', data.value);
+ }
}
- });
- // if we are the publisher, then only replicate every T_REPUBLISH
- } else if (Date.now() <= data.value.timestamp + constants.T_REPUBLISH) {
- self.put(data.key, data.value.value, function(err) {
- if (err) {
- self._log.error('failed to republish item at key %s', data.key);
+
+ // if we are not the publisher, then replicate every T_REPLICATE
+ if (data.value.publisher !== self._self.nodeID) {
+ self.put(data.key, data.value.value, function(err) {
+ if (err) {
+ self._log.error('failed to replicate item at key %s', data.key);
+ }
+ });
+
+ // if we are the publisher, then only replicate every T_REPUBLISH
+ }
+ else if (Date.now() <= data.value.timestamp + constants.T_REPUBLISH) {
+ self.put(data.key, data.value.value, function(err) {
+ if (err) {
+ self._log.error('failed to republish item at key %s', data.key);
+ }
+ });
}
- });
- }
- });
+ });
- stream.on('error', function(err) {
- self._log.error('error while replicating: %s', err.message);
- });
+ stream.on('error', function(err) {
+ self._log.error('error while replicating: %s', err.message);
+ });
- stream.on('end', function() {
- self._log.info('database replication complete');
- });
+ stream.on('end', function() {
+ self._log.info('database replication complete');
+ });
};
/**
@@ -462,11 +485,11 @@ Node.prototype._updateContact = function(contact, callback) {
* @param {object} params
*/
Node.prototype._handlePing = function(params) {
- var contact = this._rpc._createContact(params);
- var message = new Message('PONG', { referenceID: params.rpcID }, this._self);
+ var contact = this._rpc._createContact(params);
+ var message = new Message('PONG', { referenceID: params.rpcID }, this._self);
- this._log.info('received PING from %s, sending PONG', params.nodeID);
- this._rpc.send(contact, message);
+ this._log.info('received PING from %s, sending PONG', params.nodeID);
+ this._rpc.send(contact, message);
};
/**
@@ -509,13 +532,18 @@ Node.prototype._storeValidatedKeyValue = function (item, params) {
this._storage.put(item.key, JSON.stringify(item), function(err) {
var contact = node._rpc._createContact(params);
- var message = new Message('STORE_REPLY', {
- referenceID: params.rpcID,
- success: !!err
- }, node._self);
+ var message = new Message(
+ 'STORE_REPLY', {
+ referenceID: params.rpcID,
+ success: !!err
+ },
+ node._self);
//node._log.debug('successful store, notifying %s', params.nodeID);
node._rpc.send(contact, message);
+
+ // signal an event that the message was stored
+ node.emit('store', node._self.nodeID, item );
});
};
@@ -530,10 +558,14 @@ Node.prototype._handleFindNode = function(params) {
var contact = this._rpc._createContact(params);
var near = this._getNearestContacts(params.key, constants.K, params.nodeID);
- var message = new Message('FIND_NODE_REPLY', {
- referenceID: params.rpcID,
- contacts: near
- }, this._self);
+
+ var message = new Message(
+ 'FIND_NODE_REPLY',
+ {
+ referenceID: params.rpcID,
+ contacts: near
+ },
+ this._self);
//this._log.debug('sending %s nearest %d contacts', params.nodeID, near.length, {});
@@ -583,66 +615,66 @@ Node.prototype._handleFindValue = function(params) {
* @param {string} nodeID
*/
Node.prototype._getNearestContacts = function(key, limit, nodeID) {
- var contacts = [];
- var hashedKey = utils.createID(key);
- var initialIndex = utils.getBucketIndex(this._self.nodeID, hashedKey);
- var ascBucketIndex = initialIndex;
- var descBucketIndex = initialIndex;
-
- if (this._buckets[initialIndex]) {
- addNearestFromBucket(this._buckets[initialIndex]);
- }
+ var contacts = [];
+ var hashedKey = utils.createID(key);
+ var initialIndex = utils.getBucketIndex(this._self.nodeID, hashedKey);
+ var ascBucketIndex = initialIndex;
+ var descBucketIndex = initialIndex;
+
+ if (this._buckets[initialIndex]) {
+ addNearestFromBucket(this._buckets[initialIndex]);
+ }
- while (contacts.length < limit && ascBucketIndex < constants.B) {
- ascBucketIndex++;
+ while (contacts.length < limit && ascBucketIndex < constants.B) {
+ ascBucketIndex++;
- if (this._buckets[ascBucketIndex]) {
- addNearestFromBucket(this._buckets[ascBucketIndex]);
+ if (this._buckets[ascBucketIndex]) {
+ addNearestFromBucket(this._buckets[ascBucketIndex]);
+ }
}
- }
- while (contacts.length < limit && descBucketIndex >= 0) {
- descBucketIndex--;
+ while (contacts.length < limit && descBucketIndex >= 0) {
+ descBucketIndex--;
- if (this._buckets[descBucketIndex]) {
- addNearestFromBucket(this._buckets[descBucketIndex]);
+ if (this._buckets[descBucketIndex]) {
+ addNearestFromBucket(this._buckets[descBucketIndex]);
+ }
}
- }
- function addToContacts(contact) {
- var isContact = contact instanceof Contact;
- var poolNotFull = contacts.length < limit;
- var notRequester = contact.nodeID !== nodeID;
+ function addToContacts(contact) {
+ var isContact = contact instanceof Contact;
+ var poolNotFull = contacts.length < limit;
+ var notRequester = contact.nodeID !== nodeID;
- if (isContact && poolNotFull && notRequester) {
- contacts.push(contact);
+ if (isContact && poolNotFull && notRequester) {
+ contacts.push(contact);
+ }
}
- }
- function addNearestFromBucket(bucket) {
- var contactList = bucket.getContactList();
- var distances = contactList.map(addDistance).sort(sortKeysByDistance);
- var howMany = limit - contacts.length;
+ function addNearestFromBucket(bucket) {
+ var contactList = bucket.getContactList();
+ var distances = contactList.map(addDistance).sort(sortKeysByDistance);
+ var howMany = limit - contacts.length;
- distances.splice(0, howMany).map(pluckContact).forEach(addToContacts);
- }
+ distances.splice(0, howMany).map(pluckContact).forEach(addToContacts);
+ }
- function pluckContact(c) {
- return c.contact;
- }
+ function pluckContact(c) {
+ return c.contact;
+ }
- function sortKeysByDistance(a, b) {
- return utils.compareKeys(a.distance, b.distance);
- }
+ function sortKeysByDistance(a, b) {
+ return utils.compareKeys(a.distance, b.distance);
+ }
- function addDistance(contact) {
- return {
- contact: contact,
- distance: utils.getDistance(contact.nodeID, hashedKey)
- };
- }
+ function addDistance(contact) {
+ return {
+ contact: contact,
+ distance: utils.getDistance(contact.nodeID, hashedKey)
+ };
+ }
- return contacts;
+ return contacts;
};
module.exports = Node;
diff --git a/libs/transport/p2p/wotkad/lib/router.js b/libs/transport/p2p/wotkad/lib/router.js
index 8be2cb8..37d40a4 100644
--- a/libs/transport/p2p/wotkad/lib/router.js
+++ b/libs/transport/p2p/wotkad/lib/router.js
@@ -1,7 +1,21 @@
-/**
-* @module kad/router
-*/
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+Copyright (C) 2015 The W3C WoT Team
+
+*/
'use strict';
var assert = require('assert');
@@ -33,6 +47,7 @@ function Router(type, key, node) {
this.limit = constants.ALPHA;
this.shortlist = node._getNearestContacts(key, this.limit, node._self.nodeID);
+
this.closestNode = this.shortlist[0];
this.previousClosestNode = null;
this.contacted = {};
@@ -47,20 +62,23 @@ function Router(type, key, node) {
* @param {function} callback
*/
Router.prototype.route = function(callback) {
- if (!this.closestNode) {
- return callback(new Error('Not connected to any peers'));
- }
+ if (!this.closestNode) {
+ return callback(new Error('Not connected to any peers'));
+ }
- this.closestNodeDistance = utils.getDistance(
- this.hashedKey,
- this.closestNode.nodeID
- );
+ this.closestNodeDistance = utils.getDistance(
+ this.hashedKey,
+ this.closestNode.nodeID
+ );
- this.message = new Message('FIND_' + this.type, {
- key: this.key
- }, this.node._self);
+ this.message = new Message(
+ 'FIND_' + this.type,
+ {
+ key: this.key
+ },
+ this.node._self);
- this._iterativeFind(this.shortlist, callback);
+ this._iterativeFind(this.shortlist, callback);
};
/**
@@ -70,11 +88,11 @@ Router.prototype.route = function(callback) {
* @param {function} callback
*/
Router.prototype._iterativeFind = function(contacts, callback) {
- var self = this;
+ var self = this;
- async.each(contacts, this._queryContact.bind(this), function(err) {
- self._handleQueryResults(callback);
- });
+ async.each(contacts, this._queryContact.bind(this), function(err) {
+ self._handleQueryResults(callback);
+ });
};
/**
@@ -84,17 +102,17 @@ Router.prototype._iterativeFind = function(contacts, callback) {
* @param {function} callback
*/
Router.prototype._queryContact = function(contactInfo, callback) {
- var self = this;
- var contact = this.node._rpc._createContact(contactInfo);
+ var self = this;
+ var contact = this.node._rpc._createContact(contactInfo);
- this.node._rpc.send(contact, this.message, function(err, params) {
- if (err) {
- self._removeFromShortList(contact.nodeID);
- return callback();
- }
+ this.node._rpc.send(contact, this.message, function(err, params) {
+ if (err) {
+ self._removeFromShortList(contact.nodeID);
+ return callback();
+ }
- self._handleFindResult(params, contact, callback);
- });
+ self._handleFindResult(params, contact, callback);
+ });
};
/**
@@ -104,53 +122,55 @@ Router.prototype._queryContact = function(contactInfo, callback) {
* @param {object} contact
* @param {function} callback
*/
-Router.prototype._handleFindResult = function(params, contact, callback) {
- var self = this;
- var distance = utils.getDistance(this.hashedKey, contact.nodeID);
-
- this.contacted[contact.nodeID] = this.node._updateContact(contact);
-
- if (utils.compareKeys(distance, this.closestNodeDistance) === -1) {
- this.previousClosestNode = this.closestNode;
- this.closestNode = contact;
- this.closestNodeDistance = distance;
- }
-
- if(this.type === 'NODE') {
- this._addToShortList(params.contacts);
- return callback();
- }
-
- if(!params.value) {
- this.contactsWithoutValue.push(contact);
- this._addToShortList(params.contacts);
- return callback();
- }
-
- var parsedValue;
- try {
- parsedValue = JSON.parse(params.value).value;
- } catch(err) {
- this.node._log.warn('failed to parse value %s', params.value);
- return rejectContact();
- }
-
-this.node.validateKeyValuePair(this.key, parsedValue, function(isValid) {
- if(!isValid) {
- self.node._log.warn('failed to validate key/value pair for %s', self.key);
+Router.prototype._handleFindResult = function (params, contact, callback) {
+ var self = this;
+ var distance = utils.getDistance(this.hashedKey, contact.nodeID);
+
+ this.contacted[contact.nodeID] = this.node._updateContact(contact);
+
+ if (utils.compareKeys(distance, this.closestNodeDistance) === -1) {
+ this.previousClosestNode = this.closestNode;
+ this.closestNode = contact;
+ this.closestNodeDistance = distance;
+ }
+
+ if(this.type === 'NODE') {
+ this._addToShortList(params.contacts);
+ return callback();
+ }
+
+ if(!params.value) {
+ this.contactsWithoutValue.push(contact);
+ this._addToShortList(params.contacts);
+ return callback();
+ }
+
+ var parsedValue;
+ try {
+ parsedValue = JSON.parse(params.value).value;
+ }
+ catch (err) {
+ this.node._log.error('failed to parse value %s', params.value);
return rejectContact();
}
- self.foundValue = true;
- self.value = parsedValue;
+ this.node.validateKeyValuePair(this.key, parsedValue, function(isValid) {
+ if(!isValid) {
+ self.node._log.warn('failed to validate key/value pair for %s', self.key);
+ return rejectContact();
+ }
- callback();
-});
+ self.foundValue = true;
+ self.value = parsedValue;
- function rejectContact() {
- self._removeFromShortList(contact.nodeID);
- callback();
- }
+ callback();
+ });
+
+
+ function rejectContact() {
+ self._removeFromShortList(contact.nodeID);
+ callback();
+ }
};
/**
@@ -159,9 +179,11 @@ this.node.validateKeyValuePair(this.key, parsedValue, function(isValid) {
* @param {array} contacts
*/
Router.prototype._addToShortList = function(contacts) {
- assert(Array.isArray(contacts), 'No contacts supplied');
- this.shortlist = this.shortlist.concat(contacts);
- this.shortlist = _.uniq(this.shortlist, false, 'nodeID');
+ assert(Array.isArray(contacts), 'No contacts supplied');
+
+ this.shortlist = this.shortlist.concat(contacts);
+ this.shortlist = _.uniq(this.shortlist, false, 'nodeID');
+
};
/**
@@ -170,9 +192,15 @@ Router.prototype._addToShortList = function(contacts) {
* @param {string} nodeID
*/
Router.prototype._removeFromShortList = function(nodeID) {
- this.shortlist = _.reject(this.shortlist, function(c) {
- return c.nodeID === nodeID;
- });
+ this.shortlist = _.reject(this.shortlist, function(c) {
+ return c.nodeID === nodeID;
+ });
+
+ for (var i = 0; i < this.shortlist.length; i++) {
+ if (!(this.shortlist[i] instanceof Contact)) {
+ throw new Error('Invalid contact');
+ }
+ }
};
/**
@@ -181,28 +209,29 @@ Router.prototype._removeFromShortList = function(nodeID) {
* @param {function} callback
*/
Router.prototype._handleQueryResults = function(callback) {
- var self = this;
+ var self = this;
- if (this.foundValue) {
- return this._handleValueReturned(callback);
- }
+ if (this.foundValue) {
+ return this._handleValueReturned(callback);
+ }
- var closestNodeUnchanged = this.closestNode === this.previousClosestNode;
- var shortlistFull = this.shortlist.length >= constants.K;
+ var closestNodeUnchanged = this.closestNode === this.previousClosestNode;
+ var shortlistFull = this.shortlist.length >= constants.K;
- if (closestNodeUnchanged || shortlistFull) {
- return callback(null, 'NODE', this.shortlist);
- }
+ if (closestNodeUnchanged || shortlistFull) {
+ return callback(null, 'NODE', this.shortlist);
+ }
- var remainingContacts = _.reject(this.shortlist, function(c) {
- return self.contacted[c.nodeID];
- });
+ var remainingContacts = _.reject(this.shortlist, function(c) {
+ return self.contacted[c.nodeID];
+ });
- if (remainingContacts.length === 0) {
- callback(null, 'NODE', this.shortlist);
- } else {
- this._iterativeFind(remainingContacts.splice(0, constants.ALPHA), callback);
- }
+ if (remainingContacts.length === 0) {
+ callback(null, 'NODE', this.shortlist);
+ }
+ else {
+ this._iterativeFind(remainingContacts.splice(0, constants.ALPHA), callback);
+ }
};
/**
diff --git a/libs/transport/p2p/wotkad/lib/rpc.js b/libs/transport/p2p/wotkad/lib/rpc.js
index a3eb831..4530bde 100644
--- a/libs/transport/p2p/wotkad/lib/rpc.js
+++ b/libs/transport/p2p/wotkad/lib/rpc.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/rpc
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -45,25 +60,29 @@ function RPC(options) {
* @param {object} message
* @param {function} callback
*/
-RPC.prototype.send = function(contact, message, callback) {
- assert(contact instanceof Contact, 'Invalid contact supplied');
- assert(message instanceof Message, 'Invalid message supplied');
-
- merge(message.params, {
- rpcID: this._createMessageID()
- });
-
- var data = message.serialize();
- var offset = 0;
-
- this._send(data, contact);
-
- if (typeof callback === 'function') {
- this._pendingCalls[message.params.rpcID] = {
- timestamp: Date.now(),
- callback: callback
- };
- }
+RPC.prototype.send = function (contact, message, callback) {
+ //assert(contact instanceof Contact, 'Invalid contact supplied');
+ //if (!(contact instanceof Contact)) {
+ // return;
+ //}
+ assert(contact.address && contact.port, 'Invalid contact supplied');
+ assert(message instanceof Message, 'Invalid message supplied');
+
+ merge(message.params, {
+ rpcID: this._createMessageID()
+ });
+
+ var data = message.serialize();
+ var offset = 0;
+
+ this._send(data, contact);
+
+ if (typeof callback === 'function') {
+ this._pendingCalls[message.params.rpcID] = {
+ timestamp: Date.now(),
+ callback: callback
+ };
+ }
};
/**
@@ -71,7 +90,7 @@ RPC.prototype.send = function(contact, message, callback) {
* #close
*/
RPC.prototype.close = function() {
- this._close();
+ this._close();
};
/**
@@ -118,15 +137,15 @@ RPC.prototype._handleMessage = function(buffer, info) {
* #_expireCalls
*/
RPC.prototype._expireCalls = function() {
- for (var rpcID in this._pendingCalls) {
- var pendingCall = this._pendingCalls[rpcID];
- var timePassed = Date.now() - pendingCall.timestamp;
-
- if (timePassed > constants.T_RESPONSETIMEOUT) {
- pendingCall.callback(new Error('RPC with ID `' + rpcID + '` timed out'));
- delete this._pendingCalls[rpcID];
+ for (var rpcID in this._pendingCalls) {
+ var pendingCall = this._pendingCalls[rpcID];
+ var timePassed = Date.now() - pendingCall.timestamp;
+
+ if (timePassed > constants.T_RESPONSETIMEOUT) {
+ pendingCall.callback(new Error('RPC with ID `' + rpcID + '` timed out'));
+ delete this._pendingCalls[rpcID];
+ }
}
- }
};
/* istanbul ignore next */
@@ -135,7 +154,7 @@ RPC.prototype._expireCalls = function() {
* #_close
*/
RPC.prototype._close = function() {
- throw new Error('Method not implemented');
+ throw new Error('Method not implemented');
};
/* istanbul ignore next */
@@ -146,7 +165,7 @@ RPC.prototype._close = function() {
* @param {Contact} contact
*/
RPC.prototype._send = function(data, contact) {
- throw new Error('Method not implemented');
+ throw new Error('Method not implemented');
};
/* istanbul ignore next */
@@ -156,7 +175,7 @@ RPC.prototype._send = function(data, contact) {
* @param {object} options
*/
RPC.prototype._createContact = function(options) {
- throw new Error('Method not implemented');
+ throw new Error('Method not implemented');
};
module.exports = RPC;
diff --git a/libs/transport/p2p/wotkad/lib/storages/localstorage.js b/libs/transport/p2p/wotkad/lib/storages/localstorage.js
index 4099059..69da7bb 100644
--- a/libs/transport/p2p/wotkad/lib/storages/localstorage.js
+++ b/libs/transport/p2p/wotkad/lib/storages/localstorage.js
@@ -9,7 +9,7 @@ var EventEmitter = require('events').EventEmitter
var map = new Map();
function KadLocalStorage(namespace) {
- if (namespace.indexOf('_') >= 0) throw new Error('invalid namespace')
+ if (namespace.indexOf('_') >= 0) throw new Error('Invalid namespace, character "_" in the namespace and nick name is not allowed')
this._prefix = namespace + '_'
}
diff --git a/libs/transport/p2p/wotkad/lib/transports/address-port-contact.js b/libs/transport/p2p/wotkad/lib/transports/address-port-contact.js
index 718c9ab..0276f21 100644
--- a/libs/transport/p2p/wotkad/lib/transports/address-port-contact.js
+++ b/libs/transport/p2p/wotkad/lib/transports/address-port-contact.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/contact
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -18,26 +33,27 @@ inherits(AddressPortContact, Contact);
*/
function AddressPortContact(options) {
- if (!(this instanceof AddressPortContact)) {
- return new AddressPortContact(options);
- }
+ if (!(this instanceof AddressPortContact)) {
+ return new AddressPortContact(options);
+ }
- assert(options instanceof Object, 'Invalid options were supplied');
- assert(typeof options.address === 'string', 'Invalid address was supplied');
- assert(typeof options.port === 'number', 'Invalid port was supplied');
+ assert(options instanceof Object, 'Invalid options were supplied');
+ assert(typeof options.address === 'string', 'Invalid address was supplied');
+ assert(typeof options.port === 'number', 'Invalid port was supplied');
- this.address = options.address;
- this.port = options.port;
+ this.address = options.address;
+ this.port = options.port;
- Contact.call(this, options)
+ Contact.call(this, options)
}
+
/**
* Generate a NodeID by taking the SHA1 hash of the address and port
* #_createNodeID
*/
AddressPortContact.prototype._createNodeID = function() {
- return utils.createID(this.toString());
+ return utils.createID(this.toString());
};
/**
@@ -45,7 +61,7 @@ AddressPortContact.prototype._createNodeID = function() {
* #_toString
*/
AddressPortContact.prototype.toString = function() {
- return this.address + ':' + this.port;
+ return this.address + ':' + this.port;
};
module.exports = AddressPortContact;
diff --git a/libs/transport/p2p/wotkad/lib/transports/index.js b/libs/transport/p2p/wotkad/lib/transports/index.js
index 63bd801..c1f6a14 100644
--- a/libs/transport/p2p/wotkad/lib/transports/index.js
+++ b/libs/transport/p2p/wotkad/lib/transports/index.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/transports
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
diff --git a/libs/transport/p2p/wotkad/lib/transports/tcp.js b/libs/transport/p2p/wotkad/lib/transports/tcp.js
index 183c42c..f9ff587 100644
--- a/libs/transport/p2p/wotkad/lib/transports/tcp.js
+++ b/libs/transport/p2p/wotkad/lib/transports/tcp.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/transports/tcp
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
diff --git a/libs/transport/p2p/wotkad/lib/transports/udp.js b/libs/transport/p2p/wotkad/lib/transports/udp.js
index 96bb88b..fe734bf 100644
--- a/libs/transport/p2p/wotkad/lib/transports/udp.js
+++ b/libs/transport/p2p/wotkad/lib/transports/udp.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/transports/udp
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
@@ -17,34 +32,34 @@ inherits(UDPTransport, RPC);
* @param {object} options
*/
function UDPTransport(options) {
- if (!(this instanceof UDPTransport)) {
- return new UDPTransport(options);
- }
+ if (!(this instanceof UDPTransport)) {
+ return new UDPTransport(options);
+ }
- var self = this;
- var socketOptions = { type: 'udp4', reuseAddr: true };
- var socketMessageHandler = this._handleMessage.bind(this);
+ var self = this;
+ var socketOptions = { type: 'udp4', reuseAddr: true };
+ var socketMessageHandler = this._handleMessage.bind(this);
- RPC.call(this, options);
+ RPC.call(this, options);
- this._socket = dgram.createSocket(socketOptions, socketMessageHandler);
+ this._socket = dgram.createSocket(socketOptions, socketMessageHandler);
- this._socket.on('error', function(err) {
- var contact = self._contact;
- self._log.warn('failed to bind to supplied address %s', contact.address);
- self._log.info('binding to all interfaces as a fallback');
- self._socket.close();
+ this._socket.on('error', function(err) {
+ var contact = self._contact;
+ self._log.warn('failed to bind to supplied address %s', contact.address);
+ self._log.info('binding to all interfaces as a fallback');
+ self._socket.close();
- self._socket = dgram.createSocket(socketOptions, socketMessageHandler);
+ self._socket = dgram.createSocket(socketOptions, socketMessageHandler);
- self._socket.bind(contact.port);
- });
+ self._socket.bind(contact.port);
+ });
- this._socket.on('listening', function() {
- self.emit('ready');
- });
+ this._socket.on('listening', function() {
+ self.emit('ready');
+ });
- this._socket.bind(this._contact.port, this._contact.address);
+ this._socket.bind(this._contact.port, this._contact.address);
}
/**
@@ -53,7 +68,7 @@ function UDPTransport(options) {
* @param {object} options
*/
UDPTransport.prototype._createContact = function(options) {
- return new AddressPortContact(options);
+ return new AddressPortContact(options);
}
/**
@@ -63,7 +78,7 @@ UDPTransport.prototype._createContact = function(options) {
* @param {Contact} contact
*/
UDPTransport.prototype._send = function(data, contact) {
- this._socket.send(data, 0, data.length, contact.port, contact.address);
+ this._socket.send(data, 0, data.length, contact.port, contact.address);
};
/**
@@ -71,7 +86,7 @@ UDPTransport.prototype._send = function(data, contact) {
* #_close
*/
UDPTransport.prototype._close = function() {
- this._socket.close();
+ this._socket.close();
};
module.exports = UDPTransport;
diff --git a/libs/transport/p2p/wotkad/lib/utils.js b/libs/transport/p2p/wotkad/lib/utils.js
index 3a4dd01..ff445c7 100644
--- a/libs/transport/p2p/wotkad/lib/utils.js
+++ b/libs/transport/p2p/wotkad/lib/utils.js
@@ -1,5 +1,20 @@
-/**
-* @module kad/utils
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
*/
'use strict';
diff --git a/libs/transport/p2p/wotkad/peer_network.js b/libs/transport/p2p/wotkad/peer_network.js
index 4ba5e5f..7d67736 100644
--- a/libs/transport/p2p/wotkad/peer_network.js
+++ b/libs/transport/p2p/wotkad/peer_network.js
@@ -1,4 +1,23 @@
-var util = require("util");
+/*
+
+This file is part of W3C Web-of-Things-Framework.
+
+W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework.
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see .
+
+File created by Tibor Zsolt Pardi
+
+Copyright (C) 2015 The W3C WoT Team
+
+*/
+
+var util = require("util");
var events = require("events");
var assert = require('assert');
var async = require('async');
@@ -14,6 +33,7 @@ function PeerNetwork() {
events.EventEmitter.call(this);
+ this.stored_items = {};
}
PeerNetwork.prototype.create_peer = function (options) {
@@ -22,24 +42,46 @@ PeerNetwork.prototype.create_peer = function (options) {
assert(options.address, 'No address supplied');
assert(options.port, 'No port supplied');
assert(options.nick, 'No nick supplied');
+ assert(options.alg, 'No acryptography algorithm supplied');
+ assert(options.private_key, 'No private key supplied');
+ assert(options.public_key, 'No private key supplied');
var peernode = wotkad({
address: options.address,
port: options.port,
nick: options.nick,
+ alg: options.alg,
+ private_key: options.private_key,
+ public_key: options.public_key,
seeds: options.seeds,
validateKeyValuePair: this.validate_keyvaluepair
});
+ peernode.on('store', this.msg_stored.bind(this));
+
return peernode;
}
-PeerNetwork.prototype.validate_keyvaluepair = function (key, value, callback) {
- callback(true);
+PeerNetwork.prototype.msg_stored = function (node_id, item) {
+ if (!item || !item.key || !item.hash)
+ return;
+
+ var hash = item.hash;
+ var key = item.key;
+ var stored = this.stored_items[key];
+ if (stored == hash) {
+ return;
+ }
+
+ this.stored_items[key] = hash;
+ this.emit("data", key);
}
+PeerNetwork.prototype.validate_keyvaluepair = function (key, value, callback) {
+ callback(true);
+}
module.exports = PeerNetwork;
\ No newline at end of file
diff --git a/package.json b/package.json
index 692171d..6e6b4bf 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
},
"dependencies": {
"async": "^1.5.0",
+ "bigi": "^1.4.1",
"body-parser": "^1.13.2",
"clarinet": "^0.11.0",
"coap": "^0.12.0",
diff --git a/transports/p2p/handler.js b/transports/p2p/handler.js
index 10235f9..d94eb50 100644
--- a/transports/p2p/handler.js
+++ b/transports/p2p/handler.js
@@ -1,23 +1,35 @@
var assert = require('assert');
var logger = require('../../logger');
-var wotkad = require('../../libs/transport/p2p/wotkad');
+var PeerNetwork = require('../../libs/transport/p2p/wotkad/peer_network');
exports.start = function start(settings) {
try {
logger.info('Bootstrap P2P network, initiate seed node');
- // start the P2P overlay networks and Kademlia DHT
+ if (!settings || !settings.nodes || !settings.nodes.length) {
+ throw new Error("Invalid P2P configuration settings");
+ }
- assert(settings.address, 'No p2p address is specified');
- assert(settings.port, 'No p2p port is specified');
+ // start the P2P overlay networks and Kademlia DHT
+ var peernet = new PeerNetwork();
- // Create our first node
- var seed_node = wotkad({
- transport: wotkad.transports.UDP,
- address: '127.0.0.1',
- port: 65530,
- nick: 'wotseed01'
- });
+ for (var i = 0; i < settings.nodes.length; i++) {
+ var node = settings.nodes[i];
+ assert(node.address, 'No p2p address is specified');
+ assert(node.port, 'No p2p port is specified');
+ assert(node.nick, 'No p2p nick is specified');
+
+ // Create our first node
+ var seed_node = peernet.create_peer({
+ address: node.address,
+ port: node.port,
+ nick: node.nick,
+ alg: {},
+ private_key: {},
+ public_key: {},
+ seeds: node.seeds
+ });
+ }
logger.info('P2P overlay network started');
}