Skip to content

Instantly share code, notes, and snippets.

@lenisko
Forked from Ayms/gist:6451926
Created February 14, 2019 01:14
Show Gist options
  • Save lenisko/db937642b294d651507866b1aa8c7adb to your computer and use it in GitHub Desktop.
Save lenisko/db937642b294d651507866b1aa8c7adb to your computer and use it in GitHub Desktop.
WebCrypto code example - Upload a file, encrypt it, calculate the hash and store the results using indexedDB

Code example using WebCrypto, File API, indexedDB, createObjectURL and Workers.

<input type="file" onsubmit="process_upload">
var workerjs=' \
  onmessage=function(evt) { \
		var encrypt=crypto.workersubtle.encrypt({name:"AES-CBC",iv:new Uint8Array(16)},evt.data[0]); \
		var buffer=evt.data[1]; \
		var block=XXX; \
		while (buffer.length) { \
			encrypt.process(buffer.subarray(0,block)).done(function(result) { \
				postMessage(result) \
			}); \
			buffer=buffer.subarray(Math.min(buffer.length,block)); \
		}; \
		encrypt.finish().done(function(result) { \
			postMessage([result]); \
		}); \
	} \
';

var process_upload=function() {
	var file=this.files[0];
	var process=function(key) {
		var reader=new FileReader();
		var readed=function() {
			var request={};
			var file_enc=[];
			var size=reader.result.byteLength;
			var tsize=0;
			var worker=new Worker(URL.createObjectURL(new Blob([workerjs])));
			var h=crypto.subtle.digest('SHA-256'); 
			worker.onmessage=function(evt) {
				var res=(evt.data instanceof Array)?evt.data[0]:evt.data;
				tsize +=res.length;//display a progress bar (tsize/size)*100%
				file_enc.push(res);
				h.process(res).then(function() {
					if (evt.data instanceof Array) { //end
						request.blob=new Blob(file_enc,{type:'application/octet-binary'});
						request.type=file.type;
						this.finish(res).done(function(result) {
							request.file_hash=result;
							store_DB(request);
						});
					};
				});
			};
			worker.postMessage([key,new Uint8Array(reader.result)]);
		};
		reader.addEventListener("loadend",readed,false);
		reader.readAsArrayBuffer(file);
	};
	crypto.importKey("raw",TextToArrayBufferView('00112233445566778899aabbccddeeff'),'AES-CBC',false,['encrypt','decrypt']).done(function(result) {process(result)});
};

var open_db=function() {
	var db=demoDB.db;
	return db.transaction(['encrypted_files'],'readwrite').objectStore('encrypted_files');
};

var store_DB=function(request) {
	var objectStore=open_db();
	objectStore.put({hash:request.file_hash,type:request.type,blob:request.blob});
};

var demoDB=indexedDB.open('demo',1);

demoDB.onupgradeneeded=function(evt) {
	var db=evt.target.result;
	db.createObjectStore('encrypted_files',{keyPath:'hash'});
};

demoDB.onsuccess=function (evt) {
	demoDB.db=evt.target.result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment