diff --git a/shrine-webclient/src/main/html/js-i2b2/cells/plugins/MedCo/workersController.js b/shrine-webclient/src/main/html/js-i2b2/cells/plugins/MedCo/workersController.js
index 46d1a37d5..bc5f3936e 100644
--- a/shrine-webclient/src/main/html/js-i2b2/cells/plugins/MedCo/workersController.js
+++ b/shrine-webclient/src/main/html/js-i2b2/cells/plugins/MedCo/workersController.js
@@ -1,258 +1,265 @@
// a structure to handle the workers (background threads)
i2b2.MedCo.ctrlr.background = {
// from outside you should just call the following
// - init()
// - toBeEncrypted() x N (call this functions whenever you have something to encrypt)
// - encryptionDone() (check if encryption has finished)
// - toBeDecrypted() x N (call this functions whenever you have something to decrypt)
// - decryptionDone() (check if decryption has finished)
// here is stored the list of workers of with the workload can be spread
workers: [],
// ------------------ Encryption ------------------
// K and S are the parameters that will be used to encrypt
K: null,
S: null,
// aggregate public key of the cothority (used to decrypt)
AggregateKey: null, //"GKrufk6bsuMwegxcPqr7B1aFWKit1szJlugZ01HkSPA=",
// This is a map from plaintexts to the corresponding ciphertext to avoid encrypting again.
// It is updated every time a worker encrypts new integer.
encryptionCache: {},
// A list of plaintexts that have to be encrypted (notice that some of these my have the corresponding ciphertext
// in the encryptionCache). When a plaintext is encrypted it is saved in encryptionCache and removed from toEncrypt
toEncrypt: [],
// store the number of remaining plaintext to encrypt ("toEncrypt.length" may be different from "remainingToEncrypt"
// since when a plaintext is sent to a worker it is removed from toEncrypt but "remainingToEncrypt" is not
// decreased yet)
remainingToEncrypt: 0,
// ------------------ Decryption ------------------
// secret key of the user. Used to decrypt the patient counts received.
SecKey: null,
// This is a map from ciphertexts to the corresponding plaintexts to avoid decrypting again.
// It is updated every time a worker decrypts new cipher.
decryptionCache: {},
// A list of ciphertexts that have to be decrypted (notice that some of these my have the corresponding plaintext
// in the decryptionCache). When a ciphertext is decrypted it is saved in decryptionCache and removed from toDecrypt.
toDecrypt: [],
// store the number of remaining plaintext to decrypt ("toDecrypt.length" may be different from "remainingToDecrypt"
// since when a plaintext is sent to a worker it is removed from toDecrypt but "remainingToDecrypt" is not
// decreased yet)
remainingToDecrypt: 0,
// initialize workers and the ephemeral key for the encryption
init: function(num_workers, secKey){ //aggregateKey
this.SecKey = secKey;
this.AggregateKey = null;
+ this.K = null;
+ this.S = null;
+
this.initWorkers(num_workers);
- this.initEncrypt();
+
var group_toml = "http://" + location.host + "/shrine-client/js-i2b2/cells/plugins/MedCo/group.toml";
fetch(group_toml).then(function(response) {
response.text().then(function(text) {
this.AggregateKey = AggKeys(text);
+ this.initEncrypt()
});
- });
+ })
},
// init initializes the workers (to create them one time and then just send them the strings to
// encrypt/decrypt). Initialise a worker may take some seconds because each one of them ahas to import
// the crypto javascript
initWorkers: function(num_workers){
var that = i2b2.MedCo.ctrlr.background;
// first kill the existing workers, if any
for (var i=0; i < this.workers.length; i++) {
this.workers[i].terminate();
}
this.workers = [];
// todo be careful the importPath to points to the correct location of the file
// var importPath = document.location["href"];
// // you have to tell the workers where the crypto library is so that they can import it
// importPath = importPath.substr(0, importPath.lastIndexOf('/')) + "/scripts/cryptolib.js";
var importPath = "http://" + location.host + "/shrine-client/js-i2b2/cells/plugins/MedCo/cryptolib.js"; // todo check is correct
for (var i=0; i < num_workers; i++){
// start a new worker
var w = new Worker(URL.createObjectURL(new Blob(["("+worker_code.toString()+")()"], {type: 'text/javascript'})));
// register to each worker an encrypt function that will look for something to encrypt and send it
// to the worker
w.encrypt = function (){
// look for something to encrypt
while (that.toEncrypt.length > 0){
if (that.toEncrypt[0] in that.encryptionCache){
// it has been encrypted in the past
that.toEncrypt.shift();
that.remainingToEncrypt -= 1;
document.getElementById("MedCo_encrypting").innerHTML = that.remainingToEncrypt;
}
else{
+ if (that.K==null || that.S==null){
+ alert("initEncrypt failed in computing K and S.")
+ }
w.postMessage({"enc": {"plain": that.toEncrypt.shift(), "K": that.K, "S": that.S}});
break
}
}
};
w.decrypt = function(){
// look for something to decrypt
while (that.toDecrypt.length){
if (that.toDecrypt[0] in that.decryptionCache){
// it has been decrypted in the past
that.toDecrypt.shift();
that.remainingToDecrypt -= 1;
}
else{
w.postMessage({"dec": {"cipher": that.toDecrypt.shift(), "secKey": that.SecKey}});
break
}
}
};
// register event for the result
w.onmessage = function(e) {
var task = Object.keys(e.data)[0];
switch (task) {
case "enc":
that.encryptionCache[e.data[task]["plain"]] = e.data[task]["cipher"];
that.remainingToEncrypt -= 1;
document.getElementById("MedCo_encrypting").innerHTML = that.remainingToEncrypt;
// start another encryption
w.encrypt();
break;
case "dec":
that.decryptionCache[e.data[task]["cipher"]] = e.data[task]["plain"];
that.remainingToDecrypt -= 1;
// start another decryption
w.decrypt();
break;
default:
alert("Message received from the worker not recognized:" + JSON.stringify(e.data))
}
};
w.postMessage({"init": {"import": importPath}});
this.workers.push(w)
}
},
initEncrypt: function(){
// var context = i2b2.MedCo.ctrlr.background;
// init the ephemeral key of the light encryption
if (this.AggregateKey == null){
- alert("aggregate not loaded")
+ alert("Aggregate not computed.")
}
[this.K, this.S] = LightEncryptStr_init(this.AggregateKey);
this.encryptionCache = {}; // old ciphertexts are not valid anymore
},
// receives a list of plaintexts to be encrypted and append it to the toEncrypt list
toBeEncrypted: function(toEncrypt){
// var context = i2b2.MedCo.ctrlr.background;
// other plaintext to be encrypted are appended to the list
this.toEncrypt = this.toEncrypt.concat(toEncrypt);
this.remainingToEncrypt += toEncrypt.length;
// sends to each worker something to encrypt
for(var i=0; i < this.workers.length; i++){
this.workers[i].encrypt(); // function registered to the worker (see init)
}
document.getElementById("MedCo_encrypting").innerHTML = this.remainingToEncrypt;
},
// receives a list of ciphertexts to be decrypted and append it to the toDecrypt list
toBeDecrypted: function(toDecrypt){
// var context = i2b2.MedCo.ctrlr.background;
// other plaintext to be encrypted are appended to the list
this.toDecrypt = this.toDecrypt.concat(toDecrypt);
this.remainingToDecrypt += toDecrypt.length;
// sends to each worker something to encrypt
for(var i=0; i < this.workers.length; i++){
this.workers[i].decrypt(); // function registered to the worker (see init)
}
},
// checks if there are other plaintexts to be encrypted
encryptionDone: function() {
return i2b2.MedCo.ctrlr.background.remainingToEncrypt == 0;
},
// checks if there are other chipertexts to be decrypted
decryptionDone: function() {
return i2b2.MedCo.ctrlr.background.remainingToDecrypt == 0;
}
};
// all worker code goes here (this function is just used to create workers in the i2b2.MedCo.ctrlr.background.init)
function worker_code() {
// a worker responds to 3 different messages, init, encrypt, decrypt
onmessage = function(e) {
// e.data is in one of the following forms -> response:
// - {"init": {"import": "http://.../cryptolib.js"}} -> no response
// - {"enc": {"plain": "123", "K": "...", "S": "..."}} -> {"enc": {"plain": "", "cipher": ""}}
// - todo {"dec": { "cipher": "...", secKey: "..." }} -> {"dec": {"plain": "", "cipher": ""}}
var task = Object.keys(e.data)[0];
switch (task){
case "init":
self.importScripts(e.data[task]["import"]); // e.g. self.importScripts("http://localhost:63342/i-b-webclient/tools/gopherjsCrypto/tests/scripts/useme.js");
// console.log("worker says: imported cryptolib");
break;
case "enc":
var plain = e.data[task]["plain"];
var K = e.data[task]["K"];
var S = e.data[task]["S"];
var cipher = LightEncryptStr(plain, K, S);
// console.log("worker says: plain: " + plain + "; cipher: ", cipher);
// {"enc": {"plain": "", "cipher": ""}}
var response = {};
response[task] = {};
response[task]["plain"] = plain;
response[task]["cipher"] = cipher;
postMessage(response);
break;
case "dec":
var cipher = e.data[task]["cipher"];
var secKey = e.data[task]["secKey"];
var plain = parseInt(DecryptStr(cipher, secKey));
// console.log("worker says: cipher: " + cipher + "; plain: ", plain);
// {"dec": {"plain": "", "cipher": ""}}
var response = {};
response[task] = {};
response[task]["plain"] = plain;
response[task]["cipher"] = cipher;
postMessage(response);
break;
default:
alert("worker says: message not recognized: " + JSON.stringify(e.data))
}
};
}
\ No newline at end of file