Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Flow example #49

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"plugins": [
"transform-flow-strip-types",
"transform-es2015-modules-amd"
],
"ignore": [
"./login/frontend/static/js/bad_password_bloom_data.js"
]
}
7 changes: 7 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[ignore]

[include]

[libs]

[options]
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
*.pyc

node_modules
build/
yarn-error.log
.vscode/settings.json
21 changes: 21 additions & 0 deletions FLOW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Flow typing the code base

This is an ongoing process. You will need [flow](https://flow.org/) and yarn. To get started:

```
yarn install
node_modules/.bin/babel login/ --watch --out-dir build
```

# Contributing

To start we're trying to type the code base without making any large
feature changes.

This is best done by adding a `// @flow` line to the beginning of a
file, followed by fixing the resulting fallout of the `flow` command.

# random

* mark external libraries with TODO and EXTERNAL
* `nix-shell -p python2 --command "yarn install"`
5 changes: 5 additions & 0 deletions api/js/cli/assert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function assert(expression: bool) {
if (!expression) {
throw new Error('Assertion failed');
}
}
16 changes: 6 additions & 10 deletions api/js/cli/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* 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,
* This program is distributed in the hope that ist will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
Expand Down Expand Up @@ -52,15 +52,11 @@ Decrypting:

/** @suppress{duplicate} */
var mitro = mitro || {};
/** @suppress{duplicate} */
var keyczar = keyczar || require('keyczarjs');

// TODO(flow): require keyczar

(function() {
mitro.crypto = {};
if (typeof module !== 'undefined' && module.exports) {
// define node.js module
mitro.cache = require('./lru_cache.js');
module.exports = mitro.crypto;
}
var crypto = mitro.crypto;

/** Only for type checking. TODO: Use this? Make it an interface?
Expand Down Expand Up @@ -162,7 +158,7 @@ function _makeKeyNoMemo(encryptionKey, signingKey) {
}
return memoResult;
};

key.verify = function(message, signature) {
return signingKey.verify(message, signature);
};
Expand Down Expand Up @@ -204,7 +200,7 @@ function _makeKeyNoMemo(encryptionKey, signingKey) {
var memoKey = mitro.cache.makeKey('decrypt', message);
var memoResult = cache.getItem(memoKey);
if (memoResult) {

} else {
memoResult = key.decryptNoMemo(message);
cache.setItem(memoKey, memoResult);
Expand Down
6 changes: 4 additions & 2 deletions api/js/cli/kew.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

// Original source: https://github.com/Obvious/kew
// License: MIT
// Now: https://github.com/Medium/kew
// TODO(tom): EXTERNAL library

// Export all variables in the kew namespace in the browser
var kew = kew || {};
Expand Down Expand Up @@ -567,7 +569,7 @@ kew.all = function(promises) {
var promise = new kew.Promise();
var counter = promises.length;

/*The below functions have been pulled out of the for loop to prevent
/*The below functions have been pulled out of the for loop to prevent
function creation in a loop*/
var decrement = function decrementAllCounter() {
counter--;
Expand Down Expand Up @@ -624,7 +626,7 @@ function allSettled(promises) {
var resolution = function(){
if ((--counter) === 0) promise.resolve(outputs);
};

for (var i = 0; i < promises.length; i += 1) {
if (!promises[i] || !isPromiseLike(promises[i])) {
replaceElFulfilled(outputs, i, promises[i]);
Expand Down
94 changes: 31 additions & 63 deletions api/js/cli/keycache.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @flow
/*
* *****************************************************************************
* Copyright (c) 2012, 2013, 2014 Lectorius, Inc.
Expand All @@ -24,57 +25,29 @@
* *****************************************************************************
*/

/** @suppress{duplicate} */
var forge = forge || require('node-forge');
/** @suppress{duplicate} */
var mitro = mitro || {};

// Cache for crypto keys. Includes code to fill it in the background.
(function() {
"use strict";
mitro.keycache = {};

var _Worker = null;
// define window.mitro.keycache for the browser
if(typeof(window) !== 'undefined') {
_Worker = (typeof(unsafeWindow) !== 'undefined') ? unsafeWindow.Worker : Worker;
}
// define node.js module
else if(typeof(module) !== 'undefined' && module.exports) {
mitro.crappycrypto = require('./crappycrypto.js');
mitro.crypto = require('./crypto.js');
module.exports = mitro.keycache;
try {
_Worker = require('webworker-threads').Worker;
} catch (e) {
// failed to load webworkers; ignore if DISABLE_WEBWORKERS env var is set
if (!process.env.DISABLE_WEBWORKERS) {
throw e;
}
}
}
import * as crypto from "./crypto";
import * as forge from "../../../node_modules/node-forge/js/forge";
import * as background_api from "../../../login/common/background_api";

// ideally keep the cache fill with this many keys
mitro.keycache.CACHE_TARGET = 2;
const CACHE_TARGET = 2;

// TODO: Define this in one place; maybe here and not in mitro_lib?
var crypto = mitro.crypto;
mitro.keycache.useCrappyCrypto = function() {
if (!mitro.crappycrypto) {
throw new Error('crappycrypto does not exist?');
type Cache = {
push: (key: string) => void;
setPopListener: (listener: any) => void;
size: () => number;
getNewRSAKeysAsync: (numKeys: number, onSuccess: any, onError: any) => void;
}
crypto = mitro.crappycrypto;
};


mitro.keycache.MakeKeyCache = function() {
// TODO(tom): migrate to class
export const MakeKeyCache = function(): Cache {
var keys = [];
var pushListener = null;
var popListener = null;
var keyLimit = mitro.keycache.CACHE_TARGET;
var keyLimit = CACHE_TARGET;
var keyLimitReachedCallback = null;

var cache = {
var cache: any = {
size: function() {
return keys.length;
},
Expand All @@ -87,7 +60,7 @@ mitro.keycache.MakeKeyCache = function() {
keyLimitReachedCallback();
keyLimitReachedCallback = null;
}
keyLimit = mitro.keycache.CACHE_TARGET;
keyLimit = CACHE_TARGET;
}
if (pushListener !== null) {
pushListener(cache);
Expand Down Expand Up @@ -144,12 +117,11 @@ mitro.keycache.MakeKeyCache = function() {
keyLimit = count;
keyLimitReachedCallback = onSuccess;
for (var i = cache.size(); i < count; ++i) {
popListener();
if (popListener !== null) popListener(cache);
}
}
};


cache.getNewRSAKeysAsync = function(numKeys, onSuccess, onError) {
try {
var rval = [];
Expand All @@ -176,27 +148,26 @@ mitro.keycache.MakeKeyCache = function() {

/** Returns a string with random bytes from forge.random.getBytesSync. */
// TODO: Remove this
mitro.keycache.getEntropyBytes = function(numBytes) {
export const getEntropyBytes = function(numBytes: number) {
return forge.random.seedFileSync(numBytes);
};



mitro.keycache.startFiller = function(cache) {
export const startFiller = function(cache: Cache) {
// start a worker: get it to fill the cache
var background_worker = new _Worker('keycache_webworker.js');

var type = 'keyczar';
if (crypto == mitro.crappycrypto) {
type = 'crappy';
}
const background_worker = new Worker('keycache_webworker.js');
const type = 'keyczar';

var hasStrongRandom = (type != 'crappy' && typeof window != 'undefined' &&
window.crypto && window.crypto.getRandomValues);

background_worker.addEventListener('message', function(e) {

background_worker.onmessage = function(e: MessageEvent) {
if (!e.data || typeof e.data !== "object") {
return;
}
if (e.data.key) {
console.log('got key from worker');
// $FlowFixMe
var k = crypto.loadFromJson(e.data.key);
cache.push(k);
} else if (e.data.request == 'log') {
Expand All @@ -206,14 +177,14 @@ mitro.keycache.startFiller = function(cache) {
} else {
console.log('unhandled worker message', e.data);
}
});
}

var postGenerateKey = function() {
var request = {request: 'generate'};
var request: any = {request: 'generate'};
if (hasStrongRandom) {
// each time we generate a key, add some additional entropy from the browser
// TODO: Is this a sufficient amount?
request.seed = mitro.keycache.getEntropyBytes(32);
request.seed = getEntropyBytes(32);
}
background_worker.postMessage(request);
};
Expand All @@ -230,13 +201,13 @@ mitro.keycache.startFiller = function(cache) {
if (hasStrongRandom) {
// seed the random number generator with good entropy, if we have it
// 32 pools that each want 32 bytes of entropy
var seed = mitro.keycache.getEntropyBytes(32 * 32);
var seed = getEntropyBytes(32 * 32);
background_worker.postMessage({request: 'seed', seed: seed});
}

// Post one message to the background for each key
var count = cache.size();
while (count < mitro.keycache.CACHE_TARGET) {
while (count < CACHE_TARGET) {
postGenerateKey();
count += 1;
}
Expand All @@ -247,6 +218,3 @@ mitro.keycache.startFiller = function(cache) {
}
};
};


})();
Loading