From 59e213690e4d91ab24903c68b6b49c7162361b57 Mon Sep 17 00:00:00 2001 From: Uncled1023 Date: Mon, 18 Jan 2016 16:57:26 -0800 Subject: [PATCH] Fixed encrypted data not being sent to server. Still having issues with the encryption and subsequent conversions. --- .../Areas/Upload/Controllers/UploadController.cs | 16 +--- Teknik/Areas/Upload/Models/FileModel.cs | 20 +++++ Teknik/Areas/Upload/Scripts/EncryptionWorker.js | 51 ++++++++++- Teknik/Areas/Upload/Scripts/Upload.js | 98 +++++++++++---------- Teknik/Areas/Upload/UploadAreaRegistration.cs | 6 +- Teknik/Areas/Upload/Uploader.cs | 15 ++-- .../Upload/Scripts => Scripts/Crypto-js}/aes.js | 0 Teknik/Scripts/Crypto-js/lib-typedarrays.js | 62 +++++++++++++ Teknik/Scripts/_references.js | Bin 2482 -> 2564 bytes Teknik/Teknik.csproj | 4 +- 10 files changed, 198 insertions(+), 74 deletions(-) create mode 100644 Teknik/Areas/Upload/Models/FileModel.cs rename Teknik/{Areas/Upload/Scripts => Scripts/Crypto-js}/aes.js (100%) create mode 100644 Teknik/Scripts/Crypto-js/lib-typedarrays.js diff --git a/Teknik/Areas/Upload/Controllers/UploadController.cs b/Teknik/Areas/Upload/Controllers/UploadController.cs index c8ce766..d44798d 100644 --- a/Teknik/Areas/Upload/Controllers/UploadController.cs +++ b/Teknik/Areas/Upload/Controllers/UploadController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; +using Teknik.Areas.Upload.Models; using Teknik.Areas.Upload.ViewModels; using Teknik.Controllers; @@ -28,20 +29,9 @@ namespace Teknik.Areas.Upload.Controllers [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] - public ActionResult Upload(string iv) + public ActionResult Upload(string fileType, string iv, HttpPostedFileWrapper data) { - Models.Upload upload = null; - foreach (string fileName in Request.Files) - { - HttpPostedFileBase file = Request.Files[fileName]; - //Save file content goes here - string fName = file.FileName; - if (file != null && file.ContentLength > 0) - { - upload = Uploader.SaveFile(file, iv); - break; - } - } + 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"); diff --git a/Teknik/Areas/Upload/Models/FileModel.cs b/Teknik/Areas/Upload/Models/FileModel.cs new file mode 100644 index 0000000..6654cb9 --- /dev/null +++ b/Teknik/Areas/Upload/Models/FileModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.Areas.Upload.Models +{ + public class FileModel + { + public string FileName { get; set; } + + public string FileType { get; set; } + + public string IV { get; set; } + + public string ContentAsBase64String { get; set; } + } + +} diff --git a/Teknik/Areas/Upload/Scripts/EncryptionWorker.js b/Teknik/Areas/Upload/Scripts/EncryptionWorker.js index cb1f165..52538d6 100644 --- a/Teknik/Areas/Upload/Scripts/EncryptionWorker.js +++ b/Teknik/Areas/Upload/Scripts/EncryptionWorker.js @@ -4,12 +4,21 @@ switch (data.cmd) { case 'encrypt': + var wordArray = CryptoJS.lib.WordArray.create(new Uint8Array(data.file)) + + //var dataStr = ab2str(data.file); + // encrypt the passed in file data - var encrypted = CryptoJS.AES.encrypt(data.file, data.key, { iv: data.iv }); + var encrypted = CryptoJS.AES.encrypt(wordArray, data.key, { iv: data.iv }); + var encByteArray = wordToByteArray(encrypted); - var cipherText = encrypted.toString(); + // patch it all back together for the trip home + var objData = + { + encrypted: encByteArray.buffer + }; - self.postMessage(cipherText); + self.postMessage(objData, [objData.encrypted]); break; case 'decrypt': // decrypt the passed in file data @@ -20,4 +29,38 @@ self.postMessage(fileText); break; } -}, false); \ No newline at end of file +}, 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 _base64ToArrayBuffer(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; +} + +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 Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} \ No newline at end of file diff --git a/Teknik/Areas/Upload/Scripts/Upload.js b/Teknik/Areas/Upload/Scripts/Upload.js index a0f0d84..0a20a37 100644 --- a/Teknik/Areas/Upload/Scripts/Upload.js +++ b/Teknik/Areas/Upload/Scripts/Upload.js @@ -34,40 +34,21 @@ Dropzone.options.TeknikUpload = { addRemoveLinks: true, autoProcessQueue: false, clickable: true, - accept: function (file, done) { - encryptFile(file, done); - }, init: function() { - this.on("sending", function (file, xhr, formData) { - var data = new FormData(); - data.append('file-content', file.data); - data.append('file-iv', file.iv); - formData = data; - }); - this.on("success", function (file, response) { - obj = JSON.parse(response); - var name = obj.result.name; - var fullName = obj.result.url; + this.on("addedfile", function (file, responseText) { + // Create the UI element for the new item var short_name = file.name.split(".")[0].hashCode(); $("#upload-links").css('display', 'inline', 'important'); $("#upload-links").prepend(' \ \ '); - linkUploadDelete('.generate-delete-link-'+short_name+''); - }); - this.on("addedfile", function (file, responseText) { - - // We will be handling encryption and uploading here // Encrypt the file encryptFile(file, uploadFile); @@ -97,18 +78,21 @@ Dropzone.options.TeknikUpload = { } }; -function uploadFile(data, key, iv) +function uploadFile(data, key, iv, filetype, filename) { $("#key").val(key); $("#iv").val(iv); + var blob = new Blob([data]); // Now we need to upload the file var fd = new FormData(); - fd.append('data', data); + fd.append('fileType', filetype); fd.append('iv', iv); - fd.append('content-type', document.getElementById('file').files[0].type); + fd.append('data', blob); + fd.append('__RequestVerificationToken', $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val()); + var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); - xhr.addEventListener("load", uploadComplete, false); + xhr.addEventListener("load", uploadComplete.bind(null, filename), false); xhr.addEventListener("error", uploadFailed, false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", uploadFileURL); @@ -119,16 +103,33 @@ function uploadProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); $(".progress").children('.progress-bar').css('width', (percentComplete * (3 / 5)) + 40 + '%'); - $(".progress").children('.progress-bar').html(progress.toFixed(2) + '% Uploaded'); + $(".progress").children('.progress-bar').html(percentComplete + '% Uploaded'); } else { document.getElementById('progressNumber').innerHTML = 'unable to compute'; } } -function uploadComplete(evt) { - /* This event is raised when the server send back a response */ - alert(evt.target.responseText); +function uploadComplete(filename, evt) { + obj = JSON.parse(evt.target.responseText); + var name = obj.result.name; + var fullName = obj.result.url; + var short_name = filename.split(".")[0].hashCode(); + $("#upload-links").css('display', 'inline', 'important'); + $("#upload-links").prepend(' \ + \ + '); + linkUploadDelete('.generate-delete-link-' + name + ''); } function uploadFailed(evt) { @@ -139,9 +140,11 @@ function uploadCanceled(evt) { alert("The upload has been canceled by the user or the browser dropped the connection."); } - // 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; + // Start the file reader var reader = new FileReader(); @@ -163,19 +166,20 @@ function encryptFile(file, callback) { worker.addEventListener('message', function (e) { if (callback != null) { // Finish - callback(e.data, keyStr, ivStr); + callback(e.data.encrypted, keyStr, ivStr, filetype, filename); } }); // Execute worker with data - worker.postMessage({ - cmd: 'encrypt', - script: aesScriptSrc, - key: key, - iv: iv, - file: e.target.result, - chunkSize: 1024 - }); + var objData = + { + cmd: 'encrypt', + script: aesScriptSrc, + key: key, + iv: iv, + file: e.target.result + }; + worker.postMessage(objData, [objData.file]); }; })(callback); @@ -190,5 +194,5 @@ function encryptFile(file, callback) { // Start async read var blob = file.slice(0, file.size); - reader.readAsDataURL(blob); -} \ No newline at end of file + reader.readAsArrayBuffer(blob); +} diff --git a/Teknik/Areas/Upload/UploadAreaRegistration.cs b/Teknik/Areas/Upload/UploadAreaRegistration.cs index 1137a97..5eb1046 100644 --- a/Teknik/Areas/Upload/UploadAreaRegistration.cs +++ b/Teknik/Areas/Upload/UploadAreaRegistration.cs @@ -105,11 +105,13 @@ namespace Teknik.Areas.Upload "~/Scripts/Dropzone/dropzone.js", "~/Areas/Upload/Scripts/Upload.js", "~/Scripts/bootbox/bootbox.min.js", - "~/Areas/Upload/Scripts/aes.js")); + "~/Scripts/Crypto-js/aes.js", + "~/Scripts/Crypto-js/lib-typedarray.js")); BundleTable.Bundles.Add(new ScriptBundle("~/bundles/cryptoWorker").Include( "~/Areas/Upload/Scripts/EncryptionWorker.js")); BundleTable.Bundles.Add(new ScriptBundle("~/bundles/crypto").Include( - "~/Areas/Upload/Scripts/aes.js")); + "~/Scripts/Crypto-js/aes.js", + "~/Scripts/Crypto-js/lib-typedarray.js")); // Register Style Bundles BundleTable.Bundles.Add(new StyleBundle("~/Content/upload").Include( diff --git a/Teknik/Areas/Upload/Uploader.cs b/Teknik/Areas/Upload/Uploader.cs index 91c6bf4..74cc0b2 100644 --- a/Teknik/Areas/Upload/Uploader.cs +++ b/Teknik/Areas/Upload/Uploader.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Web; +using System.IO; using Teknik.Configuration; using Teknik.Models; @@ -9,17 +10,17 @@ namespace Teknik.Areas.Upload { public static class Uploader { - public static Models.Upload SaveFile(HttpPostedFileBase file) + public static Models.Upload SaveFile(HttpPostedFileWrapper file, string contentType) { - return SaveFile(file, null, null); + return SaveFile(file, contentType, null, null); } - public static Models.Upload SaveFile(HttpPostedFileBase file, string iv) + public static Models.Upload SaveFile(HttpPostedFileWrapper file, string contentType, string iv) { - return SaveFile(file, iv, null); + return SaveFile(file, contentType, iv, null); } - public static Models.Upload SaveFile(HttpPostedFileBase file, string iv, string key) + public static Models.Upload SaveFile(HttpPostedFileWrapper file, string contentType, string iv, string key) { Config config = Config.Load(); TeknikEntities db = new TeknikEntities(); @@ -31,7 +32,7 @@ namespace Teknik.Areas.Upload file.SaveAs(fileName); // Generate a unique url - string extension = (config.UploadConfig.IncludeExtension) ? Utility.GetDefaultExtension(file.ContentType) : string.Empty; + string extension = (config.UploadConfig.IncludeExtension) ? Utility.GetDefaultExtension(contentType) : string.Empty; string url = Utility.RandomString(config.UploadConfig.UrlLength) + extension; while (db.Uploads.Where(u => u.Url == url).FirstOrDefault() != null) { @@ -44,7 +45,7 @@ namespace Teknik.Areas.Upload upload.Url = url; upload.FileName = fileName; upload.ContentLength = file.ContentLength; - upload.ContentType = file.ContentType; + upload.ContentType = contentType; upload.Key = key; upload.IV = iv; diff --git a/Teknik/Areas/Upload/Scripts/aes.js b/Teknik/Scripts/Crypto-js/aes.js similarity index 100% rename from Teknik/Areas/Upload/Scripts/aes.js rename to Teknik/Scripts/Crypto-js/aes.js diff --git a/Teknik/Scripts/Crypto-js/lib-typedarrays.js b/Teknik/Scripts/Crypto-js/lib-typedarrays.js new file mode 100644 index 0000000..511137b --- /dev/null +++ b/Teknik/Scripts/Crypto-js/lib-typedarrays.js @@ -0,0 +1,62 @@ +/* +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 () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + typedArray instanceof Uint8ClampedArray || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; +}()); diff --git a/Teknik/Scripts/_references.js b/Teknik/Scripts/_references.js index f0d58209db5dfa43173fd7be92b943b7405a194b..fc0f90aa393b683607ea7bd4cd065259c140846d 100644 GIT binary patch delta 90 zcmdla+#<4}jA`==CIcq^WQHP!N`?Z45{7&RU52d5g-q^-XkrY-4EhW?44Di`Kouom a)u{|A42eLUML@EWp?Km#+szWJvseHKD;4bk delta 26 icmZn>*(AK7jEOaoA(f$c;zIw;5lnteo3mJFu>b&btO#NN diff --git a/Teknik/Teknik.csproj b/Teknik/Teknik.csproj index 47c99ed..52972e6 100644 --- a/Teknik/Teknik.csproj +++ b/Teknik/Teknik.csproj @@ -166,6 +166,7 @@ + @@ -208,7 +209,7 @@ - + @@ -288,6 +289,7 @@ +