UNPKG

cryptobox-hd

Version:

High-level API with persistent storage for Proteus-HD.

1,339 lines (1,214 loc) 114 kB
/*! cryptobox-hd v1.0.1 */ var cryptobox = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 12); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { module.exports = Proteus; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var RecordAlreadyExistsError_1 = __webpack_require__(14); exports.RecordAlreadyExistsError = RecordAlreadyExistsError_1.default; var RecordNotFoundError_1 = __webpack_require__(15); exports.RecordNotFoundError = RecordNotFoundError_1.default; var RecordTypeError_1 = __webpack_require__(16); exports.RecordTypeError = RecordTypeError_1.default; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var DecryptionError = (function (_super) { __extends(DecryptionError, _super); function DecryptionError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, DecryptionError.prototype); _this.message = message; _this.name = _this.constructor.name; _this.stack = new Error().stack; return _this; } return DecryptionError; }(Error)); exports.DecryptionError = DecryptionError; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var EventEmitter = __webpack_require__(20); var LRUCache = __webpack_require__(25); var error_1 = __webpack_require__(6); var CryptoboxSession_1 = __webpack_require__(4); var DecryptionError_1 = __webpack_require__(2); var InvalidPreKeyFormatError_1 = __webpack_require__(5); var ReadOnlyStore_1 = __webpack_require__(7); var error_2 = __webpack_require__(1); var Cryptobox = (function (_super) { __extends(Cryptobox, _super); function Cryptobox(cryptoBoxStore, minimumAmountOfPreKeys) { if (minimumAmountOfPreKeys === void 0) { minimumAmountOfPreKeys = 1; } var _this = _super.call(this) || this; if (!cryptoBoxStore) { throw new Error("You cannot initialize Cryptobox without a storage component."); } if (minimumAmountOfPreKeys > Proteus.keys.PreKey.MAX_PREKEY_ID) { minimumAmountOfPreKeys = Proteus.keys.PreKey.MAX_PREKEY_ID; } _this.cachedPreKeys = []; _this.cachedSessions = new LRUCache(1000); _this.minimumAmountOfPreKeys = minimumAmountOfPreKeys; _this.store = cryptoBoxStore; _this.pk_store = new ReadOnlyStore_1.ReadOnlyStore(_this.store); var storageEngine = cryptoBoxStore.constructor.name; return _this; } Cryptobox.prototype.save_session_in_cache = function (session) { this.cachedSessions.set(session.id, session); return session; }; Cryptobox.prototype.load_session_from_cache = function (session_id) { return this.cachedSessions.get(session_id); }; Cryptobox.prototype.remove_session_from_cache = function (session_id) { this.cachedSessions.delete(session_id); }; Cryptobox.prototype.create = function () { var _this = this; return this.create_new_identity() .then(function (identity) { _this.identity = identity; return _this.create_last_resort_prekey(); }) .then(function (lastResortPreKey) { _this.cachedPreKeys = [lastResortPreKey]; return _this.init(); }); }; Cryptobox.prototype.load = function () { var _this = this; return this.store.load_identity() .then(function (identity) { if (identity) { _this.identity = identity; return _this.store.load_prekeys(); } throw new error_1.CryptoboxError('Failed to load local identity'); }) .then(function (preKeysFromStorage) { var lastResortPreKey = preKeysFromStorage.find(function (preKey) { return preKey.key_id === Proteus.keys.PreKey.MAX_PREKEY_ID; }); if (lastResortPreKey) { _this.lastResortPreKey = lastResortPreKey; _this.cachedPreKeys = preKeysFromStorage; return _this.init(); } throw new error_1.CryptoboxError('Failed to load last resort PreKey'); }); }; Cryptobox.prototype.init = function () { var _this = this; return this.refill_prekeys() .then(function () { var ids = _this.cachedPreKeys.map(function (preKey) { return preKey.key_id.toString(); }); return _this.cachedPreKeys.sort(function (a, b) { return a.key_id - b.key_id; }); }); }; Cryptobox.prototype.get_serialized_last_resort_prekey = function () { return Promise.resolve(this.serialize_prekey(this.lastResortPreKey)); }; Cryptobox.prototype.get_serialized_standard_prekeys = function () { var _this = this; var standardPreKeys = this.cachedPreKeys .map(function (preKey) { var isLastResortPreKey = preKey.key_id === Proteus.keys.PreKey.MAX_PREKEY_ID; return isLastResortPreKey ? undefined : _this.serialize_prekey(preKey); }) .filter(function (preKeyJson) { return preKeyJson; }); return Promise.resolve(standardPreKeys); }; Cryptobox.prototype.publish_event = function (topic, event) { this.emit(topic, event); }; Cryptobox.prototype.publish_prekeys = function (newPreKeys) { if (newPreKeys.length > 0) { this.publish_event(Cryptobox.TOPIC.NEW_PREKEYS, newPreKeys); } }; Cryptobox.prototype.publish_session_id = function (session) { this.publish_event(Cryptobox.TOPIC.NEW_SESSION, session.id); }; Cryptobox.prototype.refill_prekeys = function () { var _this = this; return Promise.resolve() .then(function () { var missingAmount = Math.max(0, _this.minimumAmountOfPreKeys - _this.cachedPreKeys.length); if (missingAmount > 0) { var startId = _this.cachedPreKeys .reduce(function (currentHighestValue, currentPreKey) { var isLastResortPreKey = currentPreKey.key_id === Proteus.keys.PreKey.MAX_PREKEY_ID; return isLastResortPreKey ? currentHighestValue : Math.max(currentPreKey.key_id + 1, currentHighestValue); }, 0); return _this.new_prekeys(startId, missingAmount); } return []; }) .then(function (newPreKeys) { if (newPreKeys.length > 0) { _this.cachedPreKeys = _this.cachedPreKeys.concat(newPreKeys); } return newPreKeys; }); }; Cryptobox.prototype.create_new_identity = function () { var _this = this; return Promise.resolve() .then(function () { return _this.store.delete_all(); }) .then(function () { var identity = Proteus.keys.IdentityKeyPair.new(); return _this.store.save_identity(identity); }); }; Cryptobox.prototype.session_from_prekey = function (session_id, pre_key_bundle) { var _this = this; var cachedSession = this.load_session_from_cache(session_id); if (cachedSession) { return Promise.resolve(cachedSession); } return Promise.resolve() .then(function () { var bundle; try { bundle = Proteus.keys.PreKeyBundle.deserialise(pre_key_bundle); } catch (error) { throw new InvalidPreKeyFormatError_1.InvalidPreKeyFormatError("PreKey bundle for session \"" + session_id + "\" has an unsupported format."); } return Proteus.session.Session.init_from_prekey(_this.identity, bundle) .then(function (session) { var cryptobox_session = new CryptoboxSession_1.CryptoboxSession(session_id, _this.pk_store, session); return _this.session_save(cryptobox_session); }) .catch(function (error) { if (error instanceof error_2.RecordAlreadyExistsError) { return _this.session_load(session_id); } throw error; }); }); }; Cryptobox.prototype.session_from_message = function (session_id, envelope) { var _this = this; var env = Proteus.message.Envelope.deserialise(envelope); return Proteus.session.Session.init_from_message(this.identity, this.pk_store, env) .then(function (tuple) { var session = tuple[0], decrypted = tuple[1]; var cryptoBoxSession = new CryptoboxSession_1.CryptoboxSession(session_id, _this.pk_store, session); return [cryptoBoxSession, decrypted]; }); }; Cryptobox.prototype.session_load = function (session_id) { var _this = this; var cachedSession = this.load_session_from_cache(session_id); if (cachedSession) { return Promise.resolve(cachedSession); } return this.store.read_session(this.identity, session_id) .then(function (session) { var cryptobox_session = new CryptoboxSession_1.CryptoboxSession(session_id, _this.pk_store, session); return _this.save_session_in_cache(cryptobox_session); }); }; Cryptobox.prototype.session_cleanup = function (session) { var _this = this; var preKeyDeletionPromises = this.pk_store.prekeys.map(function (preKeyId) { return _this.store.delete_prekey(preKeyId); }); return Promise.all(preKeyDeletionPromises) .then(function (deletedPreKeyIds) { _this.cachedPreKeys = _this.cachedPreKeys.filter(function (preKey) { return !deletedPreKeyIds.includes(preKey.key_id); }); _this.pk_store.release_prekeys(deletedPreKeyIds); return _this.refill_prekeys(); }) .then(function (newPreKeys) { _this.publish_prekeys(newPreKeys); return _this.save_session_in_cache(session); }) .then(function () { return session; }); }; Cryptobox.prototype.session_save = function (session) { var _this = this; return this.store.create_session(session.id, session.session) .then(function () { return _this.session_cleanup(session); }); }; Cryptobox.prototype.session_update = function (session) { var _this = this; return this.store.update_session(session.id, session.session) .then(function () { return _this.session_cleanup(session); }); }; Cryptobox.prototype.session_delete = function (session_id) { this.remove_session_from_cache(session_id); return this.store.delete_session(session_id); }; Cryptobox.prototype.create_last_resort_prekey = function () { var _this = this; return Promise.resolve() .then(function () { _this.lastResortPreKey = Proteus.keys.PreKey.last_resort(); return _this.store.save_prekeys([_this.lastResortPreKey]); }) .then(function (preKeys) { return preKeys[0]; }); }; Cryptobox.prototype.serialize_prekey = function (prekey) { return Proteus.keys.PreKeyBundle.new(this.identity.public_key, prekey).serialised_json(); }; Cryptobox.prototype.new_prekeys = function (start, size) { var _this = this; if (size === void 0) { size = 0; } if (size === 0) { return Promise.resolve([]); } return Promise.resolve() .then(function () { return Proteus.keys.PreKey.generate_prekeys(start, size); }) .then(function (newPreKeys) { return _this.store.save_prekeys(newPreKeys); }); }; Cryptobox.prototype.encrypt = function (session_id, payload, pre_key_bundle, confuse_pre_key_id) { var _this = this; var encryptedBuffer; var loadedSession; return Promise.resolve() .then(function () { if (pre_key_bundle) { return _this.session_from_prekey(session_id, pre_key_bundle); } return _this.session_load(session_id); }) .then(function (session) { loadedSession = session; return loadedSession.encrypt(payload, confuse_pre_key_id); }) .then(function (encrypted) { encryptedBuffer = encrypted; return _this.session_update(loadedSession); }) .then(function () { return encryptedBuffer; }); }; Cryptobox.prototype.decrypt = function (session_id, ciphertext) { var _this = this; var is_new_session = false; var message; var session; if (ciphertext.byteLength === 0) { return Promise.reject(new DecryptionError_1.DecryptionError('Cannot decrypt an empty ArrayBuffer.')); } return this.session_load(session_id) .catch(function () { return _this.session_from_message(session_id, ciphertext); }) .then(function (value) { var decrypted_message; if (value[0] !== undefined) { session = value[0], decrypted_message = value[1]; _this.publish_session_id(session); is_new_session = true; return decrypted_message; } session = value; return session.decrypt(ciphertext); }) .then(function (decrypted_message) { message = decrypted_message; if (is_new_session) { return _this.session_save(session); } return _this.session_update(session); }) .then(function () { return message; }); }; Cryptobox.TOPIC = { NEW_PREKEYS: "new-prekeys", NEW_SESSION: "new-session" }; return Cryptobox; }(EventEmitter)); exports.Cryptobox = Cryptobox; Cryptobox.prototype.VERSION = __webpack_require__(23).version; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var DecryptionError_1 = __webpack_require__(2); var CryptoboxSession = (function () { function CryptoboxSession(id, pk_store, session) { this.id = id; this.pk_store = pk_store; this.session = session; Object.freeze(this); } CryptoboxSession.prototype.decrypt = function (ciphertext) { if (ciphertext.byteLength === 0) { return Promise.reject(new DecryptionError_1.DecryptionError('Cannot decrypt an empty ArrayBuffer.')); } var envelope = Proteus.message.Envelope.deserialise(ciphertext); return this.session.decrypt(this.pk_store, envelope); }; CryptoboxSession.prototype.encrypt = function (plaintext, confuse_pre_key_id) { return this.session.encrypt(plaintext, confuse_pre_key_id) .then(function (ciphertext) { return ciphertext.serialise(); }); }; CryptoboxSession.prototype.fingerprint_local = function () { return this.session.local_identity.public_key.fingerprint(); }; CryptoboxSession.prototype.fingerprint_remote = function () { return this.session.remote_identity.fingerprint(); }; return CryptoboxSession; }()); exports.CryptoboxSession = CryptoboxSession; /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var InvalidPreKeyFormatError = (function (_super) { __extends(InvalidPreKeyFormatError, _super); function InvalidPreKeyFormatError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, InvalidPreKeyFormatError.prototype); _this.name = _this.constructor.name; _this.message = message; _this.stack = new Error().stack; return _this; } return InvalidPreKeyFormatError; }(Error)); exports.InvalidPreKeyFormatError = InvalidPreKeyFormatError; /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var CryptoboxError_1 = __webpack_require__(13); exports.CryptoboxError = CryptoboxError_1.default; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var ReadOnlyStore = (function (_super) { __extends(ReadOnlyStore, _super); function ReadOnlyStore(store) { var _this = _super.call(this) || this; _this.store = store; _this.prekeys = []; return _this; } ReadOnlyStore.prototype.release_prekeys = function (deletedPreKeyIds) { var _this = this; deletedPreKeyIds.forEach(function (id) { var index = _this.prekeys.indexOf(id); if (index > -1) { _this.prekeys.splice(index, 1); } }); }; ReadOnlyStore.prototype.get_prekey = function (prekey_id) { if (this.prekeys.indexOf(prekey_id) !== -1) { return Promise.reject(new Error("PreKey \"" + prekey_id + "\" not found.")); } return this.store.load_prekey(prekey_id) .then(function (prekey) { return prekey; }); }; ReadOnlyStore.prototype.remove = function (prekey_id) { this.prekeys.push(prekey_id); return Promise.resolve(prekey_id); }; return ReadOnlyStore; }(Proteus.session.PreKeyStore)); exports.ReadOnlyStore = ReadOnlyStore; /***/ }), /* 8 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Cryptobox_1 = __webpack_require__(3); var SerialisedRecord = (function () { function SerialisedRecord(serialised, id) { this.created = Date.now(); this.id = id; this.serialised = serialised; this.version = Cryptobox_1.Cryptobox.prototype.VERSION; } return SerialisedRecord; }()); exports.SerialisedRecord = SerialisedRecord; /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var Cache = (function () { function Cache() { this.prekeys = {}; this.sessions = {}; } Cache.prototype.delete_all = function () { this.identity = undefined; this.prekeys = {}; this.sessions = {}; return Promise.resolve(true); }; Cache.prototype.delete_prekey = function (prekey_id) { delete this.prekeys[prekey_id]; return Promise.resolve(prekey_id); }; Cache.prototype.delete_session = function (session_id) { delete this.sessions[session_id]; return Promise.resolve(session_id); }; Cache.prototype.load_identity = function () { return Promise.resolve(this.identity); }; Cache.prototype.load_prekey = function (prekey_id) { var serialised = this.prekeys[prekey_id]; if (serialised) { return Promise.resolve(Proteus.keys.PreKey.deserialise(serialised)); } return Promise.resolve(undefined); }; Cache.prototype.load_prekeys = function () { var _this = this; var prekey_promises = Object .keys(this.prekeys) .map(function (key) { var prekey_id = parseInt(key, 10); return _this.load_prekey(prekey_id); }); return Promise.all(prekey_promises); }; Cache.prototype.read_session = function (identity, session_id) { var serialised = this.sessions[session_id]; if (serialised) { return Promise.resolve(Proteus.session.Session.deserialise(identity, serialised)); } return Promise.reject(new Error("Session with ID \"" + session_id + "\" not found.")); }; Cache.prototype.save_identity = function (identity) { this.identity = identity; return Promise.resolve(this.identity); }; Cache.prototype.save_prekey = function (preKey) { try { this.prekeys[preKey.key_id] = preKey.serialise(); } catch (error) { return Promise.reject(new Error("PreKey (no. " + preKey.key_id + ") serialization problem \"" + error.message + "\" at \"" + error.stack + "\".")); } return Promise.resolve(preKey); }; Cache.prototype.save_prekeys = function (preKeys) { var _this = this; var savePromises = preKeys .map(function (preKey) { return _this.save_prekey(preKey); }); return Promise.all(savePromises) .then(function () { return preKeys; }); }; Cache.prototype.create_session = function (session_id, session) { try { this.sessions[session_id] = session.serialise(); } catch (error) { return Promise.reject(new Error("Session serialization problem: \"" + error.message + "\"")); } return Promise.resolve(session); }; Cache.prototype.update_session = function (session_id, session) { return this.create_session(session_id, session); }; return Cache; }()); exports.default = Cache; /***/ }), /* 10 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(Buffer) { Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var error_1 = __webpack_require__(1); var SerialisedRecord_1 = __webpack_require__(8); var CryptoboxCRUDStore = (function () { function CryptoboxCRUDStore(engine) { this.engine = engine; } Object.defineProperty(CryptoboxCRUDStore, "KEYS", { get: function () { return { LOCAL_IDENTITY: 'local_identity' }; }, enumerable: true, configurable: true }); Object.defineProperty(CryptoboxCRUDStore, "STORES", { get: function () { return { LOCAL_IDENTITY: 'keys', PRE_KEYS: 'prekeys', SESSIONS: 'sessions' }; }, enumerable: true, configurable: true }); CryptoboxCRUDStore.prototype.from_store = function (record) { var decodedData = Buffer.from(record.serialised, 'base64'); return { created: record.created, id: record.id, serialised: new Uint8Array(decodedData).buffer, version: record.version, }; }; CryptoboxCRUDStore.prototype.to_store = function (record) { return { created: record.created, id: record.id, serialised: new Buffer(record.serialised).toString('base64'), version: record.version, }; }; CryptoboxCRUDStore.prototype.delete_all = function () { var _this = this; return Promise.resolve() .then(function () { return _this.engine.deleteAll(CryptoboxCRUDStore.STORES.LOCAL_IDENTITY); }) .then(function () { return _this.engine.deleteAll(CryptoboxCRUDStore.STORES.PRE_KEYS); }) .then(function () { return _this.engine.deleteAll(CryptoboxCRUDStore.STORES.SESSIONS); }) .then(function () { return true; }); }; CryptoboxCRUDStore.prototype.delete_prekey = function (prekey_id) { return this.engine.delete(CryptoboxCRUDStore.STORES.PRE_KEYS, prekey_id.toString()) .then(function () { return prekey_id; }); }; CryptoboxCRUDStore.prototype.load_identity = function () { var _this = this; return this.engine.read(CryptoboxCRUDStore.STORES.LOCAL_IDENTITY, CryptoboxCRUDStore.KEYS.LOCAL_IDENTITY) .then(function (payload) { var record = _this.from_store(payload); var identity = Proteus.keys.IdentityKeyPair.deserialise(record.serialised); return identity; }) .catch(function (error) { if (error instanceof error_1.RecordNotFoundError) { return undefined; } throw error; }); }; CryptoboxCRUDStore.prototype.load_prekey = function (prekey_id) { var _this = this; return this.engine.read(CryptoboxCRUDStore.STORES.PRE_KEYS, prekey_id.toString()) .then(function (payload) { var record = _this.from_store(payload); return Proteus.keys.PreKey.deserialise(record.serialised); }) .catch(function (error) { if (error instanceof error_1.RecordNotFoundError) { return undefined; } throw error; }); }; CryptoboxCRUDStore.prototype.load_prekeys = function () { var _this = this; return this.engine.readAll(CryptoboxCRUDStore.STORES.PRE_KEYS) .then(function (records) { var preKeys = []; records.forEach(function (payload) { var record = _this.from_store(payload); var preKey = Proteus.keys.PreKey.deserialise(record.serialised); preKeys.push(preKey); }); return preKeys; }); }; CryptoboxCRUDStore.prototype.save_identity = function (identity) { var record = new SerialisedRecord_1.SerialisedRecord(identity.serialise(), CryptoboxCRUDStore.KEYS.LOCAL_IDENTITY); var payload = this.to_store(record); return this.engine.create(CryptoboxCRUDStore.STORES.LOCAL_IDENTITY, record.id, payload) .then(function () { return identity; }); }; CryptoboxCRUDStore.prototype.save_prekey = function (pre_key) { var record = new SerialisedRecord_1.SerialisedRecord(pre_key.serialise(), pre_key.key_id.toString()); var payload = this.to_store(record); return this.engine.create(CryptoboxCRUDStore.STORES.PRE_KEYS, record.id, payload) .then(function () { return pre_key; }); }; CryptoboxCRUDStore.prototype.save_prekeys = function (pre_keys) { var _this = this; var promises = pre_keys.map(function (pre_key) { return _this.save_prekey(pre_key); }); return Promise.all(promises).then(function () { return pre_keys; }); }; CryptoboxCRUDStore.prototype.create_session = function (session_id, session) { var record = new SerialisedRecord_1.SerialisedRecord(session.serialise(), session_id); var payload = this.to_store(record); return this.engine.create(CryptoboxCRUDStore.STORES.SESSIONS, record.id, payload) .then(function () { return session; }); }; CryptoboxCRUDStore.prototype.read_session = function (identity, session_id) { var _this = this; return this.engine.read(CryptoboxCRUDStore.STORES.SESSIONS, session_id) .then(function (payload) { var record = _this.from_store(payload); return Proteus.session.Session.deserialise(identity, record.serialised); }); }; CryptoboxCRUDStore.prototype.update_session = function (session_id, session) { var record = new SerialisedRecord_1.SerialisedRecord(session.serialise(), session_id); var payload = this.to_store(record); return this.engine.update(CryptoboxCRUDStore.STORES.SESSIONS, record.id, { serialised: payload.serialised }) .then(function () { return session; }); }; CryptoboxCRUDStore.prototype.delete_session = function (session_id) { return this.engine.delete(CryptoboxCRUDStore.STORES.SESSIONS, session_id) .then(function (primary_key) { return primary_key; }); }; return CryptoboxCRUDStore; }()); exports.default = CryptoboxCRUDStore; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(18).Buffer)) /***/ }), /* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Proteus = __webpack_require__(0); var dexie_1 = __webpack_require__(24); var error_1 = __webpack_require__(1); var SerialisedRecord_1 = __webpack_require__(8); var IndexedDB = (function () { function IndexedDB(identifier) { var _this = this; this.prekeys = {}; this.TABLE = { LOCAL_IDENTITY: "keys", PRE_KEYS: "prekeys", SESSIONS: "sessions" }; this.localIdentityKey = 'local_identity'; if (typeof indexedDB === "undefined") { var warning = "IndexedDB isn't supported by your platform."; throw new Error(warning); } if (typeof identifier === 'string') { var schema = {}; schema[this.TABLE.LOCAL_IDENTITY] = ''; schema[this.TABLE.PRE_KEYS] = ''; schema[this.TABLE.SESSIONS] = ''; this.db = new dexie_1.default("cryptobox@" + identifier); this.db.version(1).stores(schema); } else { this.db = identifier; } this.db.on('blocked', function (event) { _this.db.close(); }); } IndexedDB.prototype.create = function (store_name, primary_key, entity) { var _this = this; return Promise.resolve() .then(function () { if (entity) { return _this.db[store_name].add(entity, primary_key); } throw new error_1.RecordTypeError("Entity is \"undefined\" or \"null\". Store name \"" + store_name + "\", Primary Key \"" + primary_key + "\"."); }); }; IndexedDB.prototype.read = function (store_name, primary_key) { var _this = this; return Promise.resolve() .then(function () { return _this.db[store_name].get(primary_key); }) .then(function (record) { if (record) { return record; } var message = "Record \"" + primary_key + "\" from object store \"" + store_name + "\" could not be found."; throw new error_1.RecordNotFoundError(message); }); }; IndexedDB.prototype.update = function (store_name, primary_key, changes) { return this.db[store_name].update(primary_key, changes); }; IndexedDB.prototype.delete = function (store_name, primary_key) { var _this = this; return Promise.resolve() .then(function () { return _this.db[store_name].delete(primary_key); }) .then(function () { return primary_key; }); }; IndexedDB.prototype.delete_all = function () { var _this = this; return Promise.resolve() .then(function () { return _this.db[_this.TABLE.LOCAL_IDENTITY].clear(); }) .then(function () { return _this.db[_this.TABLE.PRE_KEYS].clear(); }) .then(function () { return _this.db[_this.TABLE.SESSIONS].clear(); }) .then(function () { return true; }); }; IndexedDB.prototype.delete_prekey = function (prekey_id) { return this.delete(this.TABLE.PRE_KEYS, prekey_id.toString()) .then(function () { return prekey_id; }); }; IndexedDB.prototype.delete_session = function (session_id) { return this.delete(this.TABLE.SESSIONS, session_id) .then(function (primary_key) { return primary_key; }); }; IndexedDB.prototype.load_identity = function () { return this.read(this.TABLE.LOCAL_IDENTITY, this.localIdentityKey) .then(function (record) { return Proteus.keys.IdentityKeyPair.deserialise(record.serialised); }) .catch(function (error) { if (error instanceof error_1.RecordNotFoundError) { return undefined; } throw error; }); }; IndexedDB.prototype.load_prekey = function (prekey_id) { return this.read(this.TABLE.PRE_KEYS, prekey_id.toString()) .then(function (record) { return Proteus.keys.PreKey.deserialise(record.serialised); }) .catch(function (error) { if (error instanceof error_1.RecordNotFoundError) { return undefined; } throw error; }); }; IndexedDB.prototype.load_prekeys = function () { var _this = this; return Promise.resolve() .then(function () { return _this.db[_this.TABLE.PRE_KEYS].toArray(); }) .then(function (records) { return records.map(function (record) { return Proteus.keys.PreKey.deserialise(record.serialised); }); }); }; IndexedDB.prototype.read_session = function (identity, session_id) { return this.read(this.TABLE.SESSIONS, session_id) .then(function (payload) { return Proteus.session.Session.deserialise(identity, payload.serialised); }); }; IndexedDB.prototype.save_identity = function (identity) { var _this = this; var payload = new SerialisedRecord_1.SerialisedRecord(identity.serialise(), this.localIdentityKey); this.identity = identity; return this.create(this.TABLE.LOCAL_IDENTITY, payload.id, payload) .then(function (primaryKey) { var fingerprint = identity.public_key.fingerprint(); var message = "Saved local identity \"" + fingerprint + "\"" + (" with key \"" + primaryKey + "\" in object store \"" + _this.TABLE.LOCAL_IDENTITY + "\"."); return identity; }); }; IndexedDB.prototype.save_prekey = function (prekey) { var _this = this; var payload = new SerialisedRecord_1.SerialisedRecord(prekey.serialise(), prekey.key_id.toString()); this.prekeys[prekey.key_id] = prekey; return this.create(this.TABLE.PRE_KEYS, payload.id, payload) .then(function (primaryKey) { var message = "Saved PreKey (ID \"" + prekey.key_id + "\") with key \"" + primaryKey + "\" in object store \"" + _this.TABLE.PRE_KEYS + "\"."; return prekey; }); }; IndexedDB.prototype.save_prekeys = function (prekeys) { var _this = this; if (prekeys.length === 0) { return Promise.resolve(prekeys); } var items = []; var keys = prekeys.map(function (preKey) { var key = preKey.key_id.toString(); var payload = new SerialisedRecord_1.SerialisedRecord(preKey.serialise(), key); items.push(payload); return key; }); return Promise.resolve() .then(function () { return _this.db[_this.TABLE.PRE_KEYS].bulkPut(items, keys); }) .then(function () { return prekeys; }); }; IndexedDB.prototype.create_session = function (session_id, session) { var _this = this; var payload = new SerialisedRecord_1.SerialisedRecord(session.serialise(), session_id); return this.create(this.TABLE.SESSIONS, payload.id, payload) .then(function (primaryKey) { var message = "Added session ID \"" + session_id + "\" in object store \"" + _this.TABLE.SESSIONS + "\" with key \"" + primaryKey + "\"."; return session; }) .catch(function (error) { if (error instanceof dexie_1.default.ConstraintError) { var message = "Session with ID '" + session_id + "' already exists and cannot get overwritten. You need to delete the session first if you want to do it."; throw new error_1.RecordAlreadyExistsError(message); } throw error; }); }; IndexedDB.prototype.update_session = function (session_id, session) { var _this = this; var payload = new SerialisedRecord_1.SerialisedRecord(session.serialise(), session_id); return this.update(this.TABLE.SESSIONS, payload.id, { serialised: payload.serialised }) .then(function (primaryKey) { var message = "Updated session ID \"" + session_id + "\" in object store \"" + _this.TABLE.SESSIONS + "\" with key \"" + primaryKey + "\"."; return session; }); }; return IndexedDB; }()); exports.default = IndexedDB; /***/ }), /* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Cache_1 = __webpack_require__(9); var IndexedDB_1 = __webpack_require__(11); var CryptoboxCRUDStore_1 = __webpack_require__(10); var Cryptobox_1 = __webpack_require__(3); var error_1 = __webpack_require__(6); var CryptoboxSession_1 = __webpack_require__(4); var DecryptionError_1 = __webpack_require__(2); var InvalidPreKeyFormatError_1 = __webpack_require__(5); var ReadOnlyStore_1 = __webpack_require__(7); var error_2 = __webpack_require__(1); module.exports = { Cryptobox: Cryptobox_1.Cryptobox, CryptoboxSession: CryptoboxSession_1.CryptoboxSession, DecryptionError: DecryptionError_1.DecryptionError, error: { CryptoboxError: error_1.CryptoboxError, }, InvalidPreKeyFormatError: InvalidPreKeyFormatError_1.InvalidPreKeyFormatError, store: { Cache: Cache_1.default, error: { RecordAlreadyExistsError: error_2.RecordAlreadyExistsError, RecordNotFoundError: error_2.RecordNotFoundError, RecordTypeError: error_2.RecordTypeError, }, CryptoboxCRUDStore: CryptoboxCRUDStore_1.default, IndexedDB: IndexedDB_1.default, ReadOnlyStore: ReadOnlyStore_1.ReadOnlyStore, } }; /***/ }), /* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var CryptoboxError = (function (_super) { __extends(CryptoboxError, _super); function CryptoboxError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, CryptoboxError.prototype); _this.message = message; _this.name = _this.constructor.name; _this.stack = new Error().stack; return _this; } return CryptoboxError; }(Error)); exports.default = CryptoboxError; /***/ }), /* 14 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var RecordAlreadyExistsError = (function (_super) { __extends(RecordAlreadyExistsError, _super); function RecordAlreadyExistsError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, RecordAlreadyExistsError.prototype); _this.message = message; _this.name = _this.constructor.name; _this.stack = new Error().stack; return _this; } return RecordAlreadyExistsError; }(Error)); exports.default = RecordAlreadyExistsError; /***/ }), /* 15 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var RecordNotFoundError = (function (_super) { __extends(RecordNotFoundError, _super); function RecordNotFoundError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, RecordNotFoundError.prototype); _this.message = message; _this.name = _this.constructor.name; _this.stack = new Error().stack; return _this; } return RecordNotFoundError; }(Error)); exports.default = RecordNotFoundError; /***/ }), /* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var RecordTypeError = (function (_super) { __extends(RecordTypeError, _super); function RecordTypeError(message) { var _this = _super.call(this, message) || this; _this.message = message; Object.setPrototypeOf(_this, RecordTypeError.prototype); _this.message = message; _this.name = _this.constructor.name; _this.stack = new Error().stack; return _this; } return RecordTypeError; }(Error)); exports.default = RecordTypeError; /***/ }), /* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function placeHoldersCount (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 } function byteLength (b64) { // base64 is 4/3 + up to two characters of the original data return b64.length * 3 / 4 - placeHoldersCount(b64) } function toByteArray (b64) { var i, j, l, tmp, placeHolders, arr var len = b64.length placeHolders = placeHoldersCount(b64) arr = new Arr(len * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? len - 4 : len var L = 0 for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[L++] = (tmp >> 16) & 0xFF arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } if (placeHolders === 2) { tmp = (revLookup[b64.charCodeAt(i)] <