var CryptoUtils = { cypher: "AES-GCM", key: null, urlSafeKey: null, initialize: function(key = null) { if(key === null) { return this.generateKey(); } else { this.urlSafeKey = key; return this.importKey(this.base64ToArrayBuffer(key)); } }, generateKey: function() { var self = this; return window.crypto.subtle.generateKey( { name: this.cypher, length: 256, }, true, ["encrypt", "decrypt"] ).then(function(k){ self.key = k; return window.crypto.subtle.exportKey("raw", k) }).then(function(keydata) { console.log(keydata); self.urlSafeKey = self.arrayBufferToBase64(keydata); }).catch(function(err){ console.error(err) }); }, encrypt: function(data) { var self = this; var iv = window.crypto.getRandomValues(new Uint8Array(12)); return window.crypto.subtle.encrypt( { name: this.cypher, iv: iv, }, this.key, data ).then(function(encrypted){ return new Blob([iv, encrypted], {type: 'application/octet-binary'}); }); }, decrypt: function(data) { var self = this; return window.crypto.subtle.decrypt( { name: this.cypher, iv: data.slice(0,12), }, this.key, data.slice(12) ); }, importKey: function(key) { var self = this; return window.crypto.subtle.importKey( "raw", key, { name: self.cypher }, true, ["encrypt", "decrypt"] ).then(function(k){ self.key = k; }); }, arrayBufferToBase64: function(a) { return btoa(String.fromCharCode(...new Uint8Array(a))) }, base64ToArrayBuffer: function(b) { var str = atob(b); var buf = new ArrayBuffer(str.length); var bufView = new Uint8Array(buf); for (var i=0, strLen=str.length; i