mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Fixed encryption of files, modified UI some more.
This commit is contained in:
parent
cb6aaee0dc
commit
fbed5b2ba5
@ -18,7 +18,8 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
{
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
// GET: Upload/Upload
|
||||
|
||||
// User did not supply key
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Download(string url)
|
||||
@ -26,6 +27,14 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
|
||||
// User supplied key
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Download(string url, string key)
|
||||
{
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
@ -34,7 +43,7 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
Models.Upload upload = Uploader.SaveFile(data, fileType, iv);
|
||||
if (upload != null)
|
||||
{
|
||||
return Json(new { result = new { name = upload.Url, url = Url.SubRouteUrl("upload", "Upload.Download", new { file = upload.Url }) } }, "text/plain");
|
||||
return Json(new { result = new { name = upload.Url, url = Url.SubRouteUrl("upload", "Upload.Download.Key", new { file = upload.Url, key = "{key}" }), keyVar = "{key}" } }, "text/plain");
|
||||
}
|
||||
return Json(new { error = "Unable to upload file" });
|
||||
}
|
||||
|
@ -1,58 +1,82 @@
|
||||
self.addEventListener('message', function (e) {
|
||||
var data = e.data;
|
||||
importScripts(data.script);
|
||||
importScripts(e.data.script);
|
||||
|
||||
switch (data.cmd) {
|
||||
switch (e.data.cmd) {
|
||||
case 'encrypt':
|
||||
//var startByte = 0;
|
||||
//var endByte = 0;
|
||||
//var prog = [];
|
||||
var bytes = new Uint8Array(e.data.file);
|
||||
|
||||
//var bytes = new Uint8Array(data.file);
|
||||
var startByte = 0;
|
||||
var endByte = 0;
|
||||
var prog = [];
|
||||
|
||||
//// Create aes encryptor object
|
||||
//var aesEncryptor = CryptoJS.algo.AES.createEncryptor(data.key, { iv: data.iv });
|
||||
var key = CryptoJS.enc.Utf8.parse(e.data.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(e.data.iv);
|
||||
// Create aes encryptor object
|
||||
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
|
||||
|
||||
//while (startByte <= (bytes.length - 1)) {
|
||||
// // Set the end byte
|
||||
// endByte = startByte + data.chunkSize;
|
||||
// if (endByte > bytes.length - 1)
|
||||
// {
|
||||
// endByte = bytes.length - 1;
|
||||
// }
|
||||
while (startByte <= (bytes.length - 1)) {
|
||||
// Set the end byte
|
||||
endByte = startByte + e.data.chunkSize;
|
||||
if (endByte > bytes.length - 1)
|
||||
{
|
||||
endByte = bytes.length - 1;
|
||||
}
|
||||
|
||||
// // Grab current set of bytes
|
||||
// var curBytes = bytes.subarray(startByte, endByte);
|
||||
// var wordArray = CryptoJS.lib.WordArray.create(curBytes)
|
||||
// Grab current set of bytes
|
||||
var curBytes = bytes.subarray(startByte, endByte);
|
||||
//var b64encoded = btoa(String.fromCharCode.apply(null, curBytes));
|
||||
var wordArray = CryptoJS.lib.WordArray.create(curBytes)
|
||||
|
||||
// // encrypt the passed in file data and add it to bits[]
|
||||
// prog.push(aesEncryptor.process(wordArray));
|
||||
// encrypt the passed in file data
|
||||
var enc = aesEncryptor.process(wordArray);
|
||||
|
||||
// // Set the next start as the current end
|
||||
// startByte = endByte + 1;
|
||||
//}//then finalize
|
||||
//prog.push(aesEncryptor.finalize());
|
||||
// Convert and add to current array buffer
|
||||
var encStr = enc.toString(CryptoJS.enc.Base64); // to string
|
||||
prog.pushArray(_base64ToArray(encStr));
|
||||
|
||||
//throw JSON.stringify({ data: prog, start: startByte, end: endByte, len: bytes.length })
|
||||
var wordArray = CryptoJS.lib.WordArray.create(new Uint8Array(data.file));
|
||||
// Send an update on progress
|
||||
var objData =
|
||||
{
|
||||
cmd: 'progress',
|
||||
processed: endByte,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
var encWords = CryptoJS.AES.encrypt(wordArray, data.key, { iv: data.iv, mode: CryptoJS.mode.CBC });
|
||||
self.postMessage(objData);
|
||||
|
||||
//throw JSON.stringify({ data: wordArray });
|
||||
// Set the next start as the current end
|
||||
startByte = endByte + 1;
|
||||
}
|
||||
|
||||
//then finalize
|
||||
var encFinal = aesEncryptor.finalize();
|
||||
var finalStr = encFinal.toString(CryptoJS.enc.Base64); // to final string
|
||||
prog.pushArray(_base64ToArray(finalStr));
|
||||
|
||||
var dcBase64String = encWords.toString(); // to Base64-String
|
||||
//var encByteArray = wordToByteArray(encWords.words);
|
||||
// patch it all back together for the trip home
|
||||
var objData =
|
||||
{
|
||||
encrypted: str2ab(dcBase64String)
|
||||
cmd: 'progress',
|
||||
processed: bytes.length - 1,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
// convert array to ArrayBuffer
|
||||
var arBuf = _arrayToArrayBuffer(prog);
|
||||
|
||||
//throw JSON.stringify({ dataLength: prog.length, len: bytes.length, finalLength: arBuf.byteLength })
|
||||
|
||||
// Now package it into a mesage to send home
|
||||
var objData =
|
||||
{
|
||||
cmd: 'finish',
|
||||
encrypted: arBuf
|
||||
};
|
||||
|
||||
self.postMessage(objData, [objData.encrypted]);
|
||||
break;
|
||||
case 'decrypt':
|
||||
// decrypt the passed in file data
|
||||
var decrypted = CryptoJS.AES.decrypt(data.file, data.key, { iv: data.iv });
|
||||
var decrypted = CryptoJS.AES.decrypt(e.data.file, e.data.key, { iv: e.data.iv });
|
||||
|
||||
var fileText = decrypted.toString();
|
||||
|
||||
@ -61,36 +85,23 @@
|
||||
}
|
||||
}, false);
|
||||
|
||||
function wordToByteArray(wordArray) {
|
||||
var byteArray = [], word, i, j;
|
||||
for (i = 0; i < wordArray.length; ++i) {
|
||||
word = wordArray[i];
|
||||
for (j = 3; j >= 0; --j) {
|
||||
byteArray.push((word >> 8 * j) & 0xFF);
|
||||
}
|
||||
}
|
||||
return byteArray;
|
||||
function _arrayToArrayBuffer(array) {
|
||||
var len = array.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
bytes.set(array, 0);
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
function _base64ToArrayBuffer(base64) {
|
||||
function _base64ToArray(base64) {
|
||||
var binary_string = atob(base64);
|
||||
var len = binary_string.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function ab2str(buf) {
|
||||
return String.fromCharCode.apply(null, new Uint16Array(buf));
|
||||
}
|
||||
|
||||
function str2ab(str) {
|
||||
var buf = new ArrayBuffer(str.length); // 2 bytes for each char
|
||||
var bufView = new Uint16Array(buf);
|
||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
Array.prototype.pushArray = function (arr) {
|
||||
this.push.apply(this, arr);
|
||||
};
|
@ -3,13 +3,31 @@
|
||||
$("#upload-links").html('');
|
||||
});
|
||||
|
||||
function linkUploadDelete(selector) {
|
||||
function linkSaveKey(selector, uploadID, key, fileID) {
|
||||
$(selector).click(function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: saveKeyToServerURL,
|
||||
data: AddAntiForgeryToken({ uploadID: uploadID, key: key }),
|
||||
success: function (html) {
|
||||
if (html.result) {
|
||||
}
|
||||
else {
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html.error + '</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function linkUploadDelete(selector, uploadID) {
|
||||
$(selector).click(function () {
|
||||
ID = encodeURIComponent($(this).attr('id'));
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: generateDeleteKeyURL,
|
||||
data: AddAntiForgeryToken({ uploadID: ID }),
|
||||
data: AddAntiForgeryToken({ uploadID: uploadID }),
|
||||
success: function (html) {
|
||||
if (html.result) {
|
||||
bootbox.dialog({
|
||||
@ -28,6 +46,15 @@ function linkUploadDelete(selector) {
|
||||
});
|
||||
}
|
||||
|
||||
function linkRemove(selector, fileID) {
|
||||
$(selector).click(function () {
|
||||
$('#link-' + fileID).remove();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var fileCount = 0;
|
||||
|
||||
Dropzone.options.TeknikUpload = {
|
||||
paramName: "file", // The name that will be used to transfer the file
|
||||
maxFilesize: maxUploadSize, // MB
|
||||
@ -37,53 +64,39 @@ Dropzone.options.TeknikUpload = {
|
||||
previewTemplate: function () { },
|
||||
addedfile: function (file) {
|
||||
// Create the UI element for the new item
|
||||
var short_name = file.name.hashCode();
|
||||
var fileID = fileCount;
|
||||
fileCount++;
|
||||
// save ID to the file object
|
||||
file.ID = fileID;
|
||||
$("#upload-links").css('display', 'inline', 'important');
|
||||
$("#upload-links").prepend(' \
|
||||
<div class="row link-' + short_name + '" id="link-' + short_name + '"> \
|
||||
<div class="col-sm-12 text-center"> \
|
||||
'+ file.name + ' \
|
||||
</div> \
|
||||
<div class="progress-' + short_name + '"> \
|
||||
<div class="progress-bar progress-bar-success" id="progressBar-' + short_name + '" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 0%">0%</div> \
|
||||
<div class="panel panel-default" id="link-' + fileID + '"> \
|
||||
<div class="panel-heading text-center" id="link-header-' + fileID + '">'+ file.name + '</div> \
|
||||
<div class="panel-body" id="link-panel-' + fileID + '"> \
|
||||
<div class="row"> \
|
||||
<div class="col-sm-12 text-center" id="upload-link-' + fileID + '"></div> \
|
||||
</div> \
|
||||
<div class="row"> \
|
||||
<div class="col-sm-12 text-center"> \
|
||||
<div class="progress" id="progress-' + fileID + '"> \
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 0%">0%</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
');
|
||||
|
||||
// Encrypt the file
|
||||
encryptFile(file, uploadFile);
|
||||
$("#upload_message").css('display', 'none', 'important');
|
||||
},
|
||||
init: function() {
|
||||
this.on("removedfile", function(file) {
|
||||
var name = file.name.hashCode();
|
||||
$('.link-'+name).remove();
|
||||
});
|
||||
this.on("reset", function(file, responseText) {
|
||||
$("#upload_message").css('display', 'inline', 'important');
|
||||
$(".progress").children('.progress-bar').css('width', '0%');
|
||||
$(".progress").children('.progress-bar').html('0%');
|
||||
});
|
||||
this.on("error", function(file, errorMessage) {
|
||||
this.removeFile(file);
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>'+errorMessage+'</div>');
|
||||
});
|
||||
this.on("totaluploadprogress", function(progress, totalBytes, totalBytesSent) {
|
||||
$(".progress").children('.progress-bar').css('width', (progress.toFixed(2) * (3/5)) + 40 +'%');
|
||||
$(".progress").children('.progress-bar').html(progress.toFixed(2)+'% Uploaded');
|
||||
});
|
||||
this.on("queuecomplete", function() {
|
||||
$(".progress").children('.progress-bar').html('Complete');
|
||||
});
|
||||
this.removeFile(file);
|
||||
}
|
||||
};
|
||||
|
||||
// Function to encrypt a file, overide the file's data attribute with the encrypted value, and then call a callback function if supplied
|
||||
function encryptFile(file, callback) {
|
||||
var filetype = file.type;
|
||||
var filename = file.name;
|
||||
var shortName = file.name.hashCode();
|
||||
var fileID = file.ID;
|
||||
|
||||
// Start the file reader
|
||||
var reader = new FileReader();
|
||||
@ -92,30 +105,34 @@ function encryptFile(file, callback) {
|
||||
reader.onload = (function (callback) {
|
||||
return function (e) {
|
||||
// Create random key and iv
|
||||
var keyStr = randomString(16, '#aA');
|
||||
var ivStr = randomString(16, '#aA');
|
||||
var key = CryptoJS.enc.Utf8.parse(keyStr);
|
||||
var iv = CryptoJS.enc.Utf8.parse(ivStr);
|
||||
|
||||
// Display encryption message
|
||||
$(".progress-" + shortName).children('.progress-bar').css('width', '20%');
|
||||
$(".progress-" + shortName).children('.progress-bar').html('Encrypting...');
|
||||
var keyStr = randomString(24, '#aA');
|
||||
var ivStr = randomString(24, '#aA');
|
||||
|
||||
var worker = new Worker(encScriptSrc);
|
||||
|
||||
worker.addEventListener('message', function (e) {
|
||||
if (callback != null) {
|
||||
// Finish
|
||||
callback(e.data.encrypted, keyStr, ivStr, filetype, filename);
|
||||
switch (e.data.cmd)
|
||||
{
|
||||
case 'progress':
|
||||
var percentComplete = Math.round(e.data.processed * 100 / e.data.total);
|
||||
$("#progress-" + fileID).children('.progress-bar').css('width', (percentComplete * (2 / 5)) + 20 + '%');
|
||||
$("#progress-" + fileID).children('.progress-bar').html(percentComplete + '% Encrypted');
|
||||
break;
|
||||
case 'finish':
|
||||
if (callback != null) {
|
||||
// Finish
|
||||
callback(e.data.encrypted, keyStr, ivStr, filetype, fileID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
worker.onerror = function (err) {
|
||||
alert(err);
|
||||
|
||||
// An error occured
|
||||
$(".progress-" + shortName).children('.progress-bar').css('width', '100%');
|
||||
$(".progress-" + shortName).children('.progress-bar').html('Error Occured');
|
||||
$("#progress-" + fileID).children('.progress-bar').css('width', '100%');
|
||||
$("#progress-" + fileID).children('.progress-bar').removeClass('progress-bar-success');
|
||||
$("#progress-" + fileID).children('.progress-bar').addClass('progress-bar-danger');
|
||||
$("#progress-" + fileID).children('.progress-bar').html('Error Occured');
|
||||
}
|
||||
|
||||
// Execute worker with data
|
||||
@ -123,24 +140,31 @@ function encryptFile(file, callback) {
|
||||
{
|
||||
cmd: 'encrypt',
|
||||
script: aesScriptSrc,
|
||||
key: key,
|
||||
iv: iv,
|
||||
chunkSize: 1024,
|
||||
key: keyStr,
|
||||
iv: ivStr,
|
||||
chunkSize: chunkSize,
|
||||
file: e.target.result
|
||||
};
|
||||
worker.postMessage(objData, [objData.file]);
|
||||
};
|
||||
})(callback);
|
||||
|
||||
reader.onprogress = function (data) {
|
||||
if (data.lengthComputable) {
|
||||
var progress = parseInt(((data.loaded / data.total) * 100), 10);
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', (progress / 5) + '%');
|
||||
$('#progress-' + fileID).children('.progress-bar').html(progress + '% Loaded');
|
||||
}
|
||||
}
|
||||
|
||||
// Start async read
|
||||
var blob = file.slice(0, file.size);
|
||||
reader.readAsArrayBuffer(blob);
|
||||
}
|
||||
|
||||
function uploadFile(data, key, iv, filetype, filename)
|
||||
function uploadFile(data, key, iv, filetype, fileID)
|
||||
{
|
||||
$("#key").val(key);
|
||||
$("#iv").val(iv);
|
||||
$('#key-' + fileID).val(key);
|
||||
var blob = new Blob([data]);
|
||||
// Now we need to upload the file
|
||||
var fd = new FormData();
|
||||
@ -150,51 +174,61 @@ function uploadFile(data, key, iv, filetype, filename)
|
||||
fd.append('__RequestVerificationToken', $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val());
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.upload.addEventListener("progress", uploadProgress.bind(null, filename), false);
|
||||
xhr.addEventListener("load", uploadComplete.bind(null, filename), false);
|
||||
xhr.addEventListener("error", uploadFailed, false);
|
||||
xhr.addEventListener("abort", uploadCanceled, false);
|
||||
xhr.upload.addEventListener("progress", uploadProgress.bind(null, fileID), false);
|
||||
xhr.addEventListener("load", uploadComplete.bind(null, fileID, key), false);
|
||||
xhr.addEventListener("error", uploadFailed.bind(null, fileID), false);
|
||||
xhr.addEventListener("abort", uploadCanceled.bind(null, fileID), false);
|
||||
xhr.open("POST", uploadFileURL);
|
||||
xhr.send(fd);
|
||||
}
|
||||
|
||||
function uploadProgress(filename, evt) {
|
||||
var shortName = filename.hashCode();
|
||||
function uploadProgress(fileID, evt) {
|
||||
if (evt.lengthComputable) {
|
||||
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
|
||||
$(".progress-" + shortName).children('.progress-bar').css('width', (percentComplete * (3 / 5)) + 40 + '%');
|
||||
$(".progress-" + shortName).children('.progress-bar').html(percentComplete + '% Uploaded');
|
||||
}
|
||||
else {
|
||||
document.getElementById('progressNumber').innerHTML = 'unable to compute';
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', (percentComplete * (2 / 5)) + 60 + '%');
|
||||
$('#progress-' + fileID).children('.progress-bar').html(percentComplete + '% Uploaded');
|
||||
}
|
||||
}
|
||||
|
||||
function uploadComplete(filename, evt) {
|
||||
function uploadComplete(fileID, key, evt) {
|
||||
obj = JSON.parse(evt.target.responseText);
|
||||
var name = obj.result.name;
|
||||
var fullName = obj.result.url;
|
||||
var shortName = filename.hashCode();
|
||||
$('.progress-' + shortName).children('.progress-bar').css('width', '100%');
|
||||
$('.progress-' + shortName).children('.progress-bar').html('Complete');
|
||||
$('.links-' + shortName).append(' \
|
||||
<div class="col-sm-6"> \
|
||||
' + filename + ' \
|
||||
</div> \
|
||||
<div class="col-sm-3"> \
|
||||
<a href="' + fullName + '" target="_blank" class="alert-link">' + fullName + '</a> \
|
||||
</div> \
|
||||
<div class="col-sm-3"> \
|
||||
<button type="button" class="btn btn-default btn-xs generate-delete-link-' + name + '" id="' + name + '">Generate Deletion URL</button> \
|
||||
var fullName = decodeURIComponent(obj.result.url);
|
||||
var keyVar = decodeURIComponent(obj.result.keyVar);
|
||||
fullName = fullName.replace(keyVar, key);
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', '100%');
|
||||
$('#progress-' + fileID).children('.progress-bar').html('Complete');
|
||||
$('#upload-link-' + fileID).html('<p><a href="' + fullName + '" target="_blank" class="alert-link">' + fullName + '</a></p>');
|
||||
$('#link-' + fileID).append(' \
|
||||
<div class="panel-footer"> \
|
||||
<div class="row"> \
|
||||
<div class="col-sm-4 text-center"> \
|
||||
<button type="button" class="btn btn-default btn-sm" id="save-key-link-' + fileID + '">Save Key On Server</button> \
|
||||
</div> \
|
||||
<div class="col-sm-4 text-center"> \
|
||||
<button type="button" class="btn btn-default btn-sm" id="generate-delete-link-' + fileID + '">Generate Deletion URL</button> \
|
||||
</div> \
|
||||
<div class="col-sm-4 text-center"> \
|
||||
<button type="button" class="btn btn-default btn-sm" id="remove-link-' + fileID + '">Remove</button> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
');
|
||||
linkUploadDelete('.generate-delete-link-' + name + '');
|
||||
linkSaveKey('#save-key-link-' + fileID + '', name, key, fileID);
|
||||
linkUploadDelete('#generate-delete-link-' + fileID + '', name);
|
||||
linkRemove('#remove-link-' + fileID + '', fileID);
|
||||
}
|
||||
|
||||
function uploadFailed(evt) {
|
||||
alert("There was an error attempting to upload the file.");
|
||||
function uploadFailed(fileID, evt) {
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', '100%');
|
||||
$("#progress-" + fileID).children('.progress-bar').removeClass('progress-bar-success');
|
||||
$("#progress-" + fileID).children('.progress-bar').addClass('progress-bar-danger');
|
||||
$('#progress-' + fileID).children('.progress-bar').html('Upload Failed');
|
||||
}
|
||||
|
||||
function uploadCanceled(evt) {
|
||||
alert("The upload has been canceled by the user or the browser dropped the connection.");
|
||||
function uploadCanceled(fileID, evt) {
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', '100%');
|
||||
$("#progress-" + fileID).children('.progress-bar').removeClass('progress-bar-success');
|
||||
$("#progress-" + fileID).children('.progress-bar').addClass('progress-bar-warning');
|
||||
$('#progress-' + fileID).children('.progress-bar').html('Upload Canceled');
|
||||
}
|
||||
|
@ -29,10 +29,17 @@ namespace Teknik.Areas.Upload
|
||||
new { controller = "Upload", action = "Download", url = string.Empty },
|
||||
new[] { typeof(Controllers.UploadController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Upload.Download.Key",
|
||||
"dev",
|
||||
"Upload/{file}/{key}",
|
||||
new { controller = "Upload", action = "Download", url = string.Empty },
|
||||
new[] { typeof(Controllers.UploadController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Upload.Delete",
|
||||
"dev",
|
||||
"Upload/{url}/{deleteKey}",
|
||||
"Upload/{file}/{key}",
|
||||
new { controller = "Upload", action = "Delete", url = string.Empty, deleteKey = string.Empty },
|
||||
new[] { typeof(Controllers.UploadController).Namespace }
|
||||
);
|
||||
@ -105,13 +112,15 @@ namespace Teknik.Areas.Upload
|
||||
"~/Scripts/Dropzone/dropzone.js",
|
||||
"~/Areas/Upload/Scripts/Upload.js",
|
||||
"~/Scripts/bootbox/bootbox.min.js",
|
||||
"~/Scripts/Crypto-js/aes.js",
|
||||
"~/Scripts/Crypto-js/lib-typedarray.js"));
|
||||
"~/Scripts/Crypto-js/aes.js"));
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/cryptoWorker").Include(
|
||||
"~/Areas/Upload/Scripts/EncryptionWorker.js"));
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/crypto").Include(
|
||||
"~/Scripts/Crypto-js/aes.js",
|
||||
"~/Scripts/Crypto-js/lib-typedarray.js"));
|
||||
"~/Scripts/Crypto-js/enc-base64.js",
|
||||
"~/Scripts/Crypto-js/mode-ctr.js",
|
||||
"~/Scripts/Crypto-js/lib-typedarrays.js",
|
||||
"~/Scripts/Crypto-js/pad-nopadding.js"));
|
||||
|
||||
// Register Style Bundles
|
||||
BundleTable.Bundles.Add(new StyleBundle("~/Content/upload").Include(
|
||||
|
@ -4,9 +4,10 @@
|
||||
var encScriptSrc = '@Scripts.Url("~/bundles/cryptoWorker")';
|
||||
var aesScriptSrc = '@Scripts.Url("~/bundles/crypto")';
|
||||
var generateDeleteKeyURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action= "GenerateDeleteKey" })';
|
||||
var saveKeyToServerURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action= "SaveFileKey" })';
|
||||
var uploadFileURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action = "Upload" })';
|
||||
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Download")';
|
||||
var maxUploadSize = @(Model.Config.UploadConfig.MaxUploadSize / 100000);
|
||||
var chunkSize = @(Model.Config.UploadConfig.ChunkSize);
|
||||
</script>
|
||||
|
||||
@Styles.Render("~/Content/upload")
|
||||
@ -15,8 +16,6 @@
|
||||
<div class="row text-center">
|
||||
<form action="@Url.SubRouteUrl("upload", "Upload.Action", new { action = "Upload" })" class="dropzone" id="TeknikUpload" name="TeknikUpload" enctype="multipart/form-data">
|
||||
@Html.AntiForgeryToken()
|
||||
<input name="key" id="key" type="hidden" />
|
||||
<input name="iv" id="iv" type="hidden" />
|
||||
<div class="dz-message text-center" id="upload_message">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
|
@ -15,6 +15,8 @@ namespace Teknik.Configuration
|
||||
public string FileExtension { get; set; }
|
||||
public int UrlLength { get; set; }
|
||||
public bool IncludeExtension { get; set; }
|
||||
// The size of the chunk that the file will be encrypted/decrypted in (bytes)
|
||||
public int ChunkSize { get; set; }
|
||||
|
||||
public UploadConfig()
|
||||
{
|
||||
@ -28,6 +30,7 @@ namespace Teknik.Configuration
|
||||
FileExtension = "enc";
|
||||
UrlLength = 6;
|
||||
IncludeExtension = true;
|
||||
ChunkSize = 1024;
|
||||
}
|
||||
}
|
||||
}
|
109
Teknik/Scripts/Crypto-js/enc-base64.js
Normal file
109
Teknik/Scripts/Crypto-js/enc-base64.js
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var C_enc = C.enc;
|
||||
|
||||
/**
|
||||
* Base64 encoding strategy.
|
||||
*/
|
||||
var Base64 = C_enc.Base64 = {
|
||||
/**
|
||||
* Converts a word array to a Base64 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Base64 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
var map = this._map;
|
||||
|
||||
// Clamp excess bits
|
||||
wordArray.clamp();
|
||||
|
||||
// Convert
|
||||
var base64Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 3) {
|
||||
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
|
||||
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
|
||||
|
||||
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
|
||||
|
||||
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
|
||||
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding
|
||||
var paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
while (base64Chars.length % 4) {
|
||||
base64Chars.push(paddingChar);
|
||||
}
|
||||
}
|
||||
|
||||
return base64Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Base64 string to a word array.
|
||||
*
|
||||
* @param {string} base64Str The Base64 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
|
||||
*/
|
||||
parse: function (base64Str) {
|
||||
// Shortcuts
|
||||
var base64StrLength = base64Str.length;
|
||||
var map = this._map;
|
||||
|
||||
// Ignore padding
|
||||
var paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
var paddingIndex = base64Str.indexOf(paddingChar);
|
||||
if (paddingIndex != -1) {
|
||||
base64StrLength = paddingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
var nBytes = 0;
|
||||
for (var i = 0; i < base64StrLength; i++) {
|
||||
if (i % 4) {
|
||||
var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2);
|
||||
var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2);
|
||||
words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);
|
||||
nBytes++;
|
||||
}
|
||||
}
|
||||
|
||||
return WordArray.create(words, nBytes);
|
||||
},
|
||||
|
||||
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
|
||||
};
|
||||
}());
|
135
Teknik/Scripts/Crypto-js/enc-utf16.js
Normal file
135
Teknik/Scripts/Crypto-js/enc-utf16.js
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var C_enc = C.enc;
|
||||
|
||||
/**
|
||||
* UTF-16 BE encoding strategy.
|
||||
*/
|
||||
var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 BE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 BE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var utf16Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 2) {
|
||||
var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 BE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 BE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
|
||||
*/
|
||||
parse: function (utf16Str) {
|
||||
// Shortcut
|
||||
var utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < utf16StrLength; i++) {
|
||||
words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF-16 LE encoding strategy.
|
||||
*/
|
||||
C_enc.Utf16LE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 LE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 LE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var utf16Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 2) {
|
||||
var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 LE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 LE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
|
||||
*/
|
||||
parse: function (utf16Str) {
|
||||
// Shortcut
|
||||
var utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < utf16StrLength; i++) {
|
||||
words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
}
|
||||
};
|
||||
|
||||
function swapEndian(word) {
|
||||
return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
|
||||
}
|
||||
}());
|
44
Teknik/Scripts/Crypto-js/mode-ctr.js
Normal file
44
Teknik/Scripts/Crypto-js/mode-ctr.js
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
/**
|
||||
* Counter block mode.
|
||||
*/
|
||||
CryptoJS.mode.CTR = (function () {
|
||||
var CTR = CryptoJS.lib.BlockCipherMode.extend();
|
||||
|
||||
var Encryptor = CTR.Encryptor = CTR.extend({
|
||||
processBlock: function (words, offset) {
|
||||
// Shortcuts
|
||||
var cipher = this._cipher
|
||||
var blockSize = cipher.blockSize;
|
||||
var iv = this._iv;
|
||||
var counter = this._counter;
|
||||
|
||||
// Generate keystream
|
||||
if (iv) {
|
||||
counter = this._counter = iv.slice(0);
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
}
|
||||
var keystream = counter.slice(0);
|
||||
cipher.encryptBlock(keystream, 0);
|
||||
|
||||
// Increment counter
|
||||
counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0
|
||||
|
||||
// Encrypt
|
||||
for (var i = 0; i < blockSize; i++) {
|
||||
words[offset + i] ^= keystream[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CTR.Decryptor = Encryptor;
|
||||
|
||||
return CTR;
|
||||
}());
|
16
Teknik/Scripts/Crypto-js/pad-nopadding.js
Normal file
16
Teknik/Scripts/Crypto-js/pad-nopadding.js
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
/**
|
||||
* A noop padding strategy.
|
||||
*/
|
||||
CryptoJS.pad.NoPadding = {
|
||||
pad: function () {
|
||||
},
|
||||
|
||||
unpad: function () {
|
||||
}
|
||||
};
|
Binary file not shown.
@ -289,7 +289,11 @@
|
||||
<Content Include="Scripts\bootstrap.js" />
|
||||
<Content Include="Scripts\bootstrap.min.js" />
|
||||
<Content Include="Scripts\common.js" />
|
||||
<Content Include="Scripts\Crypto-js\enc-base64.js" />
|
||||
<Content Include="Scripts\Crypto-js\enc-utf16.js" />
|
||||
<Content Include="Scripts\Crypto-js\lib-typedarrays.js" />
|
||||
<Content Include="Scripts\Crypto-js\mode-ctr.js" />
|
||||
<Content Include="Scripts\Crypto-js\pad-nopadding.js" />
|
||||
<Content Include="Scripts\Dropzone\dropzone.js" />
|
||||
<Content Include="Scripts\jquery-2.1.4.js" />
|
||||
<Content Include="Scripts\jquery-2.1.4.min.js" />
|
||||
|
Loading…
Reference in New Issue
Block a user