diff --git a/crypto.html b/crypto.html
index e17e4ccf..4dd686a2 100644
--- a/crypto.html
+++ b/crypto.html
@@ -106,7 +106,7 @@
(function () {
// Constants/Enums
- var encTypes = {
+ const encTypes = {
AesCbc256_B64: 0,
AesCbc128_HmacSha256_B64: 1,
AesCbc256_HmacSha256_B64: 2,
@@ -118,80 +118,86 @@
// Classes
- var Cipher = function (encType, iv, ct, mac) {
- if (!arguments.length) {
- this.encType = null;
- this.iv = null;
- this.ct = null;
+ class Cipher {
+ constructor(encType, iv, ct, mac) {
+ if (!arguments.length) {
+ this.encType = null;
+ this.iv = null;
+ this.ct = null;
+ this.mac = null;
+ this.string = null;
+ return;
+ }
+
+ this.encType = encType;
+ this.iv = iv;
+ this.ct = ct;
+ this.string = encType + '.' + iv.b64 + '|' + ct.b64;
+
this.mac = null;
- this.string = null;
- return;
- }
-
- this.encType = encType;
- this.iv = iv;
- this.ct = ct;
- this.string = encType + '.' + iv.b64 + '|' + ct.b64;
-
- this.mac = null;
- if (mac) {
- this.mac = mac;
- this.string += ('|' + mac.b64);
+ if (mac) {
+ this.mac = mac;
+ this.string += ('|' + mac.b64);
+ }
}
}
- var ByteData = function (buf) {
- if (!arguments.length) {
- this.arr = null;
- this.b64 = null;
- return;
- }
+ class ByteData {
+ constructor(buf) {
+ if (!arguments.length) {
+ this.arr = null;
+ this.b64 = null;
+ return;
+ }
- this.arr = new Uint8Array(buf);
- this.b64 = toB64(buf);
+ this.arr = new Uint8Array(buf);
+ this.b64 = toB64(buf);
+ }
}
- var SymmetricCryptoKey = function (buf) {
- if (!arguments.length) {
- this.key = new ByteData();
- this.encKey = new ByteData();
- this.macKey = new ByteData();
- return;
+ class SymmetricCryptoKey {
+ constructor(buf) {
+ if (!arguments.length) {
+ this.key = new ByteData();
+ this.encKey = new ByteData();
+ this.macKey = new ByteData();
+ return;
+ }
+
+ this.key = new ByteData(buf);
+
+ // First half
+ let encKey = this.key.arr.slice(0, this.key.arr.length / 2).buffer;
+ this.encKey = new ByteData(encKey);
+
+ // Second half
+ let macKey = this.key.arr.slice(this.key.arr.length / 2).buffer;
+ this.macKey = new ByteData(macKey);
}
-
- this.key = new ByteData(buf);
-
- // First half
- var encKey = this.key.arr.slice(0, this.key.arr.length / 2).buffer;
- this.encKey = new ByteData(encKey);
-
- // Second half
- var macKey = this.key.arr.slice(this.key.arr.length / 2).buffer;
- this.macKey = new ByteData(macKey);
}
// Helpers
function fromUtf8(str) {
- var strUtf8 = unescape(encodeURIComponent(str)),
+ let strUtf8 = unescape(encodeURIComponent(str)),
bytes = new Uint8Array(strUtf8.length);
- for (var i = 0; i < strUtf8.length; i++) {
+ for (let i = 0; i < strUtf8.length; i++) {
bytes[i] = strUtf8.charCodeAt(i);
}
return bytes.buffer;
}
function toUtf8(buf) {
- var bytes = new Uint8Array(buf),
+ let bytes = new Uint8Array(buf),
encodedString = String.fromCharCode.apply(null, bytes),
decodedString = decodeURIComponent(escape(encodedString));
return decodedString;
}
function toB64(buf) {
- var binary = '',
+ let binary = '',
bytes = new Uint8Array(buf);
- for (var i = 0; i < bytes.byteLength; i++) {
+ for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
@@ -204,80 +210,80 @@
// Crypto
function pbkdf2(password, salt, iterations, length) {
- var importAlg = {
+ let importAlg = {
name: 'PBKDF2'
};
- var deriveAlg = {
+ let deriveAlg = {
name: 'PBKDF2',
salt: salt,
iterations: iterations,
hash: { name: 'SHA-256' }
};
- var aesOptions = {
+ let aesOptions = {
name: 'AES-CBC',
length: 256
};
return window.crypto.subtle.importKey('raw', password, importAlg, false, ['deriveKey'])
- .then(function (importedKey) {
+ .then((importedKey) => {
return window.crypto.subtle.deriveKey(deriveAlg, importedKey, aesOptions, true, ['encrypt']);
- }).then(function (derivedKey) {
+ }).then((derivedKey) => {
return window.crypto.subtle.exportKey('raw', derivedKey);
- }).then(function (exportedKey) {
+ }).then((exportedKey) => {
return new ByteData(exportedKey);
- }).catch(function (err) {
+ }).catch((err) => {
console.error(err);
});
}
function aesEncrypt(data, encKey, macKey) {
- var keyOptions = {
+ let keyOptions = {
name: 'AES-CBC'
};
- var encOptions = {
+ let encOptions = {
name: 'AES-CBC',
iv: new Uint8Array(16)
};
window.crypto.getRandomValues(encOptions.iv);
- var ivData = new ByteData(encOptions.iv.buffer);
+ let ivData = new ByteData(encOptions.iv.buffer);
- var ctData, macData;
+ let ctData, macData;
return window.crypto.subtle.importKey('raw', encKey.arr.buffer, keyOptions, false, ['encrypt'])
- .then(function (importedKey) {
+ .then((importedKey) => {
return window.crypto.subtle.encrypt(encOptions, importedKey, data);
- }).then(function (encryptedBuffer) {
+ }).then((encryptedBuffer) => {
ctData = new ByteData(encryptedBuffer);
if (!macKey) {
return null;
}
- var dataForMac = buildDataForMac(ivData.arr, ctData.arr);
+ let dataForMac = buildDataForMac(ivData.arr, ctData.arr);
return computeMac(dataForMac.buffer, macKey.arr.buffer);
- }).then(function (macBuffer) {
- var type = encTypes.AesCbc256_B64;
+ }).then((macBuffer) => {
+ let type = encTypes.AesCbc256_B64;
if (macBuffer) {
type = encTypes.AesCbc256_HmacSha256_B64;
macData = new ByteData(macBuffer);
}
return new Cipher(type, ivData, ctData, macData);
- }).catch(function (err) {
+ }).catch((err) => {
console.error(err);
});
}
function aesDecrypt(cipher, encKey, macKey) {
- var keyOptions = {
+ let keyOptions = {
name: 'AES-CBC'
};
- var decOptions = {
+ let decOptions = {
name: 'AES-CBC',
iv: cipher.iv.arr.buffer
};
- var checkMacPromise = new Promise(function (resolve) {
+ let checkMacPromise = new Promise((resolve) => {
if (cipher.encType == encTypes.AesCbc256_B64) {
resolve(false);
return;
@@ -289,65 +295,65 @@
});
return checkMacPromise
- .then(function (checkMac) {
+ .then((checkMac) => {
if (!checkMac) {
return null;
}
- var dataForMac = buildDataForMac(cipher.iv.arr, cipher.ct.arr);
+ let dataForMac = buildDataForMac(cipher.iv.arr, cipher.ct.arr);
return computeMac(dataForMac.buffer, macKey.arr.buffer)
})
- .then(function (macBuffer) {
+ .then((macBuffer) => {
if (!macBuffer) {
return true;
}
return macsEqual(cipher.mac.arr.buffer, macBuffer, macKey.arr.buffer);
- }).then(function (macsMatch) {
+ }).then((macsMatch) => {
if (macsMatch === false) {
throw 'MAC check failed.';
}
return window.crypto.subtle.importKey('raw', encKey.arr.buffer, keyOptions, false, ['decrypt']);
- }).then(function (importedKey) {
+ }).then((importedKey) => {
return window.crypto.subtle.decrypt(decOptions, importedKey, cipher.ct.arr.buffer);
- }).catch(function (err) {
+ }).catch((err) => {
console.error(err);
});
}
function computeMac(data, key) {
- var alg = {
+ let alg = {
name: 'HMAC',
hash: { name: 'SHA-256' }
};
return window.crypto.subtle.importKey('raw', key, alg, false, ['sign'])
- .then(function (importedKey) {
+ .then((importedKey) => {
return window.crypto.subtle.sign(alg, importedKey, data);
});
}
function macsEqual(mac1Data, mac2Data, key) {
- var alg = {
+ let alg = {
name: 'HMAC',
hash: { name: 'SHA-256' }
};
- var mac1, importedMacKey;
+ let mac1, importedMacKey;
return window.crypto.subtle.importKey('raw', key, alg, false, ['sign'])
- .then(function (importedKey) {
+ .then((importedKey) => {
importedMacKey = importedKey;
return window.crypto.subtle.sign(alg, importedMacKey, mac1Data);
- }).then(function (mac) {
+ }).then((mac) => {
mac1 = mac;
return window.crypto.subtle.sign(alg, importedMacKey, mac2Data);
- }).then(function (mac2) {
+ }).then((mac2) => {
if (mac1.byteLength !== mac2.byteLength) {
return false;
}
- var arr1 = new Uint8Array(mac1);
- var arr2 = new Uint8Array(mac2);
+ let arr1 = new Uint8Array(mac1);
+ let arr2 = new Uint8Array(mac2);
- for (var i = 0; i < arr2.length; i++) {
+ for (let i = 0; i < arr2.length; i++) {
if (arr1[i] !== arr2[i]) {
return false;
}
@@ -358,41 +364,41 @@
}
function buildDataForMac(ivArr, ctArr) {
- var dataForMac = new Uint8Array(ivArr.length + ctArr.length);
+ let dataForMac = new Uint8Array(ivArr.length + ctArr.length);
dataForMac.set(ivArr, 0);
dataForMac.set(ctArr, ivArr.length);
return dataForMac;
}
function generateRsaKeypair() {
- var rsaOptions = {
+ let rsaOptions = {
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 65537
hash: { name: 'SHA-1' }
};
- var keypair, publicKey;
+ let keypair, publicKey;
return window.crypto.subtle.generateKey(rsaOptions, true, ['encrypt', 'decrypt'])
- .then(function (generatedKey) {
+ .then((generatedKey) => {
keypair = generatedKey;
return window.crypto.subtle.exportKey('spki', keypair.publicKey);
- }).then(function (exportedKey) {
+ }).then((exportedKey) => {
publicKey = new ByteData(exportedKey);
return window.crypto.subtle.exportKey('pkcs8', keypair.privateKey);
- }).then(function (exportedKey) {
+ }).then((exportedKey) => {
return {
publicKey: publicKey,
privateKey: new ByteData(exportedKey)
};
- }).catch(function (err) {
+ }).catch((err) => {
console.error(err);
});
}
// App
- var vm = new Vue({
+ let vm = new Vue({
el: '#app',
data: {
email: '',
@@ -428,27 +434,27 @@
},
watch: {
masterKey: function (newMasterKey) {
- var self = this;
+ let self = this;
if (!newMasterKey || !newMasterKey.arr || !self.masterPasswordBuffer) {
return new ByteData();
}
pbkdf2(newMasterKey.arr.buffer, self.masterPasswordBuffer, 1, 256)
- .then(function (masterKeyHash) {
+ .then((masterKeyHash) => {
self.masterKeyHash = masterKeyHash;
});
}
},
methods: {
generateKeys: function () {
- var self = this;
+ let self = this;
- var symKey = new Uint8Array(512 / 8);
+ let symKey = new Uint8Array(512 / 8);
window.crypto.getRandomValues(symKey);
self.symKey = new SymmetricCryptoKey(symKey);
- generateRsaKeypair().then(function (keypair) {
+ generateRsaKeypair().then((keypair) => {
self.publicKey = keypair.publicKey;
self.privateKey = keypair.privateKey;
});
@@ -456,30 +462,30 @@
}
});
- vm.$watch(function () {
+ vm.$watch(() => {
return {
masterPassword: vm.masterPasswordBuffer,
email: vm.emailBuffer,
iterations: vm.pbkdf2Iterations
};
- }, function (newVal, oldVal) {
+ }, (newVal, oldVal) => {
if (!newVal.masterPassword || !newVal.email || !newVal.iterations || newVal.iterations < 1) {
vm.masterKey = new ByteData();
return;
}
pbkdf2(newVal.masterPassword, newVal.email, newVal.iterations, 256)
- .then(function (masterKey) {
+ .then((masterKey) => {
vm.masterKey = masterKey;
});
});
- vm.$watch(function () {
+ vm.$watch(() => {
return {
symKey: vm.symKey,
secret: vm.secretBuffer
};
- }, function (newVal, oldVal) {
+ }, (newVal, oldVal) => {
if (!newVal.symKey || !newVal.secret) {
vm.protectedSecret = new Cipher();
vm.unprotectedSecret = '';
@@ -487,50 +493,50 @@
}
aesEncrypt(newVal.secret, newVal.symKey.encKey, newVal.symKey.macKey)
- .then(function (cipher) {
+ .then((cipher) => {
vm.protectedSecret = cipher;
return aesDecrypt(vm.protectedSecret, newVal.symKey.encKey, newVal.symKey.macKey);
- }).then(function (secret) {
+ }).then((secret) => {
vm.unprotectedSecret = toUtf8(secret);
});
});
- vm.$watch(function () {
+ vm.$watch(() => {
return {
masterKey: vm.masterKey,
symKey: vm.symKey
};
- }, function (newVal, oldVal) {
+ }, (newVal, oldVal) => {
if (!newVal.masterKey || !newVal.masterKey.arr || !newVal.symKey || !newVal.symKey.key) {
vm.protectedSymKey = new Cipher();
return;
}
aesEncrypt(newVal.symKey.key.arr, newVal.masterKey, null)
- .then(function (cipher) {
+ .then((cipher) => {
vm.protectedSymKey = cipher;
return aesDecrypt(vm.protectedSymKey, newVal.masterKey, null);
- }).then(function (unprotectedSymKey) {
+ }).then((unprotectedSymKey) => {
vm.unprotectedSymKey = new ByteData(unprotectedSymKey);
});
});
- vm.$watch(function () {
+ vm.$watch(() => {
return {
symKey: vm.symKey,
privateKey: vm.privateKey
};
- }, function (newVal, oldVal) {
+ }, (newVal, oldVal) => {
if (!newVal.symKey || !newVal.symKey.key || !newVal.privateKey || !newVal.privateKey.arr) {
vm.protectedPrivateKey = new Cipher();
return;
}
aesEncrypt(newVal.privateKey.arr, newVal.symKey.encKey, newVal.symKey.macKey)
- .then(function (cipher) {
+ .then((cipher) => {
vm.protectedPrivateKey = cipher;
return aesDecrypt(vm.protectedPrivateKey, newVal.symKey.encKey, newVal.symKey.macKey);
- }).then(function (unprotectedPrivateKey) {
+ }).then((unprotectedPrivateKey) => {
vm.unprotectedPrivateKey = new ByteData(unprotectedPrivateKey);
});
});