Skip to content

Instantly share code, notes, and snippets.

@Ayms

Ayms/gist:6451926

Last active Aug 28, 2020
Embed
What would you like to do?
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;
};
@monscamus

This comment has been minimized.

Copy link

@monscamus monscamus commented Jul 14, 2020

Really helpful - thanks Ayms! Is TextToArrayBufferView something that you've wrote - I don't see it in the File API?

@Ayms

This comment has been minimized.

Copy link
Owner Author

@Ayms Ayms commented Jul 15, 2020

Thanks but sorry I hardly reminded this gist so can't tell what TexToArrayBufferView was, probably a simple function to transform the text format of the key to WebCrypto ArrayBuffer format

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.