Commit 26de76ef authored by Tristan Cavelier's avatar Tristan Cavelier Committed by Sebastien Robin

Jio CryptedStorage completed + Qunit tests

parent 77966ec9
...@@ -50,6 +50,7 @@ module.exports = function(grunt) { ...@@ -50,6 +50,7 @@ module.exports = function(grunt) {
}, },
globals: { globals: {
jQuery: true, jQuery: true,
sjcl: true,
LocalOrCookieStorage: true, LocalOrCookieStorage: true,
Base64: true, Base64: true,
JIO: true, JIO: true,
......
...@@ -57,6 +57,7 @@ module.exports = function(grunt) { ...@@ -57,6 +57,7 @@ module.exports = function(grunt) {
}, },
globals: { globals: {
jQuery: true, jQuery: true,
sjcl:true,
LocalOrCookieStorage: true, LocalOrCookieStorage: true,
Base64: true, Base64: true,
JIO: true, JIO: true,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1089,17 +1089,47 @@ ...@@ -1089,17 +1089,47 @@
var that = Jio.newBaseStorage( spec, my ), priv = {}; var that = Jio.newBaseStorage( spec, my ), priv = {};
// TODO : IT IS NOT SECURE AT ALL!
// WE MUST REWORK CRYPTED STORAGE!
priv.encrypt_param_object = {
"iv":"kaprWwY/Ucr7pumXoTHbpA",
"v":1,
"iter":1000,
"ks":256,
"ts":128,
"mode":"ccm",
"adata":"",
"cipher":"aes",
"salt":"K4bmZG9d704"
};
priv.decrypt_param_object = {
"iv":"kaprWwY/Ucr7pumXoTHbpA",
"ks":256,
"ts":128,
"salt":"K4bmZG9d704"
};
priv.encrypt = function (data,callback,index) { priv.encrypt = function (data,callback,index) {
// end with a callback in order to improve encrypt to an // end with a callback in order to improve encrypt to an
// asynchronous encryption. // asynchronous encryption.
var tmp = sjcl.encrypt (that.getStorageUserName()+':'+ var tmp = sjcl.encrypt (that.getStorageUserName()+':'+
that.getStoragePassword(), data); that.getStoragePassword(), data,
callback(tmp,index); priv.encrypt_param_object);
callback(JSON.parse(tmp).ct,index);
}; };
priv.decrypt = function (data,callback,index) { priv.decrypt = function (data,callback,index,key) {
var tmp = sjcl.decrypt (that.getStorageUserName()+':'+ var tmp, param = $.extend(true,{},priv.decrypt_param_object);
that.getStoragePassword(), data); param.ct = data || '';
callback(tmp,index); param = JSON.stringify (param);
try {
tmp = sjcl.decrypt (that.getStorageUserName()+':'+
that.getStoragePassword(),
param);
} catch (e) {
callback({status:0,statusText:'Decrypt Fail',
message:'Unable to decrypt.'},index,key);
return;
}
callback(tmp,index,key);
}; };
/** /**
...@@ -1132,15 +1162,10 @@ ...@@ -1132,15 +1162,10 @@
}); });
}, },
_2 = function () { _2 = function () {
priv.encrypt( priv.encrypt(that.getFileContent(),function(res) {
JSON.stringify({ newfilecontent = res;
name: that.getFileName(), _3();
content:that.getFileContent() });
}),
function(res) {
newfilecontent = res;
_3();
});
}, },
_3 = function () { _3 = function () {
new_job = that.cloneJob(); new_job = that.cloneJob();
...@@ -1166,7 +1191,7 @@ ...@@ -1166,7 +1191,7 @@
* @method loadDocument * @method loadDocument
*/ */
that.loadDocument = function () { that.loadDocument = function () {
var new_job, new_file_name, var new_job, new_file_name, option = that.cloneOptionObject(),
_1 = function () { _1 = function () {
priv.encrypt(that.getFileName(),function(res) { priv.encrypt(that.getFileName(),function(res) {
new_file_name = res; new_file_name = res;
...@@ -1178,15 +1203,31 @@ ...@@ -1178,15 +1203,31 @@
new_job.name = new_file_name; new_job.name = new_file_name;
new_job.storage = that.getSecondStorage(); new_job.storage = that.getSecondStorage();
new_job.callback = loadCallback; new_job.callback = loadCallback;
console.log (new_job);
that.addJob ( new_job ); that.addJob ( new_job );
}, },
loadCallback = function (result) { loadCallback = function (result) {
if (result.status === 'done') { if (result.status === 'done') {
priv.decrypt (result.return_value.content,function(res){ result.return_value.name = that.getFileName();
that.done(JSON.parse(res)); if (option.metadata_only) {
}); that.done(result.return_value);
} else {
priv.decrypt (result.return_value.content,function(res){
if (typeof res === 'object') {
that.fail({status:0,statusText:'Decrypt Fail',
message:'Unable to decrypt'});
} else {
result.return_value.content = res;
// content only: the second storage should
// manage content_only option, so it is not
// necessary to manage it.
that.done(result.return_value);
}
});
}
} else { } else {
// NOTE : we can re create an error object instead of
// keep the old ex:status=404,message="document 1y59gyl8g
// not found in localStorage"...
that.fail(result.error); that.fail(result.error);
} }
}; };
...@@ -1198,7 +1239,7 @@ ...@@ -1198,7 +1239,7 @@
* @method getDocumentList * @method getDocumentList
*/ */
that.getDocumentList = function () { that.getDocumentList = function () {
var new_job, i, l, cpt = 0, array, var new_job, i, l, cpt = 0, array, ok = true,
_1 = function () { _1 = function () {
new_job = that.cloneJob(); new_job = that.cloneJob();
new_job.storage = that.getSecondStorage(); new_job.storage = that.getSecondStorage();
...@@ -1209,20 +1250,29 @@ ...@@ -1209,20 +1250,29 @@
if (result.status === 'done') { if (result.status === 'done') {
array = result.return_value; array = result.return_value;
for (i = 0, l = array.length; i < l; i+= 1) { for (i = 0, l = array.length; i < l; i+= 1) {
priv.decrypt (array[i], // cpt--;
lastCallback,i); priv.decrypt (array[i].name,
lastCallback,i,'name');
// priv.decrypt (array[i].content,
// lastCallback,i,'content');
} }
} else { } else {
that.fail(result.error); that.fail(result.error);
} }
}, },
lastCallback = function (res,index) { lastCallback = function (res,index,key) {
var tmp; var tmp;
cpt++; cpt++;
tmp = JSON.parse(res); if (typeof res === 'object') {
array[index] = res.name; if (ok) {
array[index] = res.content; that.fail({status:0,statusText:'Decrypt Fail',
if (cpt === l) { message:'Unable to decrypt.'});
}
ok = false;
return;
}
array[index][key] = res;
if (cpt === l && ok) {
// this is the last callback // this is the last callback
that.done(array); that.done(array);
} }
...@@ -1235,16 +1285,28 @@ ...@@ -1235,16 +1285,28 @@
* @method removeDocument * @method removeDocument
*/ */
that.removeDocument = function () { that.removeDocument = function () {
var new_job = that.cloneJob(); var new_job, new_file_name,
new_job.storage = that.getSecondStorage(); _1 = function () {
new_job.callback = function (result) { priv.encrypt(that.getFileName(),function(res) {
new_file_name = res;
_2();
});
},
_2 = function () {
new_job = that.cloneJob();
new_job.name = new_file_name;
new_job.storage = that.getSecondStorage();
new_job.callback = removeCallback;
that.addJob(new_job);
},
removeCallback = function (result) {
if (result.status === 'done') { if (result.status === 'done') {
that.done(); that.done();
} else { } else {
that.fail(result.error); that.fail(result.error);
} }
}; };
that.addJob(new_job); _1();
}; };
return that; return that;
}; };
......
...@@ -24,6 +24,13 @@ var getXML = function (url) { ...@@ -24,6 +24,13 @@ var getXML = function (url) {
dataType:'text',success:function(xml){tmp=xml;}}); dataType:'text',success:function(xml){tmp=xml;}});
return tmp; return tmp;
}, },
objectifyDocumentArray = function (array) {
var obj = {}, k;
for (k = 0; k < array.length; k += 1) {
obj[array[k].name] = array[k];
}
return obj;
},
addFile = function (user,appid,file) { addFile = function (user,appid,file) {
var i, l, found = false, filenamearray, var i, l, found = false, filenamearray,
userarray = LocalOrCookieStorage.getItem('jio/local_user_array') || []; userarray = LocalOrCookieStorage.getItem('jio/local_user_array') || [];
...@@ -408,13 +415,6 @@ test ('Get document list', function () { ...@@ -408,13 +415,6 @@ test ('Get document list', function () {
doc1 = {}, doc2 = {}, doc1 = {}, doc2 = {},
mytest = function (value){ mytest = function (value){
o.f = function (result) { o.f = function (result) {
var objectifyDocumentArray = function (array) {
var obj = {}, k;
for (k = 0; k < array.length; k+=1) {
obj[array[k].name] = array[k];
}
return obj;
};
deepEqual (objectifyDocumentArray(result.return_value), deepEqual (objectifyDocumentArray(result.return_value),
objectifyDocumentArray(value),'getting list'); objectifyDocumentArray(value),'getting list');
}; };
...@@ -625,13 +625,6 @@ test ('Get Document List', function () { ...@@ -625,13 +625,6 @@ test ('Get Document List', function () {
[errnoprop,{'Content-Type':'text/xml; charset="utf-8"'}, [errnoprop,{'Content-Type':'text/xml; charset="utf-8"'},
davlist]); davlist]);
o.f = function (result) { o.f = function (result) {
var objectifyDocumentArray = function (array) {
var obj = {}, k;
for (k = 0; k < array.length; k += 1) {
obj[array[k].name] = array[k];
}
return obj;
};
if (result.status === 'fail') { if (result.status === 'fail') {
deepEqual (result.return_value, value, message); deepEqual (result.return_value, value, message);
} else { } else {
...@@ -824,13 +817,6 @@ test ('Get Document List', function () { ...@@ -824,13 +817,6 @@ test ('Get Document List', function () {
var o = {}, clock = this.sandbox.useFakeTimers(), t = this, var o = {}, clock = this.sandbox.useFakeTimers(), t = this,
mytest = function (message,value) { mytest = function (message,value) {
o.f = function (result) { o.f = function (result) {
var objectifyDocumentArray = function (array) {
var obj = {}, k;
for (k = 0; k < array.length; k += 1) {
obj[array[k].name] = array[k];
}
return obj;
};
deepEqual (objectifyDocumentArray(result.return_value), deepEqual (objectifyDocumentArray(result.return_value),
objectifyDocumentArray(value),'getting list'); objectifyDocumentArray(value),'getting list');
}; };
...@@ -1028,10 +1014,11 @@ test ('Check name availability' , function () { ...@@ -1028,10 +1014,11 @@ test ('Check name availability' , function () {
test ('Document save' , function () { test ('Document save' , function () {
var o = {}, clock = this.sandbox.useFakeTimers(); var o = {}, clock = this.sandbox.useFakeTimers();
o.jio=JIO.newJio({type:'crypted', o.jio=JIO.newJio({type:'crypted',
password:'mypwd', user_name:'cryptsave',
storage:{type:'local', password:'mypwd',
user_name:'cryptsave'}}, storage:{type:'local',
{ID:'jiotests'}); user_name:'cryptsavelocal'}},
{ID:'jiotests'});
o.f = function (result) { o.f = function (result) {
deepEqual (result.status,'done','save ok'); deepEqual (result.status,'done','save ok');
}; };
...@@ -1042,16 +1029,28 @@ test ('Document save' , function () { ...@@ -1042,16 +1029,28 @@ test ('Document save' , function () {
if (!o.f.calledOnce) { if (!o.f.calledOnce) {
ok (false, 'no response / too much results'); ok (false, 'no response / too much results');
} }
// encrypt 'testsave' with 'cryptsave:mypwd' password
o.tmp = LocalOrCookieStorage.getItem(
'jio/local/cryptsavelocal/jiotests/rZx5PJxttlf9QpZER/5x354bfX54QFa1');
if (o.tmp) {
delete o.tmp.last_modified;
delete o.tmp.creation_date;
}
deepEqual (o.tmp,
{name:'rZx5PJxttlf9QpZER/5x354bfX54QFa1',
content:'upZkPIpitF3QMT/DU5jM3gP0SEbwo1n81rMOfLE'},
'Check if the document is realy crypted');
o.jio.stop(); o.jio.stop();
}); });
test ('Document Load' , function () { test ('Document Load' , function () {
var o = {}, clock = this.sandbox.useFakeTimers(); var o = {}, clock = this.sandbox.useFakeTimers();
o.jio=JIO.newJio({type:'crypted', o.jio=JIO.newJio({type:'crypted',
password:'mypwd', user_name:'cryptload',
storage:{type:'local', password:'mypwd',
user_name:'cryptload'}}, storage:{type:'local',
{ID:'jiotests'}); user_name:'cryptloadlocal'}},
{ID:'jiotests'});
o.f = function (result) { o.f = function (result) {
if (result.status === 'done') { if (result.status === 'done') {
deepEqual (result.return_value,{name:'testload', deepEqual (result.return_value,{name:'testload',
...@@ -1064,6 +1063,13 @@ test ('Document Load' , function () { ...@@ -1064,6 +1063,13 @@ test ('Document Load' , function () {
} }
}; };
this.spy(o,'f'); this.spy(o,'f');
// encrypt 'testload' with 'cryptload:mypwd' password
// and 'contentoftest' with 'cryptload:mypwd'
LocalOrCookieStorage.setItem(
'jio/local/cryptloadlocal/jiotests/hiG4H80pwkXCCrlLl1X0BD0BfWLZwDUX',
{name:'mRyQFcUvUKq6tLGUjBo34P3oc2LPxEju',
content:'kSulH8Qo105dSKHcY2hEBXWXC9b+3PCEFSm1k7k',
last_modified:500,creation_date:500});
o.jio.loadDocument({name:'testload', o.jio.loadDocument({name:'testload',
max_tries:1,callback:o.f}); max_tries:1,callback:o.f});
clock.tick(1000); clock.tick(1000);
...@@ -1071,8 +1077,90 @@ test ('Document Load' , function () { ...@@ -1071,8 +1077,90 @@ test ('Document Load' , function () {
ok (false, 'no response / too much results'); ok (false, 'no response / too much results');
} }
o.jio.stop(); o.jio.stop();
LocalOrCookieStorage.deleteItem(
'jio/local/cryptloadlocal/jiotests/hiG4H80pwkXCCrlLl1X0BD0BfWLZwDUX');
});
test ('Get Document List', function () {
var o = {}, clock = this.sandbox.useFakeTimers();
o.jio=JIO.newJio({type:'crypted',
user_name:'cryptgetlist',
password:'mypwd',
storage:{type:'local',
user_name:'cryptgetlistlocal'}},
{ID:'jiotests'});
o.f = function (result) {
if (result.status === 'done') {
deepEqual (objectifyDocumentArray(result.return_value),
objectifyDocumentArray(o.doc_list),'Getting list');
} else {
console.warn (result);
ok (false, 'Cannot get list');
}
};
this.spy(o,'f');
o.doc_list = [
{name:'testgetlist1',last_modified:500,creation_date:200},
{name:'testgetlist2',last_modified:300,creation_date:300}
];
o.doc_encrypt_list = [
{name:'541eX0WTMDw7rqIP7Ofxd1nXlPOtejxGnwOzMw',
content:'/4dBPUdmLolLfUaDxPPrhjRPdA',
last_modified:500,creation_date:200},
{name:'541eX0WTMDw7rqIMyJ5tx4YHWSyxJ5UjYvmtqw',
content:'/4FBALhweuyjxxD53eFQDSm4VA',
last_modified:300,creation_date:300}
];
// encrypt with 'cryptgetlist:mypwd' as password
LocalOrCookieStorage.setItem(
'jio/local_file_name_array/cryptgetlistlocal/jiotests',
[o.doc_encrypt_list[0].name,o.doc_encrypt_list[1].name]);
LocalOrCookieStorage.setItem(
'jio/local/cryptgetlistlocal/jiotests/'+o.doc_encrypt_list[0].name,
o.doc_encrypt_list[0]);
LocalOrCookieStorage.setItem(
'jio/local/cryptgetlistlocal/jiotests/'+o.doc_encrypt_list[1].name,
o.doc_encrypt_list[1]);
o.jio.getDocumentList({max_tries:1,callback:o.f});
clock.tick (2000);
if (!o.f.calledOnce) {
ok (false, 'no response / too much results');
}
clock.tick(1000);
o.jio.stop();
}); });
// end require
test ('Remove document', function () {
var o = {}, clock = this.sandbox.useFakeTimers();
o.jio=JIO.newJio({type:'crypted',
user_name:'cryptremove',
password:'mypwd',
storage:{type:'local',
user_name:'cryptremovelocal'}},
{ID:'jiotests'});
o.f = function (result) {
deepEqual (result.status,'done','Document remove');
};
this.spy(o,'f');
// encrypt with 'cryptremove:mypwd' as password
LocalOrCookieStorage.setItem(
'jio/local_file_name_array/cryptremovelocal/jiotests',
["JqCLTjyxQqO9jwfxD/lyfGIX+qA"]);
LocalOrCookieStorage.setItem(
'jio/local/cryptremovelocal/jiotests/JqCLTjyxQqO9jwfxD/lyfGIX+qA',
{"name":"JqCLTjyxQqO9jwfxD/lyfGIX+qA",
"content":"LKaLZopWgML6IxERqoJ2mUyyO",
"creation_date":500,
"last_modified":500});
o.jio.removeDocument({name:'file',max_tries:1,callback:o.f});
clock.tick(1000);
if (!o.f.calledOnce){
ok (false, 'no response / too much results');
}
o.jio.stop();
});
}; // end thisfun }; // end thisfun
if (window.requirejs) { if (window.requirejs) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment