Skip to content

Commit

Permalink
refactor(proteus,cryptobox): Rewrite with async libsodium (#253)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
* Some functions are now async/await
* Proteus rewritten in TypeScript
  • Loading branch information
ffflorian authored Feb 9, 2018
1 parent 4d903ec commit 4a3c0f0
Show file tree
Hide file tree
Showing 126 changed files with 5,451 additions and 5,439 deletions.
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
**/bin/**
**/bower_components/**
**/dist/**
**/node_modules/**
**/bower_components/**
CHANGELOG.md
package.json
packages/react-ui-kit/*.js
18 changes: 6 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,23 @@
"prettier": "1.10.2"
},
"lint-staged": {
"*.{js,jsx}": ["eslint --ignore-path .prettierignore --fix", "git add"],
"*.json": ["prettier --write", "git add"],
"*.md": ["prettier --write", "git add"],
"*.scss": ["prettier --write", "git add"],
"*.ts": ["prettier --write", "git add"]
"*.{js,jsx}": ["eslint --fix", "git add"],
"*.{json,md,scss,ts}": ["prettier --write", "git add"]
},
"private": true,
"scripts": {
"boot": "lerna bootstrap --reject-cycles",
"clear": "lerna run clear",
"dist": "yarn clear && lerna run dist",
"fix": "yarn fix:docs && yarn fix:config && yarn fix:style && yarn fix:script",
"fix:config": "prettier --write **/*.json",
"fix:docs": "prettier --ignore-path .gitignore --write **/*.md",
"fix": "yarn fix:assets && yarn fix:script",
"fix:assets": "prettier --write **/*.{json,md,scss}",
"fix:jsScript": "yarn test:jsScript --fix",
"fix:script": "yarn fix:jsScript && yarn fix:tsScript",
"fix:style": "prettier --write **/*.scss",
"fix:tsScript": "prettier --write **/*.ts",
"precommit": "lint-staged",
"test": "yarn && yarn test:jsScript && lerna run test",
"test:jsScript": "eslint --ignore-path .gitignore --ignore-path .prettierignore **/*.{js,jsx}",
"release":
"yarn test && lerna run test:longrunning --scope @wireapp/proteus && lerna publish -m \"chore: Publish\" --conventional-commits --loglevel=verbose --exact --allow-branch=master --registry=https://registry.npmjs.org/ --yes"
"test:jsScript": "eslint --ignore-path .gitignore **/*.{js,jsx}",
"release": "yarn test && lerna run test:longrunning --scope @wireapp/proteus && lerna publish -m \"chore: Publish\" --conventional-commits --loglevel=verbose --exact --allow-branch=master --registry=https://registry.npmjs.org/ --yes"
},
"workspaces": ["packages/*"]
}
2 changes: 1 addition & 1 deletion packages/cbor/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta charset="UTF-8" />
<title>Demo</title>
<link rel="shortcut icon" href="data:image/x-icon;" type="image/x-icon" />
<script src="./window/@wireapp/cbor.js"></script>
<script src="./dist/window/@wireapp/cbor.js"></script>
</head>
<body>
<script>
Expand Down
4 changes: 2 additions & 2 deletions packages/cbor/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ module.exports = {
filename: `${__dirname}/${pkg.main}`,
},
output: {
filename: `${pkg.name}.js`,
filename: `${pkg.name.substr(pkg.name.indexOf('/') + 1)}.js`,
library: 'CBOR',
libraryTarget: 'var',
path: `${__dirname}/dist/window`,
path: `${__dirname}/dist`,
},
performance: {
hints: 'warning',
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"karma-jasmine-diff-reporter": "1.1.1",
"karma-sourcemap-loader": "0.3.7",
"rimraf": "2.6.2",
"typescript": "2.6.1",
"typescript": "2.7.1",
"webpack": "3.10.0"
},
"description": "Wire for Web's communication core.",
Expand All @@ -40,7 +40,7 @@
"start": "rimraf .tmp && yarn dist && node index.js",
"test": "yarn dist && yarn test:node && yarn test:browser",
"test:browser": "exit 0",
"test:node": "cross-env JASMINE_CONFIG_PATH=src/test/node/support/jasmine.json jasmine",
"test:node": "jasmine --config=src/test/node/support/jasmine.json",
"prepare": "yarn dist"
},
"types": "./dist/commonjs/index.d.ts",
Expand Down
31 changes: 17 additions & 14 deletions packages/core/src/main/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
ConversationEventType,
OTRMessageAdd,
} from '@wireapp/api-client/dist/commonjs/conversation/event/';
import {MemoryEngine} from '@wireapp/store-engine/dist/commonjs/engine/';
import {ClientClassification, ClientType, NewClient, RegisteredClient} from '@wireapp/api-client/dist/commonjs/client/';
import {LoginSanitizer} from './auth/';
import {RecordNotFoundError} from '@wireapp/store-engine/dist/commonjs/engine/error/';
Expand Down Expand Up @@ -175,20 +174,24 @@ export default class Account extends EventEmitter {
return this.service.crypto
.createCryptobox()
.then((serializedPreKeys: Array<PreKey>) => {
const newClient: NewClient = {
class: clientClassification,
cookie: cookieLabel,
lastkey: this.service.crypto.cryptobox.serialize_prekey(this.service.crypto.cryptobox.lastResortPreKey),
password: String(loginData.password),
prekeys: serializedPreKeys,
sigkeys: {
enckey: 'Wuec0oJi9/q9VsgOil9Ds4uhhYwBT+CAUrvi/S9vcz0=',
mackey: 'Wuec0oJi9/q9VsgOil9Ds4uhhYwBT+CAUrvi/S9vcz0=',
},
type: loginData.persist ? ClientType.PERMANENT : ClientType.TEMPORARY,
};
if (this.service.crypto.cryptobox.lastResortPreKey) {
const newClient: NewClient = {
class: clientClassification,
cookie: cookieLabel,
lastkey: this.service.crypto.cryptobox.serialize_prekey(this.service.crypto.cryptobox.lastResortPreKey),
password: String(loginData.password),
prekeys: serializedPreKeys,
sigkeys: {
enckey: 'Wuec0oJi9/q9VsgOil9Ds4uhhYwBT+CAUrvi/S9vcz0=',
mackey: 'Wuec0oJi9/q9VsgOil9Ds4uhhYwBT+CAUrvi/S9vcz0=',
},
type: loginData.persist ? ClientType.PERMANENT : ClientType.TEMPORARY,
};

return newClient;
return newClient;
} else {
throw new Error('Cryptobox got initialized without a last resort PreKey.');
}
})
.then((newClient: NewClient) => this.apiClient.client.api.postClient(newClient))
.then((client: RegisteredClient) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/main/crypto/CryptographyService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Cryptobox, store} from '@wireapp/cryptobox';
import {Decoder, Encoder} from 'bazinga64';
import {RegisteredClient} from '@wireapp/api-client/dist/commonjs/client/';
import {UserPreKeyBundleMap} from '@wireapp/api-client/dist/commonjs/user/';
import * as Proteus from '@wireapp/proteus';
import * as ProteusKeys from '@wireapp/proteus/dist/keys/';
import * as auth from '@wireapp/api-client/dist/commonjs/auth/';
import {SessionPayloadBundle} from '../crypto/';
import {OTRRecipients} from '@wireapp/api-client/dist/commonjs/conversation/';
Expand All @@ -19,11 +19,11 @@ export default class CryptographyService {
}

public createCryptobox(): Promise<Array<auth.PreKey>> {
return this.cryptobox.create().then((initialPreKeys: Array<Proteus.keys.PreKey>) => {
return this.cryptobox.create().then((initialPreKeys: Array<ProteusKeys.PreKey>) => {
return initialPreKeys
.map(preKey => {
const preKeyJson: auth.PreKey = this.cryptobox.serialize_prekey(preKey);
if (preKeyJson.id !== Proteus.keys.PreKey.MAX_PREKEY_ID) {
if (preKeyJson.id !== ProteusKeys.PreKey.MAX_PREKEY_ID) {
return preKeyJson;
}
return {id: -1, key: ''};
Expand Down Expand Up @@ -94,7 +94,7 @@ export default class CryptographyService {
}

public loadClient(): Promise<RegisteredClient> {
return this.cryptobox.load().then((initialPreKeys: Array<Proteus.keys.PreKey>) => {
return this.cryptobox.load().then((initialPreKeys: Array<ProteusKeys.PreKey>) => {
return this.storeEngine.read<RegisteredClient>(
CryptographyService.STORES.CLIENTS,
store.CryptoboxCRUDStore.KEYS.LOCAL_IDENTITY
Expand Down
32 changes: 15 additions & 17 deletions packages/core/src/test/node/spec/crypto/CryptographyService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ const Proteus = require('@wireapp/proteus');
const {crypto} = require('@wireapp/core');
const {MemoryEngine} = require('@wireapp/store-engine').StoreEngine;

let cryptographyService;
let aliceLastResortPreKey;
let bob;

describe('CryptographyService', () => {
let cryptographyService;
let aliceLastResortPreKey;
let bob;

beforeEach(done => {
cryptographyService = new crypto.CryptographyService(new MemoryEngine('alice'));
cryptographyService.cryptobox
Expand Down Expand Up @@ -61,22 +61,20 @@ describe('CryptographyService', () => {
});

describe('"decrypt"', () => {
it('decrypts a Base64-encoded cipher message.', done => {
it('decrypts a Base64-encoded cipher message.', async done => {
const alicePublicKey = cryptographyService.cryptobox.identity.public_key;
const publicPreKeyBundle = Proteus.keys.PreKeyBundle.new(alicePublicKey, aliceLastResortPreKey);
const text = 'Hello Alice!';
bob
.encrypt('alice-user-id@alice-client-id', text, publicPreKeyBundle.serialise())
.then(encryptedPreKeyMessage => {
const encodedPreKeyMessage = bazinga64.Encoder.toBase64(encryptedPreKeyMessage).asString;
return cryptographyService.decrypt('bob-user-id@bob-client-id', encodedPreKeyMessage);
})
.then(decodedMessageBuffer => {
const plaintext = Buffer.from(decodedMessageBuffer).toString('utf8');
expect(plaintext).toBe(text);
done();
})
.catch(done.fail);
const encryptedPreKeyMessage = await bob.encrypt(
'alice-user-id@alice-client-id',
text,
publicPreKeyBundle.serialise()
);
const encodedPreKeyMessage = bazinga64.Encoder.toBase64(encryptedPreKeyMessage).asString;
const decodedMessageBuffer = await cryptographyService.decrypt('bob-user-id@bob-client-id', encodedPreKeyMessage);
const plaintext = Buffer.from(decodedMessageBuffer).toString('utf8');
expect(plaintext).toBe(text);
done();
});
});

Expand Down
3 changes: 2 additions & 1 deletion packages/core/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"compilerOptions": {
"outDir": "dist/commonjs",
"rootDir": "src/main"
"rootDir": "src/main",
"strictPropertyInitialization": false
},
"exclude": ["dist/commonjs", "node_modules"],
"extends": "../../configs/tsconfig.json"
Expand Down
17 changes: 0 additions & 17 deletions packages/cryptobox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,3 @@ yarn add @wireapp/cryptobox
#### Node.js

* [demo.js](./demo.js)

### Development

#### Testing

Run individual test:

```bash
# Example
gulp test_browser --file "common/CacheSpec.js"
```

Run all tests (in Chrome & Node.js):

```bash
yarn test
```
10 changes: 4 additions & 6 deletions packages/cryptobox/bower.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
{
"dependencies": {
"dexie": "1.5.1",
"libsodium.js": "0.5.4",
"wire-webapp-lru-cache": "2.0.0",
"wire-webapp-proteus": "5.2.0"
"dexie": "2.0.1",
"libsodium.js": "0.7.3"
},
"devDependencies": {
"logdown": "2.2.0"
"logdown": "3.2.3"
},
"license": "GPL-3.0",
"main": ["dist/window/wire-webapp-cryptobox.js"],
"main": ["dist/cryptobox.js"],
"name": "wire-webapp-cryptobox"
}
7 changes: 2 additions & 5 deletions packages/cryptobox/bower_assets.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"dynamic": {
"dexie@copy": ["dexie/dist/dexie.js"],
"libsodium.js@copy": ["libsodium.js/dist/browsers-sumo/combined/sodium.js"],
"logdown@copy": ["logdown/dist/logdown.js"],
"wire-webapp-cbor@copy": ["wire-webapp-cbor/dist/window/wire-webapp-cbor.js"],
"wire-webapp-lru-cache@copy": ["wire-webapp-lru-cache/dist/window/LRUCache.js"],
"wire-webapp-proteus@copy": ["wire-webapp-proteus/dist/window/proteus.js"]
"libsodium.js@copy": ["libsodium.js/dist/browsers-sumo/sodium.js"],
"logdown@copy": ["logdown/dist/logdown.js"]
}
}
14 changes: 8 additions & 6 deletions packages/cryptobox/demo.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<!DOCTYPE html>
<!-- Wire, Copyright (C) 2016 Wire Swiss GmbH -->
<!-- Wire, Copyright (C) 2018 Wire Swiss GmbH -->
<html>
<head>
<meta charset="UTF-8" />
<title>Demo</title>
<link rel="shortcut icon" href="data:image/x-icon;" type="image/x-icon" />
<script src="dist/lib/dynamic/logdown/logdown.js"></script>
<script src="dist/lib/dynamic/dexie/dexie.js"></script>
<script src="dist/lib/dynamic/libsodium.js/sodium.js"></script>
<script src="dist/lib/dynamic/logdown/logdown.js"></script>
<script src="dist/lib/dynamic/wire-webapp-cbor/wire-webapp-cbor.js"></script>
<script src="dist/lib/dynamic/wire-webapp-proteus/proteus.js"></script>
<script src="dist/window/wire-webapp-cryptobox.js"></script>
<script src="../cbor/dist/cbor.js"></script>
<script src="../proteus/dist/proteus.js"></script>
<script src="./dist/cryptobox.js"></script>
</head>
<body>
<script>
const logger = new Logdown({prefix: 'Demo', alignOutput: true});
window.localStorage.debug = '*';

const logger = window.logdown('Demo');
logger.log(`Testing Cryptobox v${cryptobox.Cryptobox.prototype.VERSION}`);

const alice = {
Expand Down
37 changes: 3 additions & 34 deletions packages/cryptobox/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,10 @@ const bower = require('gulp-bower');
const browserSync = require('browser-sync').create();
const clean = require('gulp-clean');
const gulp = require('gulp');
const gulpif = require('gulp-if');
const gutil = require('gulp-util');
const jasmine = require('gulp-jasmine');
const karma = require('karma');
const merge = require('merge2');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const replace = require('gulp-replace');
const runSequence = require('run-sequence');
const ts = require('gulp-typescript');
const tsProjectNode = ts.createProject('tsconfig.json');
Expand Down Expand Up @@ -77,14 +74,7 @@ gulp.task('build_ts_node', () => {

gutil.log(gutil.colors.yellow(`Disable log statements: ${disableLogging}`));

return merge([
tsResult.dts.pipe(gulp.dest('dist/')),
tsResult.js
.pipe(replace('exports.default = {', 'module.exports = {'))
.pipe(gulpif(disableLogging, replace(/(const|var) Logdown[^\n]*/gi, '')))
.pipe(gulpif(disableLogging, replace(/[_]?this.logger[^\n]*/gim, '')))
.pipe(gulp.dest('dist/commonjs')),
]);
return merge([tsResult.dts.pipe(gulp.dest('dist/')), tsResult.js.pipe(gulp.dest('dist/commonjs'))]);
});

gulp.task('default', ['dist'], () => {
Expand Down Expand Up @@ -120,7 +110,7 @@ gulp.task('install_bower_assets', ['install_bower'], () =>
);

gulp.task('test', done => {
runSequence('test_node', 'test_browser', done);
done();
});

gulp.task('test_browser', done => {
Expand All @@ -138,7 +128,7 @@ gulp.task('test_browser', done => {
// Application
'dist/window/**/*.js',
// Tests
file ? `test/${file}` : 'test/{browser,common}/**/*Spec.js',
file ? `test/${file}` : 'test/**/*Spec.{browser,common}.js',
],
logLevel: file ? 'debug' : 'info',
},
Expand All @@ -147,24 +137,3 @@ gulp.task('test_browser', done => {

server.start();
});

gulp.task('test_node', () => {
const filePosition = 4;

gutil.log(gutil.colors.yellow('Running tests on Node.js:'));

const file = process.argv[filePosition];

let tests = ['test/common/**/*Spec.js', 'test/node/**/*Spec.js'];

if (file) {
tests = [`test/${file}`];
}

return gulp.src(tests).pipe(
jasmine({
random: true,
stopSpecOnExpectationFailure: true,
})
);
});
Loading

0 comments on commit 4a3c0f0

Please sign in to comment.