cryptobox-hd
Version:
High-level API with persistent storage for Proteus-HD.
1,339 lines (1,214 loc) • 114 kB
JavaScript
/*! 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)] <