new encrypted file format

pull/1/head
ansuz 8 years ago
parent 8f5989b6b0
commit 1525712deb

@ -57,55 +57,30 @@ define([
}, []));
};
var padChunk = function (A) {
var padding;
if (A.length === plainChunkLength) { return A; }
if (A.length < plainChunkLength) {
padding = new Array(plainChunkLength - A.length).fill(32);
return A.concat(padding);
}
if (A.length > plainChunkLength) {
// how many times larger is it?
var chunks = Math.ceil(A.length / plainChunkLength);
padding = new Array((plainChunkLength * chunks) - A.length).fill(32);
return A.concat(padding);
}
};
var decrypt = function (u8, key, cb) {
var fail = function (e) {
cb(e || "DECRYPTION_ERROR");
};
var nonce = createNonce();
var i = 0;
decodePrefix([]); // TODO
var takeChunk = function () {
var start = i * cypherChunkLength;
var end = start + cypherChunkLength;
i++;
var box = new Uint8Array(u8.subarray(start, end));
// decrypt the chunk
var plaintext = Nacl.secretbox.open(box, nonce, key);
increment(nonce);
return plaintext;
};
var buffer = '';
var prefix = u8.subarray(0, 2);
var metadataLength = decodePrefix(prefix);
var res = {
metadata: undefined,
};
// decrypt metadata
var chunk;
for (; !res.metadata && i * cypherChunkLength < u8.length;) {
chunk = takeChunk();
buffer += Nacl.util.encodeUTF8(chunk);
try {
res.metadata = JSON.parse(buffer);
//console.log(res.metadata);
} catch (e) {
console.log('buffering another chunk for metadata');
}
var metaBox = new Uint8Array(u8.subarray(2, 2 + metadataLength));
var metaChunk = Nacl.secretbox.open(metaBox, nonce, key);
increment(nonce);
try {
res.metadata = JSON.parse(Nacl.util.encodeUTF8(metaChunk));
} catch (e) {
return fail('E_METADATA_DECRYPTION');
}
if (!res.metadata) {
@ -114,12 +89,21 @@ define([
});
}
var fail = function () {
cb("DECRYPTION_ERROR");
var takeChunk = function () {
var start = i * cypherChunkLength + 2 + metadataLength;
var end = start + cypherChunkLength;
i++;
var box = new Uint8Array(u8.subarray(start, end));
// decrypt the chunk
var plaintext = Nacl.secretbox.open(box, nonce, key);
increment(nonce);
return plaintext;
};
var chunks = [];
// decrypt file contents
var chunk;
for (;i * cypherChunkLength < u8.length;) {
chunk = takeChunk();
if (!chunk) {
@ -139,15 +123,12 @@ define([
var encrypt = function (u8, metadata, key) {
var nonce = createNonce();
encodePrefix(); // TODO
// encode metadata
var metaBuffer = Array.prototype.slice
.call(Nacl.util.decodeUTF8(JSON.stringify(metadata)));
var plaintext = new Uint8Array(padChunk(metaBuffer));
var plaintext = new Uint8Array(metaBuffer);
var j = 0;
var i = 0;
/*
@ -164,22 +145,21 @@ define([
var part;
var box;
if (state === 0) { // metadata...
start = j * plainChunkLength;
end = start + plainChunkLength;
// DONE
if (state === 2) { return void cb(); }
part = plaintext.subarray(start, end);
if (state === 0) { // metadata...
part = new Uint8Array(plaintext);
box = Nacl.secretbox(part, nonce, key);
increment(nonce);
j++;
// metadata is done
if (j * plainChunkLength >= plaintext.length) {
return void cb(state++, box);
if (box.length > 65535) {
return void cb('METADATA_TOO_LARGE');
}
return void cb(state, box);
var prefixed = new Uint8Array(encodePrefix(box.length)
.concat(slice(box)));
state++;
return void cb(void 0, prefixed);
}
// encrypt the rest of the file...
@ -194,7 +174,7 @@ define([
// regular data is done
if (i * plainChunkLength >= u8.length) { state = 2; }
return void cb(state, box);
return void cb(void 0, box);
};
return next;

@ -47,55 +47,43 @@ define([
});
};
var again = function (state, box) {
switch (state) {
case 0:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
break;
case 1:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
break;
case 2:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
Cryptpad.rpc.send('UPLOAD_COMPLETE', '', function (e, res) {
if (e) { return void console.error(e); }
var id = res[0];
var uri = ['', 'blob', id.slice(0,2), id].join('/');
console.log("encrypted blob is now available as %s", uri);
var b64Key = Nacl.util.encodeBase64(key);
window.location.hash = Cryptpad.getFileHashFromKeys(id, b64Key);
$form.hide();
APP.toolbar.addElement(['fileshare'], {});
// check if the uploaded file can be decrypted
var newU8 = FileCrypto.joinChunks(chunks);
FileCrypto.decrypt(newU8, key, function (e, res) {
if (e) { return console.error(e); }
var title = document.title = res.metadata.name;
myFile = res.content;
myDataType = res.metadata.type;
var defaultName = Cryptpad.getDefaultName(Cryptpad.parsePadUrl(window.location.href));
Title.updateTitle(title || defaultName);
APP.toolbar.title.show();
Cryptpad.alert("successfully uploaded: " + title);
});
});
});
break;
default:
throw new Error("E_INVAL_STATE");
var again = function (err, box) {
if (err) { throw new Error(err); }
if (box) {
return void sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
}
// if not box then done
Cryptpad.rpc.send('UPLOAD_COMPLETE', '', function (e, res) {
if (e) { return void console.error(e); }
var id = res[0];
var uri = ['', 'blob', id.slice(0,2), id].join('/');
console.log("encrypted blob is now available as %s", uri);
var b64Key = Nacl.util.encodeBase64(key);
window.location.hash = Cryptpad.getFileHashFromKeys(id, b64Key);
$form.hide();
APP.toolbar.addElement(['fileshare'], {});
// check if the uploaded file can be decrypted
var newU8 = FileCrypto.joinChunks(chunks);
FileCrypto.decrypt(newU8, key, function (e, res) {
if (e) { return console.error(e); }
var title = document.title = res.metadata.name;
myFile = res.content;
myDataType = res.metadata.type;
var defaultName = Cryptpad.getDefaultName(Cryptpad.parsePadUrl(window.location.href));
Title.updateTitle(title || defaultName);
APP.toolbar.title.show();
Cryptpad.alert("successfully uploaded: " + title);
});
});
};
Cryptpad.rpc.send('UPLOAD_STATUS', '', function (e, pending) {

@ -11,7 +11,6 @@ define([
'/bower_components/file-saver/FileSaver.min.js',
], function ($, Crypto, realtimeInput, Toolbar, Cryptpad, Visible, Notify, FileCrypto) {
var Nacl = window.nacl;
$(function () {
var filesAreSame = function (a, b) {
@ -31,8 +30,8 @@ define([
var upload = function (blob, metadata) {
var u8 = new Uint8Array(blob);
var key = Nacl.randomBytes(32);
var next = FileCrypto.encrypt(u8, metadata, key);
var chunks = [];
@ -41,41 +40,32 @@ define([
cb();
};
var again = function (state, box) {
switch (state) {
case 0:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
break;
case 1:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
next(again);
});
break;
case 2:
sendChunk(box, function (e) {
if (e) { return console.error(e); }
// check if the uploaded file can be decrypted
var newU8 = FileCrypto.joinChunks(chunks);
FileCrypto.decrypt(newU8, key, function (e, res) {
if (e) { return Cryptpad.alert(e); }
var again = function (err, box) {
if (err) { throw new Error(err); }
if (filesAreSame(blob, res.content) &&
metadataIsSame(res.metadata, metadata)) {
Cryptpad.alert("successfully uploaded");
} else {
Cryptpad.alert('encryption failure!');
}
});
});
break;
default:
throw new Error("E_INVAL_STATE");
if (box) {
return void sendChunk(box, function (e) {
if (e) {
console.error(e);
return Cryptpad.alert('Something went wrong');
}
next(again);
});
}
// check if the uploaded file can be decrypted
var newU8 = FileCrypto.joinChunks(chunks);
console.log('encrypted file with metadata is %s uint8s', newU8.length);
FileCrypto.decrypt(newU8, key, function (e, res) {
if (e) { return Cryptpad.alert(e); }
if (filesAreSame(blob, res.content) &&
metadataIsSame(res.metadata, metadata)) {
Cryptpad.alert("successfully uploaded");
} else {
Cryptpad.alert('encryption failure!');
}
});
};
next(again);
};
@ -83,7 +73,7 @@ define([
var andThen = function () {
var src = '/customize/cryptofist_mini.png';
Cryptpad.fetch(src, function (e, file) {
console.log(file);
console.log('original file is %s uint8s', file.length);
upload(file, {
pew: 'pew',
bang: 'bang',

Loading…
Cancel
Save