UNPKG

caesar

Version:

An easy-to-use advanced cryptography library.

415 lines (376 loc) 12.5 kB
// Generated by CoffeeScript 1.7.1 (function() { var crypto, message, opse, stream, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; crypto = require('crypto'); stream = require('stream'); message = require('./message'); opse = require('./opse'); exports.Indexer = (function(_super) { __extends(Indexer, _super); function Indexer(id) { var _ref; this.id = id; if (!this instanceof exports.Indexer) { return new exports.Indexer(this.id); } stream.Transform.call(this, { decodeStrings: true }); _ref = [ { id: this.id, list: {} }, '', 0 ], this.index = _ref[0], this.leftover = _ref[1], this.size = _ref[2]; } Indexer.prototype._clean = function(word) { return word.toLowerCase().replace(/[^a-z0-9]/g, ''); }; Indexer.prototype._push = function(data) { var i, word, _i, _len; for (i in data) { word = data[i]; data[i] = this._clean(word); } for (_i = 0, _len = data.length; _i < _len; _i++) { word = data[_i]; if (this.index.list[word] != null) { ++this.index.list[word]; } else { this.index.list[word] = 1; } } return delete this.index['']; }; Indexer.prototype._transform = function(chunk, encoding, done) { var data, _ref; data = (this.leftover + chunk.toString()).split(/[\s]/g); this.leftover = (_ref = data.splice(data.length - 1, 1)) != null ? _ref[0] : void 0; this._push(data); this.size += chunk.length; this.push(chunk); return done(); }; Indexer.prototype._flush = function(done) { if (this.leftover.length === 0) { return done(); } this._push([this.leftover]); this.push(null); return done(); }; return Indexer; })(stream.Transform); exports.Server = (function() { function Server(index) { this.index = index; if (!this instanceof exports.Server) { return new exports.Server(this.index); } } Server.prototype.search = function(query) { var dn, domain, good, out, trpdr, trpdrs, _i, _len; out = []; for (dn in query) { trpdrs = query[dn]; if (this.index[dn] == null) { return; } domain = this.index[dn].index; good = function(entry) { return (entry != null) && -1 === out.indexOf(entry); }; for (_i = 0, _len = trpdrs.length; _i < _len; _i++) { trpdr = trpdrs[_i]; if (good(domain[trpdr])) { out.push(domain[trpdr]); } } } return out.sort(function(a, b) { return b[1] - a[1]; }); }; Server.prototype.update = function(domain, index, reps) { var cand, dn, _i, _len, _ref; if (reps == null) { reps = []; } _ref = this.index; for (dn in _ref) { cand = _ref[dn]; if (cand.docs.length <= index.docs.length && reps.indexOf(dn) === -1) { return [dn, cand.docs]; } } for (_i = 0, _len = reps.length; _i < _len; _i++) { dn = reps[_i]; delete this.index[dn]; } this.index[domain] = index; return true; }; return Server; })(); exports.MultiUserServer = (function(_super) { __extends(MultiUserServer, _super); function MultiUserServer(state, index, keychain) { this.index = index; this.keychain = keychain; if (!this instanceof exports.MultiUserServer) { return new exports.MultiUserServer(state, this.index, this.keychain); } if (state !== null) { this.state(state); } } MultiUserServer.prototype.state = function(state) { var decrypter; decrypter = new message.Decrypter(this.keychain, true, 'asym'); decrypter.write(state); return this.stateKey = decrypter.read(); }; MultiUserServer.prototype.search = function(query) { var decipher, domain, i, trpdr, trpdrs; for (domain in query) { trpdrs = query[domain]; for (i in trpdrs) { trpdr = trpdrs[i]; decipher = crypto.createDecipher('aes-256-ctr', this.stateKey); decipher.write(trpdr, 'base64'); query[domain][i] = decipher.read().toString('base64'); } } return MultiUserServer.__super__.search.call(this, query); }; return MultiUserServer; })(exports.Server); exports.Client = (function() { function Client(keys) { this.keys = keys; if (!this instanceof exports.Client) { return new exports.Client(this.keys); } } Client.prototype.outdate = function() { var dn, dns, _i, _len, _results; dns = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _results = []; for (_i = 0, _len = dns.length; _i < _len; _i++) { dn = dns[_i]; _results.push(delete this.keys[dn]); } return _results; }; Client.prototype.createQuery = function(word) { var buff, cipher, dn, hash, i, k, key, offset, out, sum, _ref; word = word.substr(0, 28); offset = 28 - word.length; out = {}; _ref = this.keys; for (dn in _ref) { key = _ref[dn]; if (!(dn !== 'sorting')) { continue; } out[dn] = []; i = 0; while (i !== key[0]) { buff = new Buffer(32); buff.fill(0); buff.writeUInt32BE(i, 28); buff.write(word, offset, word.length); hash = crypto.createHash('sha256'); hash.end(buff); sum = hash.read(); cipher = crypto.createCipher('aes-256-cbc', key[1]); cipher.write(sum); k = cipher.read().toString('base64'); out[dn].push(k); ++i; } } return out; }; Client.prototype.secureIndex = function() { var buff, c, cipher, count, data, docs, domain, ent, entries, entry, hash, i, id, index, indexes, k, key, keys, l, list, max, n, offset, one, rsindex, shuffle, sindex, sum, threshold, two, word, words, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1; domain = arguments[0], max = arguments[1], indexes = 3 <= arguments.length ? __slice.call(arguments, 2) : []; key = crypto.randomBytes(32); index = {}; for (_i = 0, _len = indexes.length; _i < _len; _i++) { list = indexes[_i]; _ref = list.list; for (word in _ref) { count = _ref[word]; if (index[word] != null) { index[word].push([list.id, count]); } else { index[word] = [[list.id, count]]; } } } sindex = {}; for (word in index) { entries = index[word]; word = word.substr(0, 28); offset = 28 - word.length; for (n in entries) { entry = entries[n]; buff = new Buffer(32); buff.fill(0); buff.writeUInt32BE(n, 28); buff.write(word, offset, word.length); hash = crypto.createHash('sha256'); hash.end(buff); sum = hash.read(); cipher = crypto.createCipher('aes-256-cbc', key); cipher.write(sum); k = cipher.read().toString('base64'); entry[1] = opse.encrypt(this.keys.sorting, entry[1]); sindex[k] = entry; } } words = Object.keys(index); docs = []; for (word in index) { entries = index[word]; for (_j = 0, _len1 = entries.length; _j < _len1; _j++) { ent = entries[_j]; if (-1 === docs.indexOf(ent[0])) { docs.push(ent[0]); } } } this.keys[domain] = [docs.length, key]; one = [256, 131072, 50331648]; two = [256, 65536, 16777216]; _ref1 = [0, 0, 0], threshold = _ref1[0], sum = _ref1[1], i = _ref1[2]; while (threshold <= max) { threshold += one[i]; sum += two[i]; ++i; } threshold = threshold - one[i - 1]; sum = sum - two[i - 1]; sum += Math.floor((max - threshold) / i); for (_k = 0, _len2 = docs.length; _k < _len2; _k++) { id = docs[_k]; c = 0; for (_l = 0, _len3 = sindex.length; _l < _len3; _l++) { entry = sindex[_l]; if (entry === id) { ++c; } } l = sum - c; while (l -= 1) { buff = new Buffer(32); buff.fill(0); buff.writeUInt32BE(docs.length + l, 28); hash = crypto.createHash('sha256'); hash.end(buff); sum = hash.read(); cipher = crypto.createCipher('aes-256-cbc', key); cipher.write(sum); cipher.end('00000000', 'hex'); data = cipher.read(); k = data.slice(0, 32).toString('base64'); n = data.slice(32).readUInt32BE(0) % 131072; sindex[k] = [id, n]; } } shuffle = function(array) { var a, b, bytes, j, _ref2; i = array.length; if (i === 0) { return false; } bytes = Math.ceil(Math.log(array.length) / (8 * Math.log(2))); while (i -= 1) { j = array.length; while (!(j < array.length)) { a = new Buffer(4); a.fill(0); b = crypto.randomBytes(bytes); b.copy(a); j = a.readUInt32LE(0); } _ref2 = [array[i], array[j]], array[j] = _ref2[0], array[i] = _ref2[1]; } return array; }; keys = shuffle(Object.keys(sindex)); rsindex = {}; for (_m = 0, _len4 = keys.length; _m < _len4; _m++) { key = keys[_m]; rsindex[key] = sindex[key]; } return { docs: docs, index: rsindex }; }; return Client; })(); exports.MultiUserClient = (function(_super) { __extends(MultiUserClient, _super); function MultiUserClient(keys, keychain) { this.keys = keys; this.keychain = keychain != null ? keychain : {}; if (!this instanceof exports.MultiUserClient) { return new exports.MultiUserClient(this.keys, this.keychain); } } MultiUserClient.prototype.state = function() { var encrypter, key; key = crypto.randomBytes(32); encrypter = new message.Encrypter(this.keychain, true, 'asym'); encrypter.write(key); return encrypter.read(); }; MultiUserClient.prototype.packKeys = function() { var encrypter, out, server; out = {}; server = this.keychain.server; delete this.keychain.server; encrypter = new message.Encrypter(this.keychain, true, 'asym'); encrypter.write(new Buffer(JSON.stringify(this.keys))); this.keychain.server = server; return encrypter.read(); }; MultiUserClient.prototype.unpackKeys = function(packed) { var decrypter, dn, key, out, server; server = this.keychain.server; delete this.keychain.server; decrypter = new message.Decrypter(this.keychain, true, 'asym'); decrypter.write(packed); out = JSON.parse(decrypter.read()); for (dn in out) { key = out[dn]; this.keys[dn] = [key[0], new Buffer(key[1])]; } return this.keychain.server = server; }; MultiUserClient.prototype.createQuery = function(state, word) { var cipher, decrypter, domain, i, key, query, trpdr, trpdrs; decrypter = new message.Decrypter(this.keychain, true, 'asym'); decrypter.write(state); key = decrypter.read(); query = MultiUserClient.__super__.createQuery.call(this, word); for (domain in query) { trpdrs = query[domain]; for (i in trpdrs) { trpdr = trpdrs[i]; cipher = crypto.createCipher('aes-256-ctr', key); cipher.write(trpdr, 'base64'); query[domain][i] = cipher.read().toString('base64'); } } return query; }; return MultiUserClient; })(exports.Client); }).call(this);