diff --git a/.jshintrc b/.jshintrc index 485b628..db85deb 100644 --- a/.jshintrc +++ b/.jshintrc @@ -6,5 +6,6 @@ "undef": true, "typed": true, "node": true, - "esnext": true -} \ No newline at end of file + "esnext": true, + "jasmine": true +} diff --git a/.travis.yml b/.travis.yml index 897040d..20f0c0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,3 @@ language: node_js node_js: - - "0.10" -before_install: - - "npm install -g grunt-cli" - - "npm install -g bower" - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - "bower install" \ No newline at end of file + - "4.2" diff --git a/Gruntfile.js b/Gruntfile.js index 08af3c3..6053756 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,28 +1,16 @@ "use strict"; module.exports = function(grunt) { - grunt.loadNpmTasks("grunt-mocha-test"); // For server-side testing - grunt.loadNpmTasks("grunt-karma"); // For client-side testing - grunt.loadNpmTasks("grunt-pure-cjs"); + grunt.loadNpmTasks("grunt-mocha-test"); grunt.loadNpmTasks("grunt-contrib-jshint"); - grunt.loadNpmTasks("grunt-blanket"); - grunt.loadNpmTasks("grunt-contrib-clean"); - grunt.loadNpmTasks("grunt-contrib-copy"); - grunt.loadNpmTasks("grunt-traceur"); - grunt.loadNpmTasks("grunt-contrib-concat"); grunt.loadNpmTasks("grunt-jscs"); grunt.initConfig({ - clean: { - all: { - src: ["coverage/", "dist/", "build/"] - } - }, jshint: { all: { src: ["Gruntfile.js", "index.js", "src/**/*.js", "test/**/*.js"], options: { - jshintrc: true + jshintrc: ".jshintrc" } } }, @@ -31,106 +19,21 @@ module.exports = function(grunt) { src: ["index.js", "src/**/*.js", "test/**/*.js"] } }, - copy: { - coverage: { - src: ["build/test/**"], - dest: "coverage/" - } - }, - blanket: { - all: { - src: "build/src/", - dest: "coverage/build/src/" - } - }, mochaTest: { unitTests: { src: ["test/unit/**/*.js"], - options: { - require: ["mocha-traceur"] - } }, integrationTests: { src: ["test/integration/node/**/*.js"], options: { clearRequireCache: true } - }, - coverage: { - src: ["coverage/build/test/unit/**/*.js"], - options: { - reporter: "html-cov", - quiet: true, - captureFile: "coverage/index.html", - clearRequireCache: true - } - } - }, - karma: { - integrationTests: { - options: { - configFile: "karma.conf.js" - } - } - }, - pure_cjs: { - dist: { - files: { - "build/axolotl.js": ["build/index.js"] - }, - options: { - exports: "axolotl", - external: { - protobufjs: { - global: "dcodeIO.ProtoBuf", - id: "__external_1" - }, - "traceur/bin/traceur-runtime": { - amd: "traceur-runtime", - global: "1", - id: "__external_2" - }, - "axolotl-crypto": { - global: "axolotlCrypto" - } - } - } - } - }, - traceur: { - dist: { - options: { - modules: "commonjs" - }, - files: [{ - expand: true, - cwd: "src/", - src: ["**/*.js"], - dest: "build/src" - }, { - src: ["index.js"], - dest: "build/index.js" - }, { - expand: true, - cwd: "test/", - src: ["**/*.js"], - dest: "build/test" - }] - } - }, - concat: { - dist: { - src: ["banner.js", "build/axolotl.js"], - dest: "dist/axolotl.js" } } }); - grunt.registerTask("coverage", ["traceur", "copy:coverage", "blanket", "mochaTest:coverage"]); - grunt.registerTask("check", ["jshint", "jscs"]); - grunt.registerTask("test", ["clean", "check", "mochaTest:unitTests"]); + grunt.registerTask("test", ["check", "mochaTest:unitTests"]); grunt.registerTask("default", ["test"]); - grunt.registerTask("dist", ["default", "traceur", "pure_cjs", "concat"]); - grunt.registerTask("integration-test", ["dist", "mochaTest:integrationTests", "karma:integrationTests"]); -}; \ No newline at end of file + grunt.registerTask("integration-test", ["mochaTest:integrationTests"]); +}; diff --git a/banner.js b/banner.js deleted file mode 100644 index 0943751..0000000 --- a/banner.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (C) 2015 Joe Bandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ diff --git a/bower.json b/bower.json deleted file mode 100644 index ced2275..0000000 --- a/bower.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "axolotl", - "main": "dist/axolotl.js", - "version": "1.3.0", - "authors": [ - "Joe Bandenburg " - ], - "description": "An independent JavaScript implementation of Axolotl. Axolotl is a ratcheting forward secrecy protocol.", - "moduleType": [ - "amd", - "globals", - "node" - ], - "keywords": [ - "axolotl", - "textsecure" - ], - "license": "LGPLv3", - "ignore": [ - "build", - "src", - "test", - "protobuf", - ".travis.yml", - "Gruntfile.js", - "index.js", - "banner.js", - "package.json", - ".travis.yml", - ".jshintrc", - ".jscsrc", - ".gitignore", - "node_modules" - ], - "dependencies": { - "protobuf": "~3.8.2", - "traceur-runtime": "~0.0.83", - "axolotl-crypto": "~1.1.0" - } -} diff --git a/dist/axolotl.js b/dist/axolotl.js deleted file mode 100644 index c44ea6b..0000000 --- a/dist/axolotl.js +++ /dev/null @@ -1,2388 +0,0 @@ -/** - * Copyright (C) 2015 Joe Bandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -(function (factory) { - if (typeof define === 'function' && define.amd) { - define([ - 'protobufjs', - 'traceur-runtime', - 'axolotl-crypto' - ], factory); - } else if (typeof exports === 'object') { - module.exports = factory(require('protobufjs'), require('traceur/bin/traceur-runtime'), require('axolotl-crypto')); - } else { - this.axolotl = factory(dcodeIO.ProtoBuf, 1, axolotlCrypto); - } -}(function (__external_1, __external_2, __external_axolotlCrypto) { - var global = this, define; - function _require(id) { - var module = _require.cache[id]; - if (!module) { - var exports = {}; - module = _require.cache[id] = { - id: id, - exports: exports - }; - _require.modules[id].call(exports, module, exports); - } - return module.exports; - } - _require.cache = []; - _require.modules = [ - function (module, exports) { - 'use strict'; - var $__src_47_Axolotl__, $__axolotl_45_crypto__; - var Axolotl = ($__src_47_Axolotl__ = _require(2), $__src_47_Axolotl__ && $__src_47_Axolotl__.__esModule && $__src_47_Axolotl__ || { default: $__src_47_Axolotl__ }).default; - var axolotlCrypto = ($__axolotl_45_crypto__ = _require(17), $__axolotl_45_crypto__ && $__axolotl_45_crypto__.__esModule && $__axolotl_45_crypto__ || { default: $__axolotl_45_crypto__ }).default; - module.exports = function (store) { - return new Axolotl(axolotlCrypto, store); - }; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__default = { - areEqual: function (left, right) { - if (left.byteLength !== right.byteLength) { - return false; - } - var leftView = new Uint8Array(left); - var rightView = new Uint8Array(right); - for (var i = 0; i < left.byteLength; i++) { - if (leftView[i] !== rightView[i]) { - return false; - } - } - return true; - }, - concat: function () { - for (var buffers = [], $__0 = 0; $__0 < arguments.length; $__0++) - buffers[$__0] = arguments[$__0]; - buffers = buffers.length === 1 ? buffers[0] : buffers; - var i; - var byteLength = 0; - for (i = 0; i < buffers.length; i++) { - byteLength += buffers[i].byteLength; - } - var newBuffer = new ArrayBuffer(byteLength); - var view = new Uint8Array(newBuffer); - var offset = 0; - for (i = 0; i < buffers.length; i++) { - view.set(new Uint8Array(buffers[i]), offset); - offset += buffers[i].byteLength; - } - return newBuffer; - }, - fromByte: function (byte) { - return new Uint8Array([byte]).buffer; - }, - stringify: function (buffer) { - var string = ''; - var view = new Uint8Array(buffer); - for (var i = 0; i < buffer.byteLength; i++) { - var byte = view[i].toString(16); - if (byte.length === 1) { - string += '0'; - } - string += byte; - } - return string; - }, - parse: function (string) { - var buffer = new ArrayBuffer(string.length / 2); - var view = new Uint8Array(buffer); - for (var i = 0; i < string.length; i += 2) { - view[i / 2] = parseInt(string[i], 16) * 16 + parseInt(string[i + 1], 16); - } - return buffer; - } - }; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__SessionFactory__, $__SessionCipher__, $__Exceptions__, $__Store__, $__Crypto__, $__co__, $__axolotl_45_crypto__; - var SessionFactory = ($__SessionFactory__ = _require(13), $__SessionFactory__ && $__SessionFactory__.__esModule && $__SessionFactory__ || { default: $__SessionFactory__ }).default; - var SessionCipher = ($__SessionCipher__ = _require(12), $__SessionCipher__ && $__SessionCipher__.__esModule && $__SessionCipher__ || { default: $__SessionCipher__ }).default; - var InvalidMessageException = ($__Exceptions__ = _require(5), $__Exceptions__ && $__Exceptions__.__esModule && $__Exceptions__ || { default: $__Exceptions__ }).InvalidMessageException; - var Store = ($__Store__ = _require(15), $__Store__ && $__Store__.__esModule && $__Store__ || { default: $__Store__ }).default; - var Crypto = ($__Crypto__ = _require(4), $__Crypto__ && $__Crypto__.__esModule && $__Crypto__ || { default: $__Crypto__ }).default; - var co = ($__co__ = _require(18), $__co__ && $__co__.__esModule && $__co__ || { default: $__co__ }).default; - var axolotlCrypto = ($__axolotl_45_crypto__ = _require(17), $__axolotl_45_crypto__ && $__axolotl_45_crypto__.__esModule && $__axolotl_45_crypto__ || { default: $__axolotl_45_crypto__ }).default; - function Axolotl(crypto, store) { - var self = this; - var wrappedStore = new Store(store); - var wrappedCrypto = new Crypto(crypto); - var sessionFactory = new SessionFactory(wrappedCrypto, wrappedStore); - var sessionCipher = new SessionCipher(wrappedCrypto); - this.generateIdentityKeyPair = function () { - return wrappedCrypto.generateKeyPair(); - }; - this.generateRegistrationId = co.wrap($traceurRuntime.initGeneratorFunction(function $__9(extendedRange) { - var upperLimit, bytes, number; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - upperLimit = extendedRange ? 2147483646 : 16380; - $ctx.state = 8; - break; - case 8: - $ctx.state = 2; - return wrappedCrypto.randomBytes(4); - case 2: - bytes = $ctx.sent; - $ctx.state = 4; - break; - case 4: - number = new Uint32Array(bytes)[0]; - $ctx.state = 10; - break; - case 10: - $ctx.returnValue = number % upperLimit + 1; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__9, this); - })); - this.generatePreKeys = co.wrap($traceurRuntime.initGeneratorFunction(function $__10(start, count) { - var results, i, $__11, $__12, $__13, $__14, $__15, $__16; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - results = []; - start--; - $ctx.state = 15; - break; - case 15: - i = 0; - $ctx.state = 11; - break; - case 11: - $ctx.state = i < count ? 5 : 9; - break; - case 8: - i++; - $ctx.state = 11; - break; - case 5: - $__11 = results.push; - $__12 = wrappedCrypto.generateKeyPair; - $__13 = $__12.call(wrappedCrypto); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__13; - case 2: - $__14 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__15 = { - id: (start + i) % 16777214 + 1, - keyPair: $__14 - }; - $__16 = $__11.call(results, $__15); - $ctx.state = 8; - break; - case 9: - $ctx.returnValue = results; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__10, this); - })); - this.generateLastResortPreKey = co.wrap($traceurRuntime.initGeneratorFunction(function $__17() { - var $__18, $__19, $__20, $__21; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__18 = wrappedCrypto.generateKeyPair; - $__19 = $__18.call(wrappedCrypto); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__19; - case 2: - $__20 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__21 = { - id: 16777215, - keyPair: $__20 - }; - $ctx.state = 8; - break; - case 8: - $ctx.returnValue = $__21; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__17, this); - })); - this.generateSignedPreKey = co.wrap($traceurRuntime.initGeneratorFunction(function $__22(identityKeyPair, signedPreKeyId) { - var keyPair, signature; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return wrappedCrypto.generateKeyPair(); - case 2: - keyPair = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return wrappedCrypto.sign(identityKeyPair.private, keyPair.public); - case 6: - signature = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $ctx.returnValue = { - id: signedPreKeyId, - keyPair: keyPair, - signature: signature - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__22, this); - })); - this.createSessionFromPreKeyBundle = sessionFactory.createSessionFromPreKeyBundle; - this.encryptMessage = sessionCipher.encryptMessage; - this.decryptWhisperMessage = sessionCipher.decryptWhisperMessage; - this.decryptPreKeyWhisperMessage = co.wrap($traceurRuntime.initGeneratorFunction(function $__23(session, preKeyWhisperMessageBytes) { - var $__7, newSession, identityKey, registrationId, $__8, finalSession, message, $__24, $__25, $__26, $__27, $__28, $__29, $__30, $__31, $__32, $__33, $__34; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__24 = sessionFactory.createSessionFromPreKeyWhisperMessage; - $__25 = $__24.call(sessionFactory, session, preKeyWhisperMessageBytes); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__25; - case 2: - $__26 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__7 = $__26; - $__27 = $__7.session; - newSession = $__27; - $__28 = $__7.identityKey; - identityKey = $__28; - $__29 = $__7.registrationId; - registrationId = $__29; - $ctx.state = 8; - break; - case 8: - $__30 = sessionCipher.decryptPreKeyWhisperMessage; - $__31 = $__30.call(sessionCipher, newSession, preKeyWhisperMessageBytes); - $ctx.state = 14; - break; - case 14: - $ctx.state = 10; - return $__31; - case 10: - $__32 = $ctx.sent; - $ctx.state = 12; - break; - case 12: - $__8 = $__32; - $__33 = $__8.session; - finalSession = $__33; - $__34 = $__8.message; - message = $__34; - $ctx.state = 16; - break; - case 16: - $ctx.returnValue = { - message: message, - session: finalSession, - identityKey: identityKey, - registrationId: registrationId - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__23, this); - })); - Object.freeze(self); - } - var $__default = Axolotl; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var Chain = function Chain(key) { - this.key = key; - this.index = 0; - this.messageKeys = []; - Object.seal(this); - }; - $traceurRuntime.createClass(Chain, {}, {}); - var $__default = Chain; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__PromiseInterfaceDecorator__; - var PromiseInterfaceDecorator = ($__PromiseInterfaceDecorator__ = _require(8), $__PromiseInterfaceDecorator__ && $__PromiseInterfaceDecorator__.__esModule && $__PromiseInterfaceDecorator__ || { default: $__PromiseInterfaceDecorator__ }).default; - var methodNames = [ - 'generateKeyPair', - 'calculateAgreement', - 'randomBytes', - 'sign', - 'verifySignature', - 'hmac', - 'encrypt', - 'decrypt' - ]; - var Crypto = function Crypto(crypto) { - $traceurRuntime.superConstructor($Crypto).call(this, crypto, methodNames); - }; - var $Crypto = Crypto; - $traceurRuntime.createClass(Crypto, {}, {}, PromiseInterfaceDecorator); - var $__default = Crypto; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - InvalidMessageException: { - get: function () { - return InvalidMessageException; - } - }, - DuplicateMessageException: { - get: function () { - return DuplicateMessageException; - } - }, - InvalidKeyException: { - get: function () { - return InvalidKeyException; - } - }, - UnsupportedProtocolVersionException: { - get: function () { - return UnsupportedProtocolVersionException; - } - }, - UntrustedIdentityException: { - get: function () { - return UntrustedIdentityException; - } - }, - __esModule: { value: true } - }); - var InvalidMessageException = function InvalidMessageException() { - $traceurRuntime.superConstructor($InvalidMessageException).apply(this, arguments); - }; - var $InvalidMessageException = InvalidMessageException; - $traceurRuntime.createClass(InvalidMessageException, {}, {}, Error); - var DuplicateMessageException = function DuplicateMessageException() { - $traceurRuntime.superConstructor($DuplicateMessageException).apply(this, arguments); - }; - var $DuplicateMessageException = DuplicateMessageException; - $traceurRuntime.createClass(DuplicateMessageException, {}, {}, Error); - var InvalidKeyException = function InvalidKeyException() { - $traceurRuntime.superConstructor($InvalidKeyException).apply(this, arguments); - }; - var $InvalidKeyException = InvalidKeyException; - $traceurRuntime.createClass(InvalidKeyException, {}, {}, Error); - var UnsupportedProtocolVersionException = function UnsupportedProtocolVersionException() { - $traceurRuntime.superConstructor($UnsupportedProtocolVersionException).apply(this, arguments); - }; - var $UnsupportedProtocolVersionException = UnsupportedProtocolVersionException; - $traceurRuntime.createClass(UnsupportedProtocolVersionException, {}, {}, Error); - var UntrustedIdentityException = function UntrustedIdentityException() { - $traceurRuntime.superConstructor($UntrustedIdentityException).apply(this, arguments); - }; - var $UntrustedIdentityException = UntrustedIdentityException; - $traceurRuntime.createClass(UntrustedIdentityException, {}, {}, Error); - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__ArrayBufferUtils__, $__co__; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var co = ($__co__ = _require(18), $__co__ && $__co__.__esModule && $__co__ || { default: $__co__ }).default; - var hashOutputSize = 32; - var iterationStartOffset = 1; - function HKDF(crypto) { - var self = this; - var extract = function (salt, inputKeyMaterial) { - return crypto.hmac(salt, inputKeyMaterial); - }; - var expand = co.wrap($traceurRuntime.initGeneratorFunction(function $__2(prk, info, outputByteCount) { - var iterations, mixin, result, remainingBytes, i, inputBytes, stepResultArray, stepResult, stepSize, stepSlice; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - iterations = Math.ceil(outputByteCount / hashOutputSize); - mixin = new ArrayBuffer(0); - result = new Uint8Array(outputByteCount); - remainingBytes = outputByteCount; - $ctx.state = 15; - break; - case 15: - i = iterationStartOffset; - $ctx.state = 11; - break; - case 11: - $ctx.state = i < iterations + iterationStartOffset ? 5 : 9; - break; - case 8: - i++; - $ctx.state = 11; - break; - case 5: - inputBytes = ArrayBufferUtils.concat(mixin, info, new Uint8Array([i]).buffer); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return crypto.hmac(prk, inputBytes); - case 2: - stepResultArray = $ctx.sent; - $ctx.state = 4; - break; - case 4: - stepResult = new Uint8Array(stepResultArray); - stepSize = Math.min(remainingBytes, stepResult.length); - stepSlice = stepResult.subarray(0, stepSize); - result.set(stepSlice, outputByteCount - remainingBytes); - mixin = stepResultArray; - remainingBytes -= stepSize; - $ctx.state = 8; - break; - case 9: - $ctx.returnValue = result.buffer; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__2, this); - })); - self.deriveSecretsWithSalt = co.wrap($traceurRuntime.initGeneratorFunction(function $__3(inputKeyMaterial, salt, info, outputByteCount) { - var prk, $__4, $__5; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return extract(salt, inputKeyMaterial); - case 2: - prk = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__4 = expand(prk, info, outputByteCount); - $ctx.state = 10; - break; - case 10: - $ctx.state = 6; - return $__4; - case 6: - $__5 = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $ctx.returnValue = $__5; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__3, this); - })); - self.deriveSecrets = function (inputKeyMaterial, info, outputByteCount) { - return self.deriveSecretsWithSalt(inputKeyMaterial, new ArrayBuffer(hashOutputSize), info, outputByteCount); - }; - Object.freeze(self); - } - var $__default = HKDF; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__WhisperProtos__, $__ProtocolConstants__, $__ArrayBufferUtils__; - var WhisperProtos = ($__WhisperProtos__ = _require(16), $__WhisperProtos__ && $__WhisperProtos__.__esModule && $__WhisperProtos__ || { default: $__WhisperProtos__ }).default; - var ProtocolConstants = ($__ProtocolConstants__ = _require(9), $__ProtocolConstants__ && $__ProtocolConstants__.__esModule && $__ProtocolConstants__ || { default: $__ProtocolConstants__ }).default; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var getVersionField = function (version) { - return ArrayBufferUtils.fromByte((version.current << 4 | version.max) & 255); - }; - var extractMessageVersion = function (versionByte) { - var view = new Uint8Array(versionByte); - return { - current: view[0] >> 4 & 15, - max: view[0] & 15 - }; - }; - var toArrayBuffer = function (obj, key) { - if (obj[key]) { - obj[key] = obj[key].toArrayBuffer(); - } - }; - var encodeWhisperMessageMacInput = function (whisperMessage) { - var versionByte = getVersionField(whisperMessage.version); - var messageBytes = new WhisperProtos.WhisperMessage(whisperMessage.message).encode().toArrayBuffer(); - return ArrayBufferUtils.concat(versionByte, messageBytes); - }; - var $__default = { - decodeWhisperMessage: function (whisperMessageBytes) { - var messageBytes = whisperMessageBytes.slice(1, -ProtocolConstants.macByteCount); - var message = WhisperProtos.WhisperMessage.decode(messageBytes); - toArrayBuffer(message, 'ratchetKey'); - toArrayBuffer(message, 'ciphertext'); - return { - version: extractMessageVersion(whisperMessageBytes.slice(0, 1)), - message: message, - mac: whisperMessageBytes.slice(-ProtocolConstants.macByteCount) - }; - }, - decodeWhisperMessageMacInput: function (whisperMessageBytes) { - return whisperMessageBytes.slice(0, -ProtocolConstants.macByteCount); - }, - encodeWhisperMessage: function (whisperMessage) { - return ArrayBufferUtils.concat(encodeWhisperMessageMacInput(whisperMessage), whisperMessage.mac); - }, - encodeWhisperMessageMacInput: encodeWhisperMessageMacInput, - decodePreKeyWhisperMessage: function (preKeyWhisperMessageBytes) { - var message = WhisperProtos.PreKeyWhisperMessage.decode(preKeyWhisperMessageBytes.slice(1)); - toArrayBuffer(message, 'message'); - toArrayBuffer(message, 'baseKey'); - toArrayBuffer(message, 'identityKey'); - return { - version: extractMessageVersion(preKeyWhisperMessageBytes.slice(0, 1)), - message: message - }; - }, - encodePreKeyWhisperMessage: function (preKeyWhisperMessage) { - var message = preKeyWhisperMessage.message; - var messageBytes = new WhisperProtos.PreKeyWhisperMessage(message).encode().toArrayBuffer(); - var versionField = getVersionField(preKeyWhisperMessage.version); - return ArrayBufferUtils.concat(versionField, messageBytes); - } - }; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var wrap = function (fn) { - return function () { - return Promise.resolve(fn.apply(this, arguments)); - }; - }; - var PromiseInterfaceDecorator = function PromiseInterfaceDecorator(impl, methodNames) { - var $__0 = this; - methodNames.forEach(function (methodName) { - if (!impl[methodName]) { - throw new Error('interface must implement ' + methodName); - } - $__0[methodName] = wrap(impl[methodName]); - }); - Object.freeze(this); - }; - $traceurRuntime.createClass(PromiseInterfaceDecorator, {}, {}); - var $__default = PromiseInterfaceDecorator; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__default = { - currentVersion: 3, - macByteCount: 8, - cipherKeyByteCount: 32, - macKeyByteCount: 32, - ivByteCount: 16, - dhKeyByteCount: 32, - rootKeyByteCount: 32, - chainKeyByteCount: 32, - maximumRetainedReceivedChainKeys: 5, - maximumMissedMessages: 2000, - maximumSessionStatesPerIdentity: 40 - }; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__HKDF__, $__Chain__, $__ArrayBufferUtils__, $__ProtocolConstants__, $__co__; - var HKDF = ($__HKDF__ = _require(6), $__HKDF__ && $__HKDF__.__esModule && $__HKDF__ || { default: $__HKDF__ }).default; - var Chain = ($__Chain__ = _require(3), $__Chain__ && $__Chain__.__esModule && $__Chain__ || { default: $__Chain__ }).default; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var ProtocolConstants = ($__ProtocolConstants__ = _require(9), $__ProtocolConstants__ && $__ProtocolConstants__.__esModule && $__ProtocolConstants__ || { default: $__ProtocolConstants__ }).default; - var co = ($__co__ = _require(18), $__co__ && $__co__.__esModule && $__co__ || { default: $__co__ }).default; - var messageKeySeed = 1; - var chainKeySeed = 2; - var whisperMessageKeys = new Uint8Array([ - 87, - 104, - 105, - 115, - 112, - 101, - 114, - 77, - 101, - 115, - 115, - 97, - 103, - 101, - 75, - 101, - 121, - 115 - ]).buffer; - var whisperRatchet = new Uint8Array([ - 87, - 104, - 105, - 115, - 112, - 101, - 114, - 82, - 97, - 116, - 99, - 104, - 101, - 116 - ]).buffer; - var whisperText = new Uint8Array([ - 87, - 104, - 105, - 115, - 112, - 101, - 114, - 84, - 101, - 120, - 116 - ]).buffer; - var discontinuityBytes = new Uint8Array([ - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255 - ]).buffer; - function Ratchet(crypto) { - var self = this; - var hkdf = new HKDF(crypto); - this.deriveInitialRootKeyAndChain = co.wrap($traceurRuntime.initGeneratorFunction(function $__5(sessionVersion, agreements) { - var secrets, masterSecret, derivedSecret; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - secrets = []; - if (sessionVersion >= 3) { - secrets.push(discontinuityBytes); - } - secrets = secrets.concat(agreements); - masterSecret = ArrayBufferUtils.concat(secrets); - $ctx.state = 8; - break; - case 8: - $ctx.state = 2; - return hkdf.deriveSecrets(masterSecret, whisperText, ProtocolConstants.rootKeyByteCount + ProtocolConstants.chainKeyByteCount); - case 2: - derivedSecret = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = { - rootKey: derivedSecret.slice(0, ProtocolConstants.rootKeyByteCount), - chain: new Chain(derivedSecret.slice(ProtocolConstants.rootKeyByteCount)) - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__5, this); - })); - this.deriveNextRootKeyAndChain = co.wrap($traceurRuntime.initGeneratorFunction(function $__6(rootKey, theirEphemeralPublicKey, ourEphemeralPrivateKey) { - var sharedSecret, derivedSecretBytes; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return crypto.calculateAgreement(theirEphemeralPublicKey, ourEphemeralPrivateKey); - case 2: - sharedSecret = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return hkdf.deriveSecretsWithSalt(sharedSecret, rootKey, whisperRatchet, ProtocolConstants.rootKeyByteCount + ProtocolConstants.chainKeyByteCount); - case 6: - derivedSecretBytes = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $ctx.returnValue = { - rootKey: derivedSecretBytes.slice(0, ProtocolConstants.rootKeyByteCount), - chain: new Chain(derivedSecretBytes.slice(ProtocolConstants.rootKeyByteCount)) - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__6, this); - })); - this.clickSubRatchet = co.wrap($traceurRuntime.initGeneratorFunction(function $__7(chain) { - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - chain.index++; - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return deriveNextChainKey(chain.key); - case 2: - chain.key = $ctx.sent; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__7, this); - })); - this.deriveMessageKeys = co.wrap($traceurRuntime.initGeneratorFunction(function $__8(chainKey) { - var messageKey, keyMaterialBytes, cipherKeyBytes, macKeyBytes, ivBytes; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return deriveMessageKey(chainKey); - case 2: - messageKey = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return hkdf.deriveSecrets(messageKey, whisperMessageKeys, ProtocolConstants.cipherKeyByteCount + ProtocolConstants.macKeyByteCount + ProtocolConstants.ivByteCount); - case 6: - keyMaterialBytes = $ctx.sent; - $ctx.state = 8; - break; - case 8: - cipherKeyBytes = keyMaterialBytes.slice(0, ProtocolConstants.cipherKeyByteCount); - macKeyBytes = keyMaterialBytes.slice(ProtocolConstants.cipherKeyByteCount, ProtocolConstants.cipherKeyByteCount + ProtocolConstants.macKeyByteCount); - ivBytes = keyMaterialBytes.slice(ProtocolConstants.cipherKeyByteCount + ProtocolConstants.macKeyByteCount); - $ctx.state = 12; - break; - case 12: - $ctx.returnValue = { - cipherKey: cipherKeyBytes, - macKey: macKeyBytes, - iv: ivBytes - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__8, this); - })); - var hmacByte = co.wrap($traceurRuntime.initGeneratorFunction(function $__9(key, byte) { - var $__10, $__11, $__12, $__13, $__14; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__10 = crypto.hmac; - $__11 = ArrayBufferUtils.fromByte; - $__12 = $__11.call(ArrayBufferUtils, byte); - $__13 = $__10.call(crypto, key, $__12); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__13; - case 2: - $__14 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = $__14; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__9, this); - })); - var deriveMessageKey = co.wrap($traceurRuntime.initGeneratorFunction(function $__15(chainKey) { - var $__16, $__17; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__16 = hmacByte(chainKey, messageKeySeed); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__16; - case 2: - $__17 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = $__17; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__15, this); - })); - var deriveNextChainKey = co.wrap($traceurRuntime.initGeneratorFunction(function $__18(chainKey) { - var $__19, $__20; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__19 = hmacByte(chainKey, chainKeySeed); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__19; - case 2: - $__20 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = $__20; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__18, this); - })); - } - var $__default = Ratchet; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__ProtocolConstants__, $__ArrayBufferUtils__, $__SessionState__; - var ProtocolConstants = ($__ProtocolConstants__ = _require(9), $__ProtocolConstants__ && $__ProtocolConstants__.__esModule && $__ProtocolConstants__ || { default: $__ProtocolConstants__ }).default; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var SessionState = ($__SessionState__ = _require(14), $__SessionState__ && $__SessionState__.__esModule && $__SessionState__ || { default: $__SessionState__ }).default; - var Session = function Session(session) { - this.states = []; - if (session) { - for (var $__4 = session.states[$traceurRuntime.toProperty(Symbol.iterator)](), $__5 = void 0; !($__5 = $__4.next()).done;) { - var state = $__5.value; - { - this.states.push(new SessionState(state)); - } - } - } - Object.seal(this); - }; - $traceurRuntime.createClass(Session, { - mostRecentState: function () { - return this.states[0]; - }, - addState: function (state) { - this.states.unshift(state); - if (this.states.length > ProtocolConstants.maximumSessionStatesPerIdentity) { - this.states.pop(); - } - }, - removeState: function (state) { - var index = this.states.indexOf(state); - this.states.splice(index, 1); - } - }, {}); - var $__default = Session; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__ArrayBufferUtils__, $__ProtocolConstants__, $__Messages__, $__SessionState__, $__Session__, $__Ratchet__, $__Exceptions__, $__co__; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var ProtocolConstants = ($__ProtocolConstants__ = _require(9), $__ProtocolConstants__ && $__ProtocolConstants__.__esModule && $__ProtocolConstants__ || { default: $__ProtocolConstants__ }).default; - var Messages = ($__Messages__ = _require(7), $__Messages__ && $__Messages__.__esModule && $__Messages__ || { default: $__Messages__ }).default; - var SessionState = ($__SessionState__ = _require(14), $__SessionState__ && $__SessionState__.__esModule && $__SessionState__ || { default: $__SessionState__ }).default; - var Session = ($__Session__ = _require(11), $__Session__ && $__Session__.__esModule && $__Session__ || { default: $__Session__ }).default; - var Ratchet = ($__Ratchet__ = _require(10), $__Ratchet__ && $__Ratchet__.__esModule && $__Ratchet__ || { default: $__Ratchet__ }).default; - var $__6 = ($__Exceptions__ = _require(5), $__Exceptions__ && $__Exceptions__.__esModule && $__Exceptions__ || { default: $__Exceptions__ }), InvalidMessageException = $__6.InvalidMessageException, DuplicateMessageException = $__6.DuplicateMessageException; - var co = ($__co__ = _require(18), $__co__ && $__co__.__esModule && $__co__ || { default: $__co__ }).default; - function SessionCipher(crypto) { - var self = this; - var ratchet = new Ratchet(crypto); - this.encryptMessage = co.wrap($traceurRuntime.initGeneratorFunction(function $__12(session, message) { - var newSession, whisperMessage; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - newSession = new Session(session); - $ctx.state = 15; - break; - case 15: - $ctx.state = 2; - return createWhisperMessage(newSession, message); - case 2: - whisperMessage = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return ratchet.clickSubRatchet(newSession.mostRecentState().sendingChain); - case 6: - $ctx.maybeThrow(); - $ctx.state = 8; - break; - case 8: - $ctx.state = newSession.mostRecentState().pendingPreKey ? 9 : 11; - break; - case 9: - $ctx.returnValue = { - isPreKeyWhisperMessage: true, - body: createPreKeyWhisperMessage(newSession, whisperMessage), - session: newSession - }; - $ctx.state = -2; - break; - case 11: - $ctx.returnValue = { - isPreKeyWhisperMessage: false, - body: whisperMessage, - session: newSession - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__12, this); - })); - this.decryptPreKeyWhisperMessage = function (session, preKeyWhisperMessageBytes) { - var preKeyWhisperMessage = Messages.decodePreKeyWhisperMessage(preKeyWhisperMessageBytes); - return self.decryptWhisperMessage(session, preKeyWhisperMessage.message.message); - }; - this.decryptWhisperMessage = co.wrap($traceurRuntime.initGeneratorFunction(function $__13(session, whisperMessageBytes) { - var newSession, exceptions, $__8, $__9, state, clonedSessionState, promise, result, messages; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - newSession = new Session(session); - exceptions = []; - $ctx.state = 17; - break; - case 17: - $__8 = newSession.states[$traceurRuntime.toProperty(Symbol.iterator)](), $__9 = void 0; - $ctx.state = 6; - break; - case 6: - $ctx.state = !($__9 = $__8.next()).done ? 12 : 14; - break; - case 12: - state = $__9.value; - $ctx.state = 13; - break; - case 13: - clonedSessionState = new SessionState(state); - promise = decryptWhisperMessageWithSessionState(clonedSessionState, whisperMessageBytes); - $ctx.state = 11; - break; - case 11: - $ctx.state = 2; - return promise.catch(function (e) { - exceptions.push(e); - }); - case 2: - result = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = result !== undefined ? 7 : 6; - break; - case 7: - newSession.removeState(state); - newSession.addState(clonedSessionState); - $ctx.state = 8; - break; - case 8: - $ctx.returnValue = { - message: result, - session: newSession - }; - $ctx.state = -2; - break; - case 14: - messages = exceptions.map(function (e) { - return e.toString(); - }); - throw new InvalidMessageException('Unable to decrypt message: ' + messages); - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__13, this); - })); - var decryptWhisperMessageWithSessionState = co.wrap($traceurRuntime.initGeneratorFunction(function $__14(sessionState, whisperMessageBytes) { - var whisperMessage, macInputTypes, message, theirEphemeralPublicKey, receivingChain, messageKeys, isValid, plaintext; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - whisperMessage = Messages.decodeWhisperMessage(whisperMessageBytes); - macInputTypes = Messages.decodeWhisperMessageMacInput(whisperMessageBytes); - if (whisperMessage.version.current !== sessionState.sessionVersion) { - throw new InvalidMessageException('Message version doesn\'t match session version'); - } - message = whisperMessage.message; - theirEphemeralPublicKey = message.ratchetKey; - $ctx.state = 20; - break; - case 20: - $ctx.state = 2; - return getOrCreateReceivingChain(sessionState, theirEphemeralPublicKey); - case 2: - receivingChain = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return getOrCreateMessageKeys(theirEphemeralPublicKey, receivingChain, message.counter); - case 6: - messageKeys = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $ctx.state = 10; - return isValidMac(macInputTypes, messageKeys.macKey, whisperMessage.version.current, sessionState.remoteIdentityKey, sessionState.localIdentityKey, whisperMessage.mac); - case 10: - isValid = $ctx.sent; - $ctx.state = 12; - break; - case 12: - if (!isValid) { - throw new InvalidMessageException('Bad mac'); - } - $ctx.state = 22; - break; - case 22: - $ctx.state = 14; - return crypto.decrypt(messageKeys.cipherKey, message.ciphertext, messageKeys.iv); - case 14: - plaintext = $ctx.sent; - $ctx.state = 16; - break; - case 16: - sessionState.pendingPreKey = null; - $ctx.state = 24; - break; - case 24: - $ctx.returnValue = plaintext; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__14, this); - })); - var isValidMac = co.wrap($traceurRuntime.initGeneratorFunction(function $__15(data, macKey, messageVersion, senderIdentityKey, receiverIdentityKey, theirMac) { - var ourMac; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return getMac(data, macKey, messageVersion, senderIdentityKey, receiverIdentityKey); - case 2: - ourMac = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = ArrayBufferUtils.areEqual(ourMac, theirMac); - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__15, this); - })); - var getMac = co.wrap($traceurRuntime.initGeneratorFunction(function $__16(data, macKey, messageVersion, senderIdentityKey, receiverIdentityKey) { - var macInputs, macBytes; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - macInputs = messageVersion >= 3 ? [ - senderIdentityKey, - receiverIdentityKey - ] : []; - macInputs.push(data); - $ctx.state = 8; - break; - case 8: - $ctx.state = 2; - return crypto.hmac(macKey, ArrayBufferUtils.concat(macInputs)); - case 2: - macBytes = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = macBytes.slice(0, ProtocolConstants.macByteCount); - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__16, this); - })); - var createWhisperMessage = co.wrap($traceurRuntime.initGeneratorFunction(function $__17(session, paddedMessage) { - var messageKeys, ciphertext, version, message, macInputBytes, $__18, $__19, $__20, $__21, $__22, $__23, $__24, $__25, $__26, $__27, $__28, $__29, $__30, $__31, $__32; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return ratchet.deriveMessageKeys(session.mostRecentState().sendingChain.key); - case 2: - messageKeys = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $ctx.state = 6; - return crypto.encrypt(messageKeys.cipherKey, paddedMessage, messageKeys.iv); - case 6: - ciphertext = $ctx.sent; - $ctx.state = 8; - break; - case 8: - version = { - current: session.mostRecentState().sessionVersion, - max: ProtocolConstants.currentVersion - }; - message = { - ratchetKey: session.mostRecentState().senderRatchetKeyPair.public, - counter: session.mostRecentState().sendingChain.index, - previousCounter: session.mostRecentState().previousCounter, - ciphertext: ciphertext - }; - macInputBytes = Messages.encodeWhisperMessageMacInput({ - version: version, - message: message - }); - $ctx.state = 20; - break; - case 20: - $__18 = Messages.encodeWhisperMessage; - $__19 = messageKeys.macKey; - $__20 = session.mostRecentState; - $__21 = $__20.call(session); - $__22 = $__21.sessionVersion; - $__23 = session.mostRecentState; - $__24 = $__23.call(session); - $__25 = $__24.localIdentityKey; - $__26 = session.mostRecentState; - $__27 = $__26.call(session); - $__28 = $__27.remoteIdentityKey; - $__29 = getMac(macInputBytes, $__19, $__22, $__25, $__28); - $ctx.state = 14; - break; - case 14: - $ctx.state = 10; - return $__29; - case 10: - $__30 = $ctx.sent; - $ctx.state = 12; - break; - case 12: - $__31 = { - version: version, - message: message, - mac: $__30 - }; - $__32 = $__18.call(Messages, $__31); - $ctx.state = 16; - break; - case 16: - $ctx.returnValue = $__32; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__17, this); - })); - var createPreKeyWhisperMessage = function (session, whisperMessage) { - var pendingPreKey = session.mostRecentState().pendingPreKey; - return Messages.encodePreKeyWhisperMessage({ - version: { - current: session.mostRecentState().sessionVersion, - max: ProtocolConstants.currentVersion - }, - message: { - registrationId: session.mostRecentState().localRegistrationId, - preKeyId: pendingPreKey.preKeyId, - signedPreKeyId: pendingPreKey.signedPreKeyId, - baseKey: pendingPreKey.baseKey, - identityKey: session.mostRecentState().localIdentityKey, - message: whisperMessage - } - }); - }; - var getOrCreateReceivingChain = co.wrap($traceurRuntime.initGeneratorFunction(function $__33(sessionState, theirEphemeralPublicKey) { - var chain, $__34, $__35; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - chain = sessionState.findReceivingChain(theirEphemeralPublicKey); - $ctx.state = 13; - break; - case 13: - $ctx.state = chain ? 1 : 2; - break; - case 1: - $ctx.returnValue = chain; - $ctx.state = -2; - break; - case 2: - $__34 = clickMainRatchet(sessionState, theirEphemeralPublicKey); - $ctx.state = 9; - break; - case 9: - $ctx.state = 5; - return $__34; - case 5: - $__35 = $ctx.sent; - $ctx.state = 7; - break; - case 7: - $ctx.returnValue = $__35; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__33, this); - })); - var getOrCreateMessageKeys = co.wrap($traceurRuntime.initGeneratorFunction(function $__36(theirEphemeralPublicKey, chain, counter) { - var cachedMessageKeys, messageKeys; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = chain.index > counter ? 3 : 24; - break; - case 3: - cachedMessageKeys = chain.messageKeys[counter]; - if (!cachedMessageKeys) { - throw new DuplicateMessageException('Received message with old counter'); - } - delete chain.messageKeys[counter]; - $ctx.state = 4; - break; - case 4: - $ctx.returnValue = cachedMessageKeys; - $ctx.state = -2; - break; - case 24: - if (counter - chain.index > ProtocolConstants.maximumMissedMessages) { - throw new InvalidMessageException('Too many skipped messages'); - } - $ctx.state = 25; - break; - case 25: - $ctx.state = chain.index < counter ? 5 : 13; - break; - case 5: - $ctx.state = 6; - return ratchet.deriveMessageKeys(chain.key); - case 6: - chain.messageKeys[chain.index] = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $ctx.state = 10; - return ratchet.clickSubRatchet(chain); - case 10: - $ctx.maybeThrow(); - $ctx.state = 25; - break; - case 13: - $ctx.state = 15; - return ratchet.deriveMessageKeys(chain.key); - case 15: - messageKeys = $ctx.sent; - $ctx.state = 17; - break; - case 17: - $ctx.state = 19; - return ratchet.clickSubRatchet(chain); - case 19: - $ctx.maybeThrow(); - $ctx.state = 21; - break; - case 21: - $ctx.returnValue = messageKeys; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__36, this); - })); - var clickMainRatchet = co.wrap($traceurRuntime.initGeneratorFunction(function $__37(sessionState, theirEphemeralPublicKey) { - var $__10, theirRootKey, nextReceivingChain, ourNewEphemeralKeyPair, $__11, rootKey, nextSendingChain, $__38, $__39, $__40, $__41, $__42, $__43, $__44, $__45, $__46, $__47, $__48, $__49, $__50, $__51; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $__38 = ratchet.deriveNextRootKeyAndChain; - $__39 = sessionState.rootKey; - $__40 = sessionState.senderRatchetKeyPair; - $__41 = $__40.private; - $__42 = $__38.call(ratchet, $__39, theirEphemeralPublicKey, $__41); - $ctx.state = 6; - break; - case 6: - $ctx.state = 2; - return $__42; - case 2: - $__43 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__10 = $__43; - $__44 = $__10.rootKey; - theirRootKey = $__44; - $__45 = $__10.chain; - nextReceivingChain = $__45; - $ctx.state = 8; - break; - case 8: - $ctx.state = 10; - return crypto.generateKeyPair(); - case 10: - ourNewEphemeralKeyPair = $ctx.sent; - $ctx.state = 12; - break; - case 12: - $__46 = ratchet.deriveNextRootKeyAndChain; - $__47 = ourNewEphemeralKeyPair.private; - $__48 = $__46.call(ratchet, theirRootKey, theirEphemeralPublicKey, $__47); - $ctx.state = 18; - break; - case 18: - $ctx.state = 14; - return $__48; - case 14: - $__49 = $ctx.sent; - $ctx.state = 16; - break; - case 16: - $__11 = $__49; - $__50 = $__11.rootKey; - rootKey = $__50; - $__51 = $__11.chain; - nextSendingChain = $__51; - $ctx.state = 20; - break; - case 20: - sessionState.rootKey = rootKey; - sessionState.addReceivingChain(theirEphemeralPublicKey, nextReceivingChain); - sessionState.previousCounter = Math.max(sessionState.sendingChain.index - 1, 0); - sessionState.sendingChain = nextSendingChain; - sessionState.senderRatchetKeyPair = ourNewEphemeralKeyPair; - $ctx.state = 24; - break; - case 24: - $ctx.returnValue = nextReceivingChain; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__37, this); - })); - Object.freeze(self); - } - var $__default = SessionCipher; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__WhisperProtos__, $__ArrayBufferUtils__, $__Messages__, $__Ratchet__, $__SessionState__, $__Session__, $__Exceptions__, $__co__; - var WhisperProtos = ($__WhisperProtos__ = _require(16), $__WhisperProtos__ && $__WhisperProtos__.__esModule && $__WhisperProtos__ || { default: $__WhisperProtos__ }).default; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var Messages = ($__Messages__ = _require(7), $__Messages__ && $__Messages__.__esModule && $__Messages__ || { default: $__Messages__ }).default; - var Ratchet = ($__Ratchet__ = _require(10), $__Ratchet__ && $__Ratchet__.__esModule && $__Ratchet__ || { default: $__Ratchet__ }).default; - var SessionState = ($__SessionState__ = _require(14), $__SessionState__ && $__SessionState__.__esModule && $__SessionState__ || { default: $__SessionState__ }).default; - var Session = ($__Session__ = _require(11), $__Session__ && $__Session__.__esModule && $__Session__ || { default: $__Session__ }).default; - var $__6 = ($__Exceptions__ = _require(5), $__Exceptions__ && $__Exceptions__.__esModule && $__Exceptions__ || { default: $__Exceptions__ }), InvalidKeyException = $__6.InvalidKeyException, UnsupportedProtocolVersionException = $__6.UnsupportedProtocolVersionException, UntrustedIdentityException = $__6.UntrustedIdentityException; - var co = ($__co__ = _require(18), $__co__ && $__co__.__esModule && $__co__ || { default: $__co__ }).default; - function SessionFactory(crypto, store) { - var self = this; - var ratchet = new Ratchet(crypto); - self.createSessionFromPreKeyBundle = co.wrap($traceurRuntime.initGeneratorFunction(function $__12(retrievedPreKeyBundle) { - var validSignature, supportsV3, ourBaseKeyPair, theirSignedPreKey, aliceParameters, sessionState, session, $__13, $__14, $__15, $__16, $__17, $__18, $__19; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = retrievedPreKeyBundle.signedPreKey ? 1 : 6; - break; - case 1: - $ctx.state = 2; - return crypto.verifySignature(retrievedPreKeyBundle.identityKey, retrievedPreKeyBundle.signedPreKey, retrievedPreKeyBundle.signedPreKeySignature); - case 2: - validSignature = $ctx.sent; - $ctx.state = 4; - break; - case 4: - if (!validSignature) { - throw new InvalidKeyException('Invalid signature on device key'); - } - $ctx.state = 6; - break; - case 6: - if (!retrievedPreKeyBundle.preKey && !retrievedPreKeyBundle.signedPreKey) { - throw new InvalidKeyException('Both signed and unsigned pre keys are absent'); - } - supportsV3 = !!retrievedPreKeyBundle.signedPreKey; - $ctx.state = 31; - break; - case 31: - $ctx.state = 9; - return crypto.generateKeyPair(); - case 9: - ourBaseKeyPair = $ctx.sent; - $ctx.state = 11; - break; - case 11: - theirSignedPreKey = supportsV3 ? retrievedPreKeyBundle.signedPreKey : retrievedPreKeyBundle.preKey; - $ctx.state = 33; - break; - case 33: - $__13 = store.getLocalIdentityKeyPair; - $__14 = $__13.call(store); - $ctx.state = 17; - break; - case 17: - $ctx.state = 13; - return $__14; - case 13: - $__15 = $ctx.sent; - $ctx.state = 15; - break; - case 15: - $__16 = retrievedPreKeyBundle.identityKey; - if (supportsV3) { - $__17 = retrievedPreKeyBundle.preKey; - $__18 = $__17; - } else { - $__18 = undefined; - } - $__19 = { - sessionVersion: supportsV3 ? 3 : 2, - ourBaseKeyPair: ourBaseKeyPair, - ourIdentityKeyPair: $__15, - theirIdentityKey: $__16, - theirSignedPreKey: theirSignedPreKey, - theirRatchetKey: theirSignedPreKey, - theirOneTimePreKey: $__18 - }; - aliceParameters = $__19; - $ctx.state = 19; - break; - case 19: - $ctx.state = 21; - return initializeAliceSession(aliceParameters); - case 21: - sessionState = $ctx.sent; - $ctx.state = 23; - break; - case 23: - sessionState.pendingPreKey = { - preKeyId: supportsV3 ? retrievedPreKeyBundle.preKeyId : null, - signedPreKeyId: retrievedPreKeyBundle.signedPreKeyId, - baseKey: ourBaseKeyPair.public - }; - $ctx.state = 35; - break; - case 35: - $ctx.state = 25; - return store.getLocalRegistrationId(); - case 25: - sessionState.localRegistrationId = $ctx.sent; - $ctx.state = 27; - break; - case 27: - session = new Session(); - session.addState(sessionState); - $ctx.state = 37; - break; - case 37: - $ctx.returnValue = session; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__12, this); - })); - self.createSessionFromPreKeyWhisperMessage = co.wrap($traceurRuntime.initGeneratorFunction(function $__20(session, preKeyWhisperMessageBytes) { - var preKeyWhisperMessage, message, $__8, $__9, cachedSessionState, ourSignedPreKeyPair, preKeyPair, bobParameters, sessionState, clonedSession, $__21, $__22, $__23, $__24, $__25, $__26, $__27, $__28; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - preKeyWhisperMessage = Messages.decodePreKeyWhisperMessage(preKeyWhisperMessageBytes); - if (preKeyWhisperMessage.version.current !== 3) { - throw new UnsupportedProtocolVersionException('Protocol version ' + preKeyWhisperMessage.version.current + ' is not supported'); - } - message = preKeyWhisperMessage.message; - $ctx.state = 33; - break; - case 33: - $ctx.state = session ? 7 : 6; - break; - case 7: - $__8 = session.states[$traceurRuntime.toProperty(Symbol.iterator)](), $__9 = void 0; - $ctx.state = 2; - break; - case 2: - $ctx.state = !($__9 = $__8.next()).done ? 4 : 6; - break; - case 4: - cachedSessionState = $__9.value; - $ctx.state = 5; - break; - case 5: - $ctx.state = cachedSessionState.theirBaseKey && ArrayBufferUtils.areEqual(cachedSessionState.theirBaseKey, message.baseKey) ? 1 : 2; - break; - case 1: - $ctx.returnValue = { - session: session, - identityKey: message.identityKey, - registrationId: message.registrationId - }; - $ctx.state = -2; - break; - case 6: - $ctx.state = 10; - return store.getLocalSignedPreKeyPair(message.signedPreKeyId); - case 10: - ourSignedPreKeyPair = $ctx.sent; - $ctx.state = 12; - break; - case 12: - $ctx.state = message.preKeyId !== null ? 13 : 16; - break; - case 13: - $ctx.state = 14; - return store.getLocalPreKeyPair(message.preKeyId); - case 14: - preKeyPair = $ctx.sent; - $ctx.state = 16; - break; - case 16: - $__21 = preKeyWhisperMessage.version; - $__22 = $__21.current; - $__23 = message.baseKey; - $__24 = message.identityKey; - $__25 = store.getLocalIdentityKeyPair; - $__26 = $__25.call(store); - $ctx.state = 23; - break; - case 23: - $ctx.state = 19; - return $__26; - case 19: - $__27 = $ctx.sent; - $ctx.state = 21; - break; - case 21: - $__28 = { - sessionVersion: $__22, - theirBaseKey: $__23, - theirIdentityKey: $__24, - ourIdentityKeyPair: $__27, - ourSignedPreKeyPair: ourSignedPreKeyPair, - ourRatchetKeyPair: ourSignedPreKeyPair, - ourOneTimePreKeyPair: preKeyPair - }; - bobParameters = $__28; - $ctx.state = 25; - break; - case 25: - $ctx.state = 27; - return initializeBobSession(bobParameters); - case 27: - sessionState = $ctx.sent; - $ctx.state = 29; - break; - case 29: - sessionState.theirBaseKey = message.baseKey; - clonedSession = new Session(session); - clonedSession.addState(sessionState); - $ctx.state = 35; - break; - case 35: - $ctx.returnValue = { - session: clonedSession, - identityKey: message.identityKey, - registrationId: message.registrationId - }; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__20, this); - })); - var initializeAliceSession = co.wrap($traceurRuntime.initGeneratorFunction(function $__29(parameters) { - var sendingRatchetKeyPair, agreements, $__10, theirRootKey, receivingChain, $__11, rootKey, sendingChain, sessionState, $__30, $__31, $__32, $__33, $__34, $__35, $__36, $__37, $__38, $__39, $__40, $__41, $__42, $__43; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - $ctx.state = 2; - return crypto.generateKeyPair(); - case 2: - sendingRatchetKeyPair = $ctx.sent; - $ctx.state = 4; - break; - case 4: - agreements = [ - crypto.calculateAgreement(parameters.theirSignedPreKey, parameters.ourIdentityKeyPair.private), - crypto.calculateAgreement(parameters.theirIdentityKey, parameters.ourBaseKeyPair.private), - crypto.calculateAgreement(parameters.theirSignedPreKey, parameters.ourBaseKeyPair.private) - ]; - if (parameters.sessionVersion >= 3 && parameters.theirOneTimePreKey) { - agreements.push(crypto.calculateAgreement(parameters.theirOneTimePreKey, parameters.ourBaseKeyPair.private)); - } - $ctx.state = 30; - break; - case 30: - $__30 = ratchet.deriveInitialRootKeyAndChain; - $__31 = parameters.sessionVersion; - $ctx.state = 14; - break; - case 14: - $ctx.state = 6; - return agreements; - case 6: - $__32 = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $__33 = $__30.call(ratchet, $__31, $__32); - $ctx.state = 16; - break; - case 16: - $ctx.state = 10; - return $__33; - case 10: - $__34 = $ctx.sent; - $ctx.state = 12; - break; - case 12: - $__10 = $__34; - $__35 = $__10.rootKey; - theirRootKey = $__35; - $__36 = $__10.chain; - receivingChain = $__36; - $ctx.state = 18; - break; - case 18: - $__37 = ratchet.deriveNextRootKeyAndChain; - $__38 = parameters.theirRatchetKey; - $__39 = sendingRatchetKeyPair.private; - $__40 = $__37.call(ratchet, theirRootKey, $__38, $__39); - $ctx.state = 24; - break; - case 24: - $ctx.state = 20; - return $__40; - case 20: - $__41 = $ctx.sent; - $ctx.state = 22; - break; - case 22: - $__11 = $__41; - $__42 = $__11.rootKey; - rootKey = $__42; - $__43 = $__11.chain; - sendingChain = $__43; - $ctx.state = 26; - break; - case 26: - sessionState = new SessionState({ - sessionVersion: parameters.sessionVersion, - remoteIdentityKey: parameters.theirIdentityKey, - localIdentityKey: parameters.ourIdentityKeyPair.public, - rootKey: rootKey, - sendingChain: sendingChain, - senderRatchetKeyPair: sendingRatchetKeyPair - }); - sessionState.addReceivingChain(parameters.theirRatchetKey, receivingChain); - $ctx.state = 32; - break; - case 32: - $ctx.returnValue = sessionState; - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__29, this); - })); - var initializeBobSession = co.wrap($traceurRuntime.initGeneratorFunction(function $__44(parameters) { - var agreements, $__10, rootKey, sendingChain, $__45, $__46, $__47, $__48, $__49, $__50, $__51; - return $traceurRuntime.createGeneratorInstance(function ($ctx) { - while (true) - switch ($ctx.state) { - case 0: - agreements = [ - crypto.calculateAgreement(parameters.theirIdentityKey, parameters.ourSignedPreKeyPair.private), - crypto.calculateAgreement(parameters.theirBaseKey, parameters.ourIdentityKeyPair.private), - crypto.calculateAgreement(parameters.theirBaseKey, parameters.ourSignedPreKeyPair.private) - ]; - if (parameters.sessionVersion >= 3 && parameters.ourOneTimePreKeyPair) { - agreements.push(crypto.calculateAgreement(parameters.theirBaseKey, parameters.ourOneTimePreKeyPair.private)); - } - $ctx.state = 18; - break; - case 18: - $__45 = ratchet.deriveInitialRootKeyAndChain; - $__46 = parameters.sessionVersion; - $ctx.state = 10; - break; - case 10: - $ctx.state = 2; - return agreements; - case 2: - $__47 = $ctx.sent; - $ctx.state = 4; - break; - case 4: - $__48 = $__45.call(ratchet, $__46, $__47); - $ctx.state = 12; - break; - case 12: - $ctx.state = 6; - return $__48; - case 6: - $__49 = $ctx.sent; - $ctx.state = 8; - break; - case 8: - $__10 = $__49; - $__50 = $__10.rootKey; - rootKey = $__50; - $__51 = $__10.chain; - sendingChain = $__51; - $ctx.state = 14; - break; - case 14: - $ctx.returnValue = new SessionState({ - sessionVersion: parameters.sessionVersion, - remoteIdentityKey: parameters.theirIdentityKey, - localIdentityKey: parameters.ourIdentityKeyPair.public, - rootKey: rootKey, - sendingChain: sendingChain, - senderRatchetKeyPair: parameters.ourRatchetKeyPair - }); - $ctx.state = -2; - break; - default: - return $ctx.end(); - } - }, $__44, this); - })); - Object.freeze(self); - } - var $__default = SessionFactory; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__ArrayBufferUtils__, $__ProtocolConstants__; - var ArrayBufferUtils = ($__ArrayBufferUtils__ = _require(1), $__ArrayBufferUtils__ && $__ArrayBufferUtils__.__esModule && $__ArrayBufferUtils__ || { default: $__ArrayBufferUtils__ }).default; - var ProtocolConstants = ($__ProtocolConstants__ = _require(9), $__ProtocolConstants__ && $__ProtocolConstants__.__esModule && $__ProtocolConstants__ || { default: $__ProtocolConstants__ }).default; - var makeReadonly = function (obj, key) { - Object.defineProperty(obj, key, { writable: false }); - }; - var SessionState = function SessionState(parameters) { - Object.assign(this, { - sessionVersion: 3, - remoteIdentityKey: null, - localIdentityKey: null, - pendingPreKey: null, - localRegistrationId: 0, - theirBaseKey: null, - rootKey: null, - sendingChain: null, - senderRatchetKeyPair: null, - receivingChains: [], - previousCounter: 0 - }, parameters); - makeReadonly(this, 'sessionVersion'); - makeReadonly(this, 'remoteIdentityKey'); - makeReadonly(this, 'localIdentityKey'); - Object.seal(this); - }; - $traceurRuntime.createClass(SessionState, { - findReceivingChain: function (theirEphemeralPublicKey) { - for (var i = 0; i < this.receivingChains.length; i++) { - var receivingChain = this.receivingChains[i]; - if (ArrayBufferUtils.areEqual(receivingChain.theirEphemeralKey, theirEphemeralPublicKey)) { - return receivingChain.chain; - } - } - return null; - }, - addReceivingChain: function (theirEphemeralPublicKey, chain) { - this.receivingChains.push({ - theirEphemeralKey: theirEphemeralPublicKey, - chain: chain - }); - if (this.receivingChains.length > ProtocolConstants.maximumRetainedReceivedChainKeys) { - this.receivingChains.shift(); - } - } - }, {}); - var $__default = SessionState; - }, - function (module, exports) { - 'use strict'; - Object.defineProperties(module.exports, { - default: { - get: function () { - return $__default; - } - }, - __esModule: { value: true } - }); - var $__PromiseInterfaceDecorator__; - var PromiseInterfaceDecorator = ($__PromiseInterfaceDecorator__ = _require(8), $__PromiseInterfaceDecorator__ && $__PromiseInterfaceDecorator__.__esModule && $__PromiseInterfaceDecorator__ || { default: $__PromiseInterfaceDecorator__ }).default; - var methodNames = [ - 'getLocalIdentityKeyPair', - 'getLocalRegistrationId', - 'getLocalSignedPreKeyPair', - 'getLocalPreKeyPair' - ]; - var Store = function Store(store) { - $traceurRuntime.superConstructor($Store).call(this, store, methodNames); - }; - var $Store = Store; - $traceurRuntime.createClass(Store, {}, {}, PromiseInterfaceDecorator); - var $__default = Store; - }, - function (module, exports) { - 'use strict'; - module.exports = _require(19).newBuilder({})['import']({ - 'package': 'textsecure', - 'messages': [ - { - 'name': 'WhisperMessage', - 'fields': [ - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'ratchetKey', - 'id': 1 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'counter', - 'id': 2 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'previousCounter', - 'id': 3 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'ciphertext', - 'id': 4 - } - ], - 'enums': [], - 'messages': [], - 'options': {}, - 'oneofs': {} - }, - { - 'name': 'PreKeyWhisperMessage', - 'fields': [ - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'registrationId', - 'id': 5 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'preKeyId', - 'id': 1 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'signedPreKeyId', - 'id': 6 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'baseKey', - 'id': 2 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'identityKey', - 'id': 3 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'message', - 'id': 4 - } - ], - 'enums': [], - 'messages': [], - 'options': {}, - 'oneofs': {} - }, - { - 'name': 'KeyExchangeMessage', - 'fields': [ - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'id', - 'id': 1 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'baseKey', - 'id': 2 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'ratchetKey', - 'id': 3 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'identityKey', - 'id': 4 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'baseKeySignature', - 'id': 5 - } - ], - 'enums': [], - 'messages': [], - 'options': {}, - 'oneofs': {} - }, - { - 'name': 'SenderKeyMessage', - 'fields': [ - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'id', - 'id': 1 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'iteration', - 'id': 2 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'ciphertext', - 'id': 3 - } - ], - 'enums': [], - 'messages': [], - 'options': {}, - 'oneofs': {} - }, - { - 'name': 'SenderKeyDistributionMessage', - 'fields': [ - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'id', - 'id': 1 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'uint32', - 'name': 'iteration', - 'id': 2 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'chainKey', - 'id': 3 - }, - { - 'rule': 'optional', - 'options': {}, - 'type': 'bytes', - 'name': 'signingKey', - 'id': 4 - } - ], - 'enums': [], - 'messages': [], - 'options': {}, - 'oneofs': {} - } - ], - 'enums': [], - 'imports': [], - 'options': { - 'java_package': 'org.whispersystems.libaxolotl.protocol', - 'java_outer_classname': 'WhisperProtos' - }, - 'services': [] - }).build('textsecure'); - }, - function (module, exports) { - module.exports = __external_axolotlCrypto; - }, - function (module, exports) { - var slice = Array.prototype.slice; - module.exports = co['default'] = co.co = co; - co.wrap = function (fn) { - return function () { - return co.call(this, fn.apply(this, arguments)); - }; - }; - function co(gen) { - var ctx = this; - if (typeof gen === 'function') - gen = gen.call(this); - return new Promise(function (resolve, reject) { - onFulfilled(); - function onFulfilled(res) { - var ret; - try { - ret = gen.next(res); - } catch (e) { - return reject(e); - } - next(ret); - } - function onRejected(err) { - var ret; - try { - ret = gen.throw(err); - } catch (e) { - return reject(e); - } - next(ret); - } - function next(ret) { - if (ret.done) - return resolve(ret.value); - var value = toPromise.call(ctx, ret.value); - if (value && isPromise(value)) - return value.then(onFulfilled, onRejected); - return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); - } - }); - } - function toPromise(obj) { - if (!obj) - return obj; - if (isPromise(obj)) - return obj; - if (isGeneratorFunction(obj) || isGenerator(obj)) - return co.call(this, obj); - if ('function' == typeof obj) - return thunkToPromise.call(this, obj); - if (Array.isArray(obj)) - return arrayToPromise.call(this, obj); - if (isObject(obj)) - return objectToPromise.call(this, obj); - return obj; - } - function thunkToPromise(fn) { - var ctx = this; - return new Promise(function (resolve, reject) { - fn.call(ctx, function (err, res) { - if (err) - return reject(err); - if (arguments.length > 2) - res = slice.call(arguments, 1); - resolve(res); - }); - }); - } - function arrayToPromise(obj) { - return Promise.all(obj.map(toPromise, this)); - } - function objectToPromise(obj) { - var results = new obj.constructor(); - var keys = Object.keys(obj); - var promises = []; - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var promise = toPromise.call(this, obj[key]); - if (promise && isPromise(promise)) - defer(promise, key); - else - results[key] = obj[key]; - } - return Promise.all(promises).then(function () { - return results; - }); - function defer(promise, key) { - results[key] = undefined; - promises.push(promise.then(function (res) { - results[key] = res; - })); - } - } - function isPromise(obj) { - return 'function' == typeof obj.then; - } - function isGenerator(obj) { - return 'function' == typeof obj.next && 'function' == typeof obj.throw; - } - function isGeneratorFunction(obj) { - var constructor = obj.constructor; - var proto = constructor.prototype; - var name = constructor.displayName || constructor.name; - var nameLooksRight = 'GeneratorFunction' == name; - var methodsLooksRight = 'function' == typeof proto.next && 'function' == typeof proto.throw; - return nameLooksRight || methodsLooksRight; - } - function isObject(val) { - return Object == val.constructor; - } - }, - function (module, exports) { - module.exports = __external_1; - } - ]; - return _require(0); -})); \ No newline at end of file diff --git a/index.js b/index.js index a816d83..78aeb88 100644 --- a/index.js +++ b/index.js @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -import Axolotl from "./src/Axolotl"; -import axolotlCrypto from "axolotl-crypto"; +const Axolotl = require("./src/Axolotl"); +const axolotlCrypto = require("axolotl-crypto"); module.exports = function(store) { return new Axolotl(axolotlCrypto, store); diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 17be0c1..0000000 --- a/karma.conf.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = function(config) { - config.set({ - frameworks: ["mocha", "chai"], - - files: [ - "bower_components/axolotl-crypto-curve25519/curve25519.js", - "bower_components/axolotl-crypto/axolotl-crypto.js", - "node_modules/bytebuffer/dist/ByteBufferAB.js", - "node_modules/protobufjs/dist/ProtoBuf.noparse.js", - "node_modules/traceur/bin/traceur-runtime.js", - "dist/axolotl.js", - "test/integration/web/**/*.js" - ], - browsers: ["Firefox"], - client: { - mocha: { - reporter: "html", // change Karma's debug.html to the mocha web reporter - ui: "bdd" - } - }, - singleRun: true - }); -}; \ No newline at end of file diff --git a/package.json b/package.json index 77d3ae1..13b2e57 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "axolotl", "version": "1.3.0", "description": "An indepedent JavaScript implementation of Axolotl. Axolotl is a ratcheting forward secrecy protocol.", - "main": "dist/axolotl.js", + "main": "index.js", "directories": { "test": "test" }, @@ -11,9 +11,8 @@ "bytebuffer": "^3.5.4", "chai": "~1.10.0", "chai-as-promised": "^4.1.1", - "co": "^4.1.0", - "grunt": "~0.4.5", - "grunt-blanket": "0.0.8", + "grunt-cli": "~0.1.13", + "grunt-blanket": "0.0.10", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-concat": "~0.5.0", "grunt-contrib-copy": "^0.7.0", @@ -21,15 +20,12 @@ "grunt-jscs": "~1.1.0", "grunt-karma": "^0.10.1", "grunt-mocha-test": "~0.12.4", - "grunt-pure-cjs": "^1.4.0", - "grunt-traceur": "^0.5.1", "karma": "^0.12.31", "karma-chai": "^0.1.0", "karma-firefox-launcher": "^0.1.4", "karma-mocha": "^0.1.10", "long": "^2.2.3", "mocha": "~2.1.0", - "mocha-traceur": "^2.1.0", "requirejs-browser": "^2.1.9", "sinon": "~1.12.2" }, @@ -41,7 +37,7 @@ "textsecure" ], "author": "Joe Bandenburg ", - "license": "LGPLv3", + "license": "LGPL-3.0", "repository": { "type": "git", "url": "http://github.com/joebandenburg/libaxolotl-javascript.git" @@ -49,6 +45,6 @@ "dependencies": { "axolotl-crypto": "^1.1.0", "protobufjs": "~3.8.2", - "traceur": "0.0.84" + "co": "^4.1.0" } } diff --git a/src/ArrayBufferUtils.js b/src/ArrayBufferUtils.js index 483448a..3814988 100644 --- a/src/ArrayBufferUtils.js +++ b/src/ArrayBufferUtils.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,8 +16,13 @@ * along with this program. If not, see . */ -export default { - // TODO: Consider timing attack +module.exports = { + // Note the code here is not secure against timing and cache attacks in many + // places, including here. Take care to run it only on clients, not on a server, + // and client code should not automatically reply to messages. + // As long as all outgoing messages are triggered by user interaction, remote + // timing attacks are not a problem, and on the client malicious code timesharing + // the same CPU is not a concern we defend against. areEqual: (left, right) => { if (left.byteLength !== right.byteLength) { return false; @@ -30,8 +36,10 @@ export default { } return true; }, - concat: function(...buffers) { - buffers = (buffers.length === 1) ? buffers[0] : buffers; + concat: function(buffers) { + if (arguments.length > 1) { + buffers = arguments; + } var i; var byteLength = 0; for (i = 0; i < buffers.length; i++) { diff --git a/src/Axolotl.js b/src/Axolotl.js index f5a815f..f358b71 100644 --- a/src/Axolotl.js +++ b/src/Axolotl.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,13 +16,13 @@ * along with this program. If not, see . */ -import SessionFactory from "./SessionFactory"; -import SessionCipher from "./SessionCipher"; -import {InvalidMessageException} from "./Exceptions"; -import Store from "./Store"; -import Crypto from "./Crypto"; -import co from "co"; -import axolotlCrypto from "axolotl-crypto"; +const SessionFactory = require("./SessionFactory"); +const SessionCipher = require("./SessionCipher"); +const InvalidMessageException = require("./Exceptions").InvalidMessageException; +const Store = require("./Store"); +const Crypto = require("./Crypto"); +const co = require("co"); +const axolotlCrypto = require("axolotl-crypto"); /** * A public/private key pair @@ -232,24 +233,22 @@ function Axolotl(crypto, store) { * @returns {Promise.} an object containing the decrypted message and a new session */ this.decryptPreKeyWhisperMessage = co.wrap(function*(session, preKeyWhisperMessageBytes) { - var { - session: newSession, - identityKey, - registrationId - } = yield sessionFactory.createSessionFromPreKeyWhisperMessage(session, preKeyWhisperMessageBytes); - var { - session: finalSession, - message - } = yield sessionCipher.decryptPreKeyWhisperMessage(newSession, preKeyWhisperMessageBytes); + const result = yield sessionFactory.createSessionFromPreKeyWhisperMessage(session, preKeyWhisperMessageBytes); + const newSession = result.session; + const identityKey = result.identityKey; + const registrationId = result.registrationId ; + const decryptionResult = yield sessionCipher.decryptPreKeyWhisperMessage(newSession, preKeyWhisperMessageBytes); + const finalSession = decryptionResult.session; + const message = decryptionResult.message; return { - message: message, + message, session: finalSession, - identityKey: identityKey, - registrationId: registrationId + identityKey, + registrationId }; }); Object.freeze(self); } -export default Axolotl; +module.exports = Axolotl; diff --git a/src/Chain.js b/src/Chain.js index dc138e3..b3c12d7 100644 --- a/src/Chain.js +++ b/src/Chain.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -18,7 +19,7 @@ /** * A chain holds the state of the sub ratchet, used for sending multiple messages before receiving a reply. */ -export default class Chain { +class Chain { /** * * @param {ArrayBuffer} key @@ -30,3 +31,5 @@ export default class Chain { Object.seal(this); } } + +module.exports = Chain; diff --git a/src/Crypto.js b/src/Crypto.js index 45aaf2e..abd0058 100644 --- a/src/Crypto.js +++ b/src/Crypto.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,7 +16,7 @@ * along with this program. If not, see . */ -import PromiseInterfaceDecorator from "./PromiseInterfaceDecorator"; +const PromiseInterfaceDecorator = require("./PromiseInterfaceDecorator"); var methodNames = [ "generateKeyPair", @@ -28,8 +29,10 @@ var methodNames = [ "decrypt" ]; -export default class Crypto extends PromiseInterfaceDecorator { +class Crypto extends PromiseInterfaceDecorator { constructor(crypto) { super(crypto, methodNames); } } + +module.exports = Crypto; diff --git a/src/Exceptions.js b/src/Exceptions.js index abc4788..a7241f0 100644 --- a/src/Exceptions.js +++ b/src/Exceptions.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,8 +16,16 @@ * along with this program. If not, see . */ -export class InvalidMessageException extends Error {} -export class DuplicateMessageException extends Error {} -export class InvalidKeyException extends Error {} -export class UnsupportedProtocolVersionException extends Error {} -export class UntrustedIdentityException extends Error {} +class InvalidMessageException extends Error {} +class DuplicateMessageException extends Error {} +class InvalidKeyException extends Error {} +class UnsupportedProtocolVersionException extends Error {} +class UntrustedIdentityException extends Error {} + +module.exports = { + InvalidMessageException, + DuplicateMessageException, + InvalidKeyException, + UnsupportedProtocolVersionException, + UntrustedIdentityException +}; diff --git a/src/HKDF.js b/src/HKDF.js index d00421d..3bd9066 100644 --- a/src/HKDF.js +++ b/src/HKDF.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,8 +16,8 @@ * along with this program. If not, see . */ -import ArrayBufferUtils from "./ArrayBufferUtils"; -import co from "co"; +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const co = require("co"); var hashOutputSize = 32; var iterationStartOffset = 1; // TODO: Depends on protocol version @@ -55,4 +56,4 @@ function HKDF(crypto) { Object.freeze(self); } -export default HKDF; +module.exports = HKDF; diff --git a/src/Messages.js b/src/Messages.js index ef26f28..abe9ea7 100644 --- a/src/Messages.js +++ b/src/Messages.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,9 +16,9 @@ * along with this program. If not, see . */ -import WhisperProtos from "./WhisperProtos"; -import ProtocolConstants from "./ProtocolConstants"; -import ArrayBufferUtils from "./ArrayBufferUtils"; +const WhisperProtos = require("./WhisperProtos"); +const ProtocolConstants = require("./ProtocolConstants"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); var getVersionField = (version) => ArrayBufferUtils.fromByte((version.current << 4 | version.max) & 0xff); @@ -41,7 +42,7 @@ var encodeWhisperMessageMacInput = (whisperMessage) => { return ArrayBufferUtils.concat(versionByte, messageBytes); }; -export default { +module.exports = { decodeWhisperMessage: (whisperMessageBytes) => { var messageBytes = whisperMessageBytes.slice(1, -ProtocolConstants.macByteCount); var message = WhisperProtos.WhisperMessage.decode(messageBytes); diff --git a/src/PromiseInterfaceDecorator.js b/src/PromiseInterfaceDecorator.js index 36d1eb0..82d6672 100644 --- a/src/PromiseInterfaceDecorator.js +++ b/src/PromiseInterfaceDecorator.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -26,7 +27,7 @@ var wrap = (fn) => { * * This allows the consumer to deal only with promises. */ -export default class PromiseInterfaceDecorator { +class PromiseInterfaceDecorator { constructor(impl, methodNames) { methodNames.forEach((methodName) => { if (!impl[methodName]) { @@ -37,3 +38,5 @@ export default class PromiseInterfaceDecorator { Object.freeze(this); } } + +module.exports = PromiseInterfaceDecorator; diff --git a/src/ProtocolConstants.js b/src/ProtocolConstants.js index c9b1e0f..99a2732 100644 --- a/src/ProtocolConstants.js +++ b/src/ProtocolConstants.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,9 +16,7 @@ * along with this program. If not, see . */ -// TODO: Consider exporting these individually - -export default { +module.exports = { currentVersion: 3, // Sizes of various fields diff --git a/src/Ratchet.js b/src/Ratchet.js index a95dfff..ef753d1 100644 --- a/src/Ratchet.js +++ b/src/Ratchet.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,11 +16,11 @@ * along with this program. If not, see . */ -import HKDF from "./HKDF"; -import Chain from "./Chain"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; -import co from "co"; +const HKDF = require("./HKDF"); +const Chain = require("./Chain"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); +const co = require("co"); const messageKeySeed = 0x01; const chainKeySeed = 0x02; @@ -137,4 +138,4 @@ function Ratchet(crypto) { }); } -export default Ratchet; +module.exports = Ratchet; diff --git a/src/Session.js b/src/Session.js index c2022a5..7f3f09a 100644 --- a/src/Session.js +++ b/src/Session.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,9 +16,9 @@ * along with this program. If not, see . */ -import ProtocolConstants from "./ProtocolConstants"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import SessionState from "./SessionState"; +const ProtocolConstants = require("./ProtocolConstants"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const SessionState = require("./SessionState"); /** * Represents the entire state of an Axolotl session. @@ -25,7 +26,7 @@ import SessionState from "./SessionState"; * @param {Session|Object} [session] - another session. If passed, this session will clone its state. * @constructor */ -export default class Session { +class Session { constructor(session) { this.states = []; if (session) { @@ -52,3 +53,5 @@ export default class Session { this.states.splice(index, 1); } } + +module.exports = Session; diff --git a/src/SessionCipher.js b/src/SessionCipher.js index e8b6237..ce2d37d 100644 --- a/src/SessionCipher.js +++ b/src/SessionCipher.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,14 +16,16 @@ * along with this program. If not, see . */ -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; -import Messages from "./Messages"; -import SessionState from "./SessionState"; -import Session from "./Session"; -import Ratchet from "./Ratchet"; -import {InvalidMessageException, DuplicateMessageException} from "./Exceptions"; -import co from "co"; +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); +const Messages = require("./Messages"); +const SessionState = require("./SessionState"); +const Session = require("./Session"); +const Ratchet = require("./Ratchet"); +const co = require("co"); +const Exceptions = require("./Exceptions"); +const InvalidMessageException = Exceptions.InvalidMessageException; +const DuplicateMessageException = Exceptions.DuplicateMessageException; /** * SessionCipher is responsible for encrypting and decrypting messages. @@ -329,26 +332,27 @@ function SessionCipher(crypto) { * @return {Promise.} the next chain for decryption */ var clickMainRatchet = co.wrap(function*(sessionState, theirEphemeralPublicKey) { - var { - rootKey: theirRootKey, - chain: nextReceivingChain - } = yield ratchet.deriveNextRootKeyAndChain(sessionState.rootKey, theirEphemeralPublicKey, + const result1 = yield ratchet.deriveNextRootKeyAndChain(sessionState.rootKey, theirEphemeralPublicKey, sessionState.senderRatchetKeyPair.private); - var ourNewEphemeralKeyPair = yield crypto.generateKeyPair(); - var { - rootKey, - chain: nextSendingChain - } = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, + const theirRootKey = result1.rootKey; + const nextReceivingChain = result1.chain; + const ourNewEphemeralKeyPair = yield crypto.generateKeyPair(); + + const result2 = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, theirEphemeralPublicKey, ourNewEphemeralKeyPair.private); + const rootKey = result2.rootKey; + const nextSendingChain = result2.chain; + sessionState.rootKey = rootKey; sessionState.addReceivingChain(theirEphemeralPublicKey, nextReceivingChain); sessionState.previousCounter = Math.max(sessionState.sendingChain.index - 1, 0); sessionState.sendingChain = nextSendingChain; sessionState.senderRatchetKeyPair = ourNewEphemeralKeyPair; + return nextReceivingChain; }); Object.freeze(self); } -export default SessionCipher; +module.exports = SessionCipher; diff --git a/src/SessionFactory.js b/src/SessionFactory.js index da0da48..241fb80 100644 --- a/src/SessionFactory.js +++ b/src/SessionFactory.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,14 +16,17 @@ * along with this program. If not, see . */ -import WhisperProtos from "./WhisperProtos"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import Messages from "./Messages"; -import Ratchet from "./Ratchet"; -import SessionState from "./SessionState"; -import Session from "./Session"; -import {InvalidKeyException, UnsupportedProtocolVersionException, UntrustedIdentityException} from "./Exceptions"; -import co from "co"; +const WhisperProtos = require("./WhisperProtos"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const Messages = require("./Messages"); +const Ratchet = require("./Ratchet"); +const SessionState = require("./SessionState"); +const Session = require("./Session"); +const co = require("co"); +const Exceptions = require("./Exceptions"); +const InvalidKeyException = Exceptions.InvalidKeyException; +const UnsupportedProtocolVersionException = Exceptions.UnsupportedProtocolVersionException; +const UntrustedIdentityException = Exceptions.UntrustedIdentityException; function SessionFactory(crypto, store) { const self = this; @@ -146,7 +150,7 @@ function SessionFactory(crypto, store) { //self.createSessionFromKeyExchange = (toIdentity, keyExchange) => {}; var initializeAliceSession = co.wrap(function*(parameters) { - var sendingRatchetKeyPair = yield crypto.generateKeyPair(); + var senderRatchetKeyPair = yield crypto.generateKeyPair(); var agreements = [ crypto.calculateAgreement(parameters.theirSignedPreKey, parameters.ourIdentityKeyPair.private), @@ -157,23 +161,21 @@ function SessionFactory(crypto, store) { agreements.push(crypto.calculateAgreement(parameters.theirOneTimePreKey, parameters.ourBaseKeyPair.private)); } - var { - rootKey: theirRootKey, - chain: receivingChain - } = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); - var { - rootKey, - chain: sendingChain - } = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, parameters.theirRatchetKey, - sendingRatchetKeyPair.private); + const initChain = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const theirRootKey = initChain.rootKey; + const receivingChain = initChain.chain; + const nextChain = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, parameters.theirRatchetKey, + senderRatchetKeyPair.private); + const rootKey = nextChain.rootKey; + const sendingChain = nextChain.chain; var sessionState = new SessionState({ sessionVersion: parameters.sessionVersion, remoteIdentityKey: parameters.theirIdentityKey, localIdentityKey: parameters.ourIdentityKeyPair.public, - rootKey: rootKey, - sendingChain: sendingChain, - senderRatchetKeyPair: sendingRatchetKeyPair + rootKey, + sendingChain, + senderRatchetKeyPair }); sessionState.addReceivingChain(parameters.theirRatchetKey, receivingChain); return sessionState; @@ -191,10 +193,9 @@ function SessionFactory(crypto, store) { parameters.ourOneTimePreKeyPair.private)); } - var { - rootKey, - chain: sendingChain - } = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const initChain = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const rootKey = initChain.rootKey; + const sendingChain = initChain.chain; return new SessionState({ sessionVersion: parameters.sessionVersion, @@ -209,4 +210,4 @@ function SessionFactory(crypto, store) { Object.freeze(self); } -export default SessionFactory; +module.exports = SessionFactory; diff --git a/src/SessionState.js b/src/SessionState.js index 789c89b..e9e7d0a 100644 --- a/src/SessionState.js +++ b/src/SessionState.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,8 +16,8 @@ * along with this program. If not, see . */ -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); var makeReadonly = (obj, key) => { Object.defineProperty(obj, key, { @@ -27,7 +28,7 @@ var makeReadonly = (obj, key) => { /** * A serialisable representation of a session "state". Sessions can contain multiple states. */ -export default class SessionState { +class SessionState { /** * * @param {object} parameters - initial parameters @@ -86,3 +87,5 @@ export default class SessionState { } } } + +module.exports = SessionState; diff --git a/src/Store.js b/src/Store.js index fea4caf..1cde6f8 100644 --- a/src/Store.js +++ b/src/Store.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,7 +16,7 @@ * along with this program. If not, see . */ -import PromiseInterfaceDecorator from "./PromiseInterfaceDecorator"; +const PromiseInterfaceDecorator = require("./PromiseInterfaceDecorator"); var methodNames = [ "getLocalIdentityKeyPair", @@ -24,8 +25,10 @@ var methodNames = [ "getLocalPreKeyPair" ]; -export default class Store extends PromiseInterfaceDecorator { +class Store extends PromiseInterfaceDecorator { constructor(store) { super(store, methodNames); } } + +module.exports = Store; diff --git a/src/WhisperProtos.js b/src/WhisperProtos.js index 76dcc7b..06b3cdc 100644 --- a/src/WhisperProtos.js +++ b/src/WhisperProtos.js @@ -1,3 +1,4 @@ +"use strict"; // Generated file. DO NOT EDIT!! module.exports = require("protobufjs").newBuilder({})["import"]({ "package": "textsecure", diff --git a/test/integration/node/axolotl.js b/test/integration/node/axolotl.js index 13bda11..3a00044 100644 --- a/test/integration/node/axolotl.js +++ b/test/integration/node/axolotl.js @@ -1,6 +1,7 @@ +"use strict"; var assert = require("assert"); -var ByteBuffer = require("ByteBuffer"); -var axolotl = require("../../../dist/axolotl"); +var ByteBuffer = require("bytebuffer"); +var axolotl = require("../../.."); var fromHex = function(hex) { return ByteBuffer.fromHex(hex).toArrayBuffer(); diff --git a/test/integration/web/axolotl.js b/test/integration/web/axolotl.js deleted file mode 100644 index 4b7f993..0000000 --- a/test/integration/web/axolotl.js +++ /dev/null @@ -1,48 +0,0 @@ -var fromHex = function(hex) { - return window.dcodeIO.ByteBuffer.fromHex(hex).toArrayBuffer(); -}; - -var state = { - states: [{ - sessionVersion: 3, - remoteIdentityKey: fromHex("0534ad091121f387dbf22e56e7a7c7e6f6964ed7ba6ed1e092d3870b6285c4eb13"), - localIdentityKey: fromHex("052e978dcd2f616c2275ff28c740645c2ceec9a7c73c712dd2d55e4b6aa3ec5f44"), - pendingPreKey: { - preKeyId: 0, - signedPreKeyId: 0, - baseKey: fromHex("052d2c043f7035101c596a1febb78fc4a8d8dff07db66449530ce1a3396d954f6c") - }, - localRegistrationId: 1083, - theirBaseKey: fromHex("050741319370838cc8e2e590253024697b3837376bd70699f48ca23147c7088f08"), - rootKey: fromHex("f0006715ba617382e62d3e074a575915e6b2289e4df6dee12fac04f4465812"), - sendingChain: { - key: fromHex("de215ccf67f7e13e57d7fac761b87eee20bdc6c1eb9479b2ac83766016a3de64"), - index: 1, - messageKeys: [] - }, - senderRatchetKeyPair: { - public: fromHex("059b1ec3e47026d098ef617b9085459c9ae5dff61067d4d797f2318ac943236957"), - private: fromHex("c842eebc48d101bc084a2f725e3f1a145829575fff108a7cd5387ae62e55267a") - }, - previousCounter: 0 - }] -}; - -describe("axolotl integration web", function() { - var stub = function() { return 1; }; - it("produces the expected output", function() { - var expectedCiphertext = "3328bb08080030001221052d2c043f7035101c596a1febb78fc4a8d8dff07db66449530ce1a3396d954" + - "f6c1a21052e978dcd2f616c2275ff28c740645c2ceec9a7c73c712dd2d55e4b6aa3ec5f442242330a21059b1ec3e47026d098ef6" + - "17b9085459c9ae5dff61067d4d797f2318ac943236957100118002210ef3c9236a9c9afba0f72ad6eefe739b27b54a8b565750a5e"; - var axol = new window.axolotl({ - getLocalIdentityKeyPair: stub, - getLocalRegistrationId: stub, - getLocalSignedPreKeyPair: stub, - getLocalPreKeyPair: stub - }); - return axol.encryptMessage(state, new Uint8Array([1, 2, 3, 4]).buffer).then(function(result) { - var actualBody = window.dcodeIO.ByteBuffer.wrap(result.body).toHex(); - assert.equal(actualBody, expectedCiphertext); - }); - }); -}); diff --git a/test/unit/ArrayBufferUtils.js b/test/unit/ArrayBufferUtils.js index 37cf391..6423655 100644 --- a/test/unit/ArrayBufferUtils.js +++ b/test/unit/ArrayBufferUtils.js @@ -1,5 +1,6 @@ -import chai from "chai"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; +"use strict"; +const chai = require("chai"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); var assert = chai.assert; diff --git a/test/unit/Axolotl.js b/test/unit/Axolotl.js index 3dd0ae4..c494cef 100644 --- a/test/unit/Axolotl.js +++ b/test/unit/Axolotl.js @@ -1,20 +1,20 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import sinon from "sinon"; -import co from "co"; - -import Axolotl from "../../src/Axolotl"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import Messages from "../../src/Messages"; -import { - UnsupportedProtocolVersionException, - InvalidKeyException, - InvalidMessageException, - DuplicateMessageException, - UntrustedIdentityException -} from "../../src/Exceptions"; -import crypto from "./FakeCrypto"; +"use strict"; +const chai = require("chai"); +const chaiAsPromised = require("chai-as-promised"); +const sinon = require("sinon"); +const co = require("co"); + +const Axolotl = require("../../src/Axolotl"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const Messages = require("../../src/Messages"); +const Exceptions = require("../../src/Exceptions"); +const UnsupportedProtocolVersionException = Exceptions.UnsupportedProtocolVersionException; +const InvalidKeyException = Exceptions.InvalidKeyException; +const InvalidMessageException = Exceptions.InvalidMessageException ; +const DuplicateMessageException = Exceptions.DuplicateMessageException ; +const UntrustedIdentityException = Exceptions.UntrustedIdentityException ; +const crypto = require("./FakeCrypto"); chai.use(chaiAsPromised); var assert = chai.assert; diff --git a/test/unit/FakeCrypto.js b/test/unit/FakeCrypto.js index ae7760e..358f194 100644 --- a/test/unit/FakeCrypto.js +++ b/test/unit/FakeCrypto.js @@ -1,6 +1,7 @@ -import chai from "chai"; -import crypto from "crypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const crypto = require("crypto"); +const co = require("co"); var assert = chai.assert; @@ -81,7 +82,7 @@ var fakeCrypto = { } }; -export default fakeCrypto; +module.exports = fakeCrypto; describe("FakeCrypto", () => { describe("generateKeyPair", () => { diff --git a/test/unit/HKDF.js b/test/unit/HKDF.js index 53d0ad7..a69e6a0 100644 --- a/test/unit/HKDF.js +++ b/test/unit/HKDF.js @@ -1,8 +1,9 @@ -import chai from "chai"; -import HKDF from "../../src/HKDF"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import crypto from "./FakeCrypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const HKDF = require("../../src/HKDF"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const crypto = require("./FakeCrypto"); +const co = require("co"); var assert = chai.assert; diff --git a/test/unit/PromiseInterfaceDecorator.js b/test/unit/PromiseInterfaceDecorator.js index 8e54f05..ede19d9 100644 --- a/test/unit/PromiseInterfaceDecorator.js +++ b/test/unit/PromiseInterfaceDecorator.js @@ -1,6 +1,7 @@ -import chai from "chai"; +"use strict"; +const chai = require("chai"); -import PromiseInterfaceDecorator from "../../src/PromiseInterfaceDecorator"; +const PromiseInterfaceDecorator = require("../../src/PromiseInterfaceDecorator"); var assert = chai.assert; diff --git a/test/unit/Session.js b/test/unit/Session.js index d723991..c47d142 100644 --- a/test/unit/Session.js +++ b/test/unit/Session.js @@ -1,7 +1,8 @@ -import chai from "chai"; -import Session from "../../src/Session"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; +"use strict"; +const chai = require("chai"); +const Session = require("../../src/Session"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); var assert = chai.assert; diff --git a/test/unit/SessionCipher.js b/test/unit/SessionCipher.js index 741132e..bbd2419 100644 --- a/test/unit/SessionCipher.js +++ b/test/unit/SessionCipher.js @@ -1,12 +1,13 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import SessionCipher from "../../src/SessionCipher"; -import SessionState from "../../src/SessionState"; -import Session from "../../src/Session"; -import Messages from "../../src/Messages"; -import {InvalidMessageException} from "../../src/Exceptions"; -import crypto from "./FakeCrypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const chaiAsPromised = require("chai-as-promised"); +const SessionCipher = require("../../src/SessionCipher"); +const SessionState = require("../../src/SessionState"); +const Session = require("../../src/Session"); +const Messages = require("../../src/Messages"); +const InvalidMessageException = require("../../src/Exceptions").InvalidMessageException; +const crypto = require("./FakeCrypto"); +const co = require("co"); chai.use(chaiAsPromised); var assert = chai.assert; diff --git a/test/unit/SessionFactory.js b/test/unit/SessionFactory.js index 2d85307..52d8caa 100644 --- a/test/unit/SessionFactory.js +++ b/test/unit/SessionFactory.js @@ -1,19 +1,12 @@ -import chai from "chai"; -import chaiAsPromise from "chai-as-promised"; -import SessionFactory from "../../src/SessionFactory"; -import Session from "../../src/Session"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import Messages from "../../src/Messages"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import crypto from "./FakeCrypto"; -import { - InvalidMessageException, - DuplicateMessageException, - InvalidKeyException, - ConcurrentUseException, - UnsupportedProtocolVersionException -} from "../../src/Exceptions"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const chaiAsPromise = require("chai-as-promised"); +const SessionFactory = require("../../src/SessionFactory"); +const Session = require("../../src/Session"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const Messages = require("../../src/Messages"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const crypto = require("./FakeCrypto"); chai.use(chaiAsPromise); var assert = chai.assert;
* This allows the consumer to deal only with promises. */ -export default class PromiseInterfaceDecorator { +class PromiseInterfaceDecorator { constructor(impl, methodNames) { methodNames.forEach((methodName) => { if (!impl[methodName]) { @@ -37,3 +38,5 @@ export default class PromiseInterfaceDecorator { Object.freeze(this); } } + +module.exports = PromiseInterfaceDecorator; diff --git a/src/ProtocolConstants.js b/src/ProtocolConstants.js index c9b1e0f..99a2732 100644 --- a/src/ProtocolConstants.js +++ b/src/ProtocolConstants.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,9 +16,7 @@ * along with this program. If not, see . */ -// TODO: Consider exporting these individually - -export default { +module.exports = { currentVersion: 3, // Sizes of various fields diff --git a/src/Ratchet.js b/src/Ratchet.js index a95dfff..ef753d1 100644 --- a/src/Ratchet.js +++ b/src/Ratchet.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,11 +16,11 @@ * along with this program. If not, see . */ -import HKDF from "./HKDF"; -import Chain from "./Chain"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; -import co from "co"; +const HKDF = require("./HKDF"); +const Chain = require("./Chain"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); +const co = require("co"); const messageKeySeed = 0x01; const chainKeySeed = 0x02; @@ -137,4 +138,4 @@ function Ratchet(crypto) { }); } -export default Ratchet; +module.exports = Ratchet; diff --git a/src/Session.js b/src/Session.js index c2022a5..7f3f09a 100644 --- a/src/Session.js +++ b/src/Session.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,9 +16,9 @@ * along with this program. If not, see . */ -import ProtocolConstants from "./ProtocolConstants"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import SessionState from "./SessionState"; +const ProtocolConstants = require("./ProtocolConstants"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const SessionState = require("./SessionState"); /** * Represents the entire state of an Axolotl session. @@ -25,7 +26,7 @@ import SessionState from "./SessionState"; * @param {Session|Object} [session] - another session. If passed, this session will clone its state. * @constructor */ -export default class Session { +class Session { constructor(session) { this.states = []; if (session) { @@ -52,3 +53,5 @@ export default class Session { this.states.splice(index, 1); } } + +module.exports = Session; diff --git a/src/SessionCipher.js b/src/SessionCipher.js index e8b6237..ce2d37d 100644 --- a/src/SessionCipher.js +++ b/src/SessionCipher.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,14 +16,16 @@ * along with this program. If not, see . */ -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; -import Messages from "./Messages"; -import SessionState from "./SessionState"; -import Session from "./Session"; -import Ratchet from "./Ratchet"; -import {InvalidMessageException, DuplicateMessageException} from "./Exceptions"; -import co from "co"; +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); +const Messages = require("./Messages"); +const SessionState = require("./SessionState"); +const Session = require("./Session"); +const Ratchet = require("./Ratchet"); +const co = require("co"); +const Exceptions = require("./Exceptions"); +const InvalidMessageException = Exceptions.InvalidMessageException; +const DuplicateMessageException = Exceptions.DuplicateMessageException; /** * SessionCipher is responsible for encrypting and decrypting messages. @@ -329,26 +332,27 @@ function SessionCipher(crypto) { * @return {Promise.} the next chain for decryption */ var clickMainRatchet = co.wrap(function*(sessionState, theirEphemeralPublicKey) { - var { - rootKey: theirRootKey, - chain: nextReceivingChain - } = yield ratchet.deriveNextRootKeyAndChain(sessionState.rootKey, theirEphemeralPublicKey, + const result1 = yield ratchet.deriveNextRootKeyAndChain(sessionState.rootKey, theirEphemeralPublicKey, sessionState.senderRatchetKeyPair.private); - var ourNewEphemeralKeyPair = yield crypto.generateKeyPair(); - var { - rootKey, - chain: nextSendingChain - } = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, + const theirRootKey = result1.rootKey; + const nextReceivingChain = result1.chain; + const ourNewEphemeralKeyPair = yield crypto.generateKeyPair(); + + const result2 = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, theirEphemeralPublicKey, ourNewEphemeralKeyPair.private); + const rootKey = result2.rootKey; + const nextSendingChain = result2.chain; + sessionState.rootKey = rootKey; sessionState.addReceivingChain(theirEphemeralPublicKey, nextReceivingChain); sessionState.previousCounter = Math.max(sessionState.sendingChain.index - 1, 0); sessionState.sendingChain = nextSendingChain; sessionState.senderRatchetKeyPair = ourNewEphemeralKeyPair; + return nextReceivingChain; }); Object.freeze(self); } -export default SessionCipher; +module.exports = SessionCipher; diff --git a/src/SessionFactory.js b/src/SessionFactory.js index da0da48..241fb80 100644 --- a/src/SessionFactory.js +++ b/src/SessionFactory.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,14 +16,17 @@ * along with this program. If not, see . */ -import WhisperProtos from "./WhisperProtos"; -import ArrayBufferUtils from "./ArrayBufferUtils"; -import Messages from "./Messages"; -import Ratchet from "./Ratchet"; -import SessionState from "./SessionState"; -import Session from "./Session"; -import {InvalidKeyException, UnsupportedProtocolVersionException, UntrustedIdentityException} from "./Exceptions"; -import co from "co"; +const WhisperProtos = require("./WhisperProtos"); +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const Messages = require("./Messages"); +const Ratchet = require("./Ratchet"); +const SessionState = require("./SessionState"); +const Session = require("./Session"); +const co = require("co"); +const Exceptions = require("./Exceptions"); +const InvalidKeyException = Exceptions.InvalidKeyException; +const UnsupportedProtocolVersionException = Exceptions.UnsupportedProtocolVersionException; +const UntrustedIdentityException = Exceptions.UntrustedIdentityException; function SessionFactory(crypto, store) { const self = this; @@ -146,7 +150,7 @@ function SessionFactory(crypto, store) { //self.createSessionFromKeyExchange = (toIdentity, keyExchange) => {}; var initializeAliceSession = co.wrap(function*(parameters) { - var sendingRatchetKeyPair = yield crypto.generateKeyPair(); + var senderRatchetKeyPair = yield crypto.generateKeyPair(); var agreements = [ crypto.calculateAgreement(parameters.theirSignedPreKey, parameters.ourIdentityKeyPair.private), @@ -157,23 +161,21 @@ function SessionFactory(crypto, store) { agreements.push(crypto.calculateAgreement(parameters.theirOneTimePreKey, parameters.ourBaseKeyPair.private)); } - var { - rootKey: theirRootKey, - chain: receivingChain - } = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); - var { - rootKey, - chain: sendingChain - } = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, parameters.theirRatchetKey, - sendingRatchetKeyPair.private); + const initChain = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const theirRootKey = initChain.rootKey; + const receivingChain = initChain.chain; + const nextChain = yield ratchet.deriveNextRootKeyAndChain(theirRootKey, parameters.theirRatchetKey, + senderRatchetKeyPair.private); + const rootKey = nextChain.rootKey; + const sendingChain = nextChain.chain; var sessionState = new SessionState({ sessionVersion: parameters.sessionVersion, remoteIdentityKey: parameters.theirIdentityKey, localIdentityKey: parameters.ourIdentityKeyPair.public, - rootKey: rootKey, - sendingChain: sendingChain, - senderRatchetKeyPair: sendingRatchetKeyPair + rootKey, + sendingChain, + senderRatchetKeyPair }); sessionState.addReceivingChain(parameters.theirRatchetKey, receivingChain); return sessionState; @@ -191,10 +193,9 @@ function SessionFactory(crypto, store) { parameters.ourOneTimePreKeyPair.private)); } - var { - rootKey, - chain: sendingChain - } = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const initChain = yield ratchet.deriveInitialRootKeyAndChain(parameters.sessionVersion, yield agreements); + const rootKey = initChain.rootKey; + const sendingChain = initChain.chain; return new SessionState({ sessionVersion: parameters.sessionVersion, @@ -209,4 +210,4 @@ function SessionFactory(crypto, store) { Object.freeze(self); } -export default SessionFactory; +module.exports = SessionFactory; diff --git a/src/SessionState.js b/src/SessionState.js index 789c89b..e9e7d0a 100644 --- a/src/SessionState.js +++ b/src/SessionState.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,8 +16,8 @@ * along with this program. If not, see . */ -import ArrayBufferUtils from "./ArrayBufferUtils"; -import ProtocolConstants from "./ProtocolConstants"; +const ArrayBufferUtils = require("./ArrayBufferUtils"); +const ProtocolConstants = require("./ProtocolConstants"); var makeReadonly = (obj, key) => { Object.defineProperty(obj, key, { @@ -27,7 +28,7 @@ var makeReadonly = (obj, key) => { /** * A serialisable representation of a session "state". Sessions can contain multiple states. */ -export default class SessionState { +class SessionState { /** * * @param {object} parameters - initial parameters @@ -86,3 +87,5 @@ export default class SessionState { } } } + +module.exports = SessionState; diff --git a/src/Store.js b/src/Store.js index fea4caf..1cde6f8 100644 --- a/src/Store.js +++ b/src/Store.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (C) 2015 Joe Bandenburg * @@ -15,7 +16,7 @@ * along with this program. If not, see . */ -import PromiseInterfaceDecorator from "./PromiseInterfaceDecorator"; +const PromiseInterfaceDecorator = require("./PromiseInterfaceDecorator"); var methodNames = [ "getLocalIdentityKeyPair", @@ -24,8 +25,10 @@ var methodNames = [ "getLocalPreKeyPair" ]; -export default class Store extends PromiseInterfaceDecorator { +class Store extends PromiseInterfaceDecorator { constructor(store) { super(store, methodNames); } } + +module.exports = Store; diff --git a/src/WhisperProtos.js b/src/WhisperProtos.js index 76dcc7b..06b3cdc 100644 --- a/src/WhisperProtos.js +++ b/src/WhisperProtos.js @@ -1,3 +1,4 @@ +"use strict"; // Generated file. DO NOT EDIT!! module.exports = require("protobufjs").newBuilder({})["import"]({ "package": "textsecure", diff --git a/test/integration/node/axolotl.js b/test/integration/node/axolotl.js index 13bda11..3a00044 100644 --- a/test/integration/node/axolotl.js +++ b/test/integration/node/axolotl.js @@ -1,6 +1,7 @@ +"use strict"; var assert = require("assert"); -var ByteBuffer = require("ByteBuffer"); -var axolotl = require("../../../dist/axolotl"); +var ByteBuffer = require("bytebuffer"); +var axolotl = require("../../.."); var fromHex = function(hex) { return ByteBuffer.fromHex(hex).toArrayBuffer(); diff --git a/test/integration/web/axolotl.js b/test/integration/web/axolotl.js deleted file mode 100644 index 4b7f993..0000000 --- a/test/integration/web/axolotl.js +++ /dev/null @@ -1,48 +0,0 @@ -var fromHex = function(hex) { - return window.dcodeIO.ByteBuffer.fromHex(hex).toArrayBuffer(); -}; - -var state = { - states: [{ - sessionVersion: 3, - remoteIdentityKey: fromHex("0534ad091121f387dbf22e56e7a7c7e6f6964ed7ba6ed1e092d3870b6285c4eb13"), - localIdentityKey: fromHex("052e978dcd2f616c2275ff28c740645c2ceec9a7c73c712dd2d55e4b6aa3ec5f44"), - pendingPreKey: { - preKeyId: 0, - signedPreKeyId: 0, - baseKey: fromHex("052d2c043f7035101c596a1febb78fc4a8d8dff07db66449530ce1a3396d954f6c") - }, - localRegistrationId: 1083, - theirBaseKey: fromHex("050741319370838cc8e2e590253024697b3837376bd70699f48ca23147c7088f08"), - rootKey: fromHex("f0006715ba617382e62d3e074a575915e6b2289e4df6dee12fac04f4465812"), - sendingChain: { - key: fromHex("de215ccf67f7e13e57d7fac761b87eee20bdc6c1eb9479b2ac83766016a3de64"), - index: 1, - messageKeys: [] - }, - senderRatchetKeyPair: { - public: fromHex("059b1ec3e47026d098ef617b9085459c9ae5dff61067d4d797f2318ac943236957"), - private: fromHex("c842eebc48d101bc084a2f725e3f1a145829575fff108a7cd5387ae62e55267a") - }, - previousCounter: 0 - }] -}; - -describe("axolotl integration web", function() { - var stub = function() { return 1; }; - it("produces the expected output", function() { - var expectedCiphertext = "3328bb08080030001221052d2c043f7035101c596a1febb78fc4a8d8dff07db66449530ce1a3396d954" + - "f6c1a21052e978dcd2f616c2275ff28c740645c2ceec9a7c73c712dd2d55e4b6aa3ec5f442242330a21059b1ec3e47026d098ef6" + - "17b9085459c9ae5dff61067d4d797f2318ac943236957100118002210ef3c9236a9c9afba0f72ad6eefe739b27b54a8b565750a5e"; - var axol = new window.axolotl({ - getLocalIdentityKeyPair: stub, - getLocalRegistrationId: stub, - getLocalSignedPreKeyPair: stub, - getLocalPreKeyPair: stub - }); - return axol.encryptMessage(state, new Uint8Array([1, 2, 3, 4]).buffer).then(function(result) { - var actualBody = window.dcodeIO.ByteBuffer.wrap(result.body).toHex(); - assert.equal(actualBody, expectedCiphertext); - }); - }); -}); diff --git a/test/unit/ArrayBufferUtils.js b/test/unit/ArrayBufferUtils.js index 37cf391..6423655 100644 --- a/test/unit/ArrayBufferUtils.js +++ b/test/unit/ArrayBufferUtils.js @@ -1,5 +1,6 @@ -import chai from "chai"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; +"use strict"; +const chai = require("chai"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); var assert = chai.assert; diff --git a/test/unit/Axolotl.js b/test/unit/Axolotl.js index 3dd0ae4..c494cef 100644 --- a/test/unit/Axolotl.js +++ b/test/unit/Axolotl.js @@ -1,20 +1,20 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import sinon from "sinon"; -import co from "co"; - -import Axolotl from "../../src/Axolotl"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import Messages from "../../src/Messages"; -import { - UnsupportedProtocolVersionException, - InvalidKeyException, - InvalidMessageException, - DuplicateMessageException, - UntrustedIdentityException -} from "../../src/Exceptions"; -import crypto from "./FakeCrypto"; +"use strict"; +const chai = require("chai"); +const chaiAsPromised = require("chai-as-promised"); +const sinon = require("sinon"); +const co = require("co"); + +const Axolotl = require("../../src/Axolotl"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const Messages = require("../../src/Messages"); +const Exceptions = require("../../src/Exceptions"); +const UnsupportedProtocolVersionException = Exceptions.UnsupportedProtocolVersionException; +const InvalidKeyException = Exceptions.InvalidKeyException; +const InvalidMessageException = Exceptions.InvalidMessageException ; +const DuplicateMessageException = Exceptions.DuplicateMessageException ; +const UntrustedIdentityException = Exceptions.UntrustedIdentityException ; +const crypto = require("./FakeCrypto"); chai.use(chaiAsPromised); var assert = chai.assert; diff --git a/test/unit/FakeCrypto.js b/test/unit/FakeCrypto.js index ae7760e..358f194 100644 --- a/test/unit/FakeCrypto.js +++ b/test/unit/FakeCrypto.js @@ -1,6 +1,7 @@ -import chai from "chai"; -import crypto from "crypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const crypto = require("crypto"); +const co = require("co"); var assert = chai.assert; @@ -81,7 +82,7 @@ var fakeCrypto = { } }; -export default fakeCrypto; +module.exports = fakeCrypto; describe("FakeCrypto", () => { describe("generateKeyPair", () => { diff --git a/test/unit/HKDF.js b/test/unit/HKDF.js index 53d0ad7..a69e6a0 100644 --- a/test/unit/HKDF.js +++ b/test/unit/HKDF.js @@ -1,8 +1,9 @@ -import chai from "chai"; -import HKDF from "../../src/HKDF"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import crypto from "./FakeCrypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const HKDF = require("../../src/HKDF"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const crypto = require("./FakeCrypto"); +const co = require("co"); var assert = chai.assert; diff --git a/test/unit/PromiseInterfaceDecorator.js b/test/unit/PromiseInterfaceDecorator.js index 8e54f05..ede19d9 100644 --- a/test/unit/PromiseInterfaceDecorator.js +++ b/test/unit/PromiseInterfaceDecorator.js @@ -1,6 +1,7 @@ -import chai from "chai"; +"use strict"; +const chai = require("chai"); -import PromiseInterfaceDecorator from "../../src/PromiseInterfaceDecorator"; +const PromiseInterfaceDecorator = require("../../src/PromiseInterfaceDecorator"); var assert = chai.assert; diff --git a/test/unit/Session.js b/test/unit/Session.js index d723991..c47d142 100644 --- a/test/unit/Session.js +++ b/test/unit/Session.js @@ -1,7 +1,8 @@ -import chai from "chai"; -import Session from "../../src/Session"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; +"use strict"; +const chai = require("chai"); +const Session = require("../../src/Session"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); var assert = chai.assert; diff --git a/test/unit/SessionCipher.js b/test/unit/SessionCipher.js index 741132e..bbd2419 100644 --- a/test/unit/SessionCipher.js +++ b/test/unit/SessionCipher.js @@ -1,12 +1,13 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import SessionCipher from "../../src/SessionCipher"; -import SessionState from "../../src/SessionState"; -import Session from "../../src/Session"; -import Messages from "../../src/Messages"; -import {InvalidMessageException} from "../../src/Exceptions"; -import crypto from "./FakeCrypto"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const chaiAsPromised = require("chai-as-promised"); +const SessionCipher = require("../../src/SessionCipher"); +const SessionState = require("../../src/SessionState"); +const Session = require("../../src/Session"); +const Messages = require("../../src/Messages"); +const InvalidMessageException = require("../../src/Exceptions").InvalidMessageException; +const crypto = require("./FakeCrypto"); +const co = require("co"); chai.use(chaiAsPromised); var assert = chai.assert; diff --git a/test/unit/SessionFactory.js b/test/unit/SessionFactory.js index 2d85307..52d8caa 100644 --- a/test/unit/SessionFactory.js +++ b/test/unit/SessionFactory.js @@ -1,19 +1,12 @@ -import chai from "chai"; -import chaiAsPromise from "chai-as-promised"; -import SessionFactory from "../../src/SessionFactory"; -import Session from "../../src/Session"; -import ArrayBufferUtils from "../../src/ArrayBufferUtils"; -import Messages from "../../src/Messages"; -import ProtocolConstants from "../../src/ProtocolConstants"; -import crypto from "./FakeCrypto"; -import { - InvalidMessageException, - DuplicateMessageException, - InvalidKeyException, - ConcurrentUseException, - UnsupportedProtocolVersionException -} from "../../src/Exceptions"; -import co from "co"; +"use strict"; +const chai = require("chai"); +const chaiAsPromise = require("chai-as-promised"); +const SessionFactory = require("../../src/SessionFactory"); +const Session = require("../../src/Session"); +const ArrayBufferUtils = require("../../src/ArrayBufferUtils"); +const Messages = require("../../src/Messages"); +const ProtocolConstants = require("../../src/ProtocolConstants"); +const crypto = require("./FakeCrypto"); chai.use(chaiAsPromise); var assert = chai.assert;