Browse Source

async/await

pull/66/head
Kyle Spearrin 6 years ago
parent
commit
666ac29295
  1. 242
      crypto.html

242
crypto.html

@ -235,7 +235,7 @@
// Crypto // Crypto
function pbkdf2(password, salt, iterations, length) { async function pbkdf2(password, salt, iterations, length) {
const importAlg = { const importAlg = {
name: 'PBKDF2' name: 'PBKDF2'
}; };
@ -252,19 +252,19 @@
length: length length: length
}; };
return window.crypto.subtle.importKey('raw', password, importAlg, false, ['deriveKey']) try {
.then((importedKey) => { const importedKey = await window.crypto.subtle.importKey(
return window.crypto.subtle.deriveKey(deriveAlg, importedKey, aesOptions, true, ['encrypt']); 'raw', password, importAlg, false, ['deriveKey']);
}).then((derivedKey) => { const derivedKey = await window.crypto.subtle.deriveKey(
return window.crypto.subtle.exportKey('raw', derivedKey); deriveAlg, importedKey, aesOptions, true, ['encrypt']);
}).then((exportedKey) => { const exportedKey = await window.crypto.subtle.exportKey('raw', derivedKey);
return new ByteData(exportedKey); return new ByteData(exportedKey);
}).catch((err) => { } catch (err) {
console.error(err); console.log(err);
}); }
} }
function aesEncrypt(data, encKey, macKey) { async function aesEncrypt(data, encKey, macKey) {
const keyOptions = { const keyOptions = {
name: 'AES-CBC' name: 'AES-CBC'
}; };
@ -276,30 +276,26 @@
window.crypto.getRandomValues(encOptions.iv); window.crypto.getRandomValues(encOptions.iv);
const ivData = new ByteData(encOptions.iv.buffer); const ivData = new ByteData(encOptions.iv.buffer);
let ctData, macData; try {
return window.crypto.subtle.importKey('raw', encKey.arr.buffer, keyOptions, false, ['encrypt']) const importedKey = await window.crypto.subtle.importKey(
.then((importedKey) => { 'raw', encKey.arr.buffer, keyOptions, false, ['encrypt']);
return window.crypto.subtle.encrypt(encOptions, importedKey, data); const encryptedBuffer = await window.crypto.subtle.encrypt(encOptions, importedKey, data);
}).then((encryptedBuffer) => { const ctData = new ByteData(encryptedBuffer);
ctData = new ByteData(encryptedBuffer); let type = encTypes.AesCbc256_B64;
if (!macKey) { let macData;
return null; if (macKey) {
}
const dataForMac = buildDataForMac(ivData.arr, ctData.arr); const dataForMac = buildDataForMac(ivData.arr, ctData.arr);
return computeMac(dataForMac.buffer, macKey.arr.buffer); const macBuffer = await computeMac(dataForMac.buffer, macKey.arr.buffer);
}).then((macBuffer) => { type = encTypes.AesCbc256_HmacSha256_B64;
let type = encTypes.AesCbc256_B64; macData = new ByteData(macBuffer);
if (macBuffer) { }
type = encTypes.AesCbc256_HmacSha256_B64; return new Cipher(type, ivData, ctData, macData);
macData = new ByteData(macBuffer); } catch (err) {
} console.error(err);
return new Cipher(type, ivData, ctData, macData); }
}).catch((err) => {
console.error(err);
});
} }
function aesDecrypt(cipher, encKey, macKey) { async function aesDecrypt(cipher, encKey, macKey) {
const keyOptions = { const keyOptions = {
name: 'AES-CBC' name: 'AES-CBC'
}; };
@ -309,84 +305,60 @@
iv: cipher.iv.arr.buffer iv: cipher.iv.arr.buffer
}; };
const checkMacPromise = new Promise((resolve) => { try {
if (cipher.encType == encTypes.AesCbc256_B64) { const checkMac = cipher.encType != encTypes.AesCbc256_B64;
resolve(false); if (checkMac) {
return; if (!macKey) {
} throw 'MAC key not provided.';
if (!macKey) {
throw 'MAC key not provided.';
}
resolve(true);
});
return checkMacPromise
.then((checkMac) => {
if (!checkMac) {
return null;
} }
const dataForMac = buildDataForMac(cipher.iv.arr, cipher.ct.arr); const dataForMac = buildDataForMac(cipher.iv.arr, cipher.ct.arr);
return computeMac(dataForMac.buffer, macKey.arr.buffer) const macBuffer = await computeMac(dataForMac.buffer, macKey.arr.buffer);
}) const macsMatch = await macsEqual(cipher.mac.arr.buffer, macBuffer, macKey.arr.buffer);
.then((macBuffer) => { if (!macsMatch) {
if (!macBuffer) {
return true;
}
return macsEqual(cipher.mac.arr.buffer, macBuffer, macKey.arr.buffer);
}).then((macsMatch) => {
if (macsMatch === false) {
throw 'MAC check failed.'; throw 'MAC check failed.';
} }
return window.crypto.subtle.importKey('raw', encKey.arr.buffer, keyOptions, false, ['decrypt']); const importedKey = await window.crypto.subtle.importKey(
}).then((importedKey) => { 'raw', encKey.arr.buffer, keyOptions, false, ['decrypt']);
return window.crypto.subtle.decrypt(decOptions, importedKey, cipher.ct.arr.buffer); return window.crypto.subtle.decrypt(decOptions, importedKey, cipher.ct.arr.buffer);
}).catch((err) => { }
console.error(err); } catch (err) {
}); console.error(err);
}
} }
function computeMac(data, key) { async function computeMac(data, key) {
const alg = { const alg = {
name: 'HMAC', name: 'HMAC',
hash: { name: 'SHA-256' } hash: { name: 'SHA-256' }
}; };
const importedKey = await window.crypto.subtle.importKey('raw', key, alg, false, ['sign']);
return window.crypto.subtle.importKey('raw', key, alg, false, ['sign']) return window.crypto.subtle.sign(alg, importedKey, data);
.then((importedKey) => {
return window.crypto.subtle.sign(alg, importedKey, data);
});
} }
function macsEqual(mac1Data, mac2Data, key) { async function macsEqual(mac1Data, mac2Data, key) {
const alg = { const alg = {
name: 'HMAC', name: 'HMAC',
hash: { name: 'SHA-256' } hash: { name: 'SHA-256' }
}; };
let mac1, importedMacKey; const importedMacKey = await window.crypto.subtle.importKey('raw', key, alg, false, ['sign']);
return window.crypto.subtle.importKey('raw', key, alg, false, ['sign']) const mac1 = await window.crypto.subtle.sign(alg, importedMacKey, mac1Data);
.then((importedKey) => { const mac2 = await window.crypto.subtle.sign(alg, importedMacKey, mac2Data);
importedMacKey = importedKey;
return window.crypto.subtle.sign(alg, importedMacKey, mac1Data);
}).then((mac) => {
mac1 = mac;
return window.crypto.subtle.sign(alg, importedMacKey, mac2Data);
}).then((mac2) => {
if (mac1.byteLength !== mac2.byteLength) {
return false;
}
const arr1 = new Uint8Array(mac1); if (mac1.byteLength !== mac2.byteLength) {
const arr2 = new Uint8Array(mac2); return false;
}
for (let i = 0; i < arr2.length; i++) { const arr1 = new Uint8Array(mac1);
if (arr1[i] !== arr2[i]) { const arr2 = new Uint8Array(mac2);
return false;
}
}
return true; for (let i = 0; i < arr2.length; i++) {
}); if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
} }
function buildDataForMac(ivArr, ctArr) { function buildDataForMac(ivArr, ctArr) {
@ -396,7 +368,7 @@
return dataForMac; return dataForMac;
} }
function generateRsaKeypair() { async function generateRsaKeypair() {
const rsaOptions = { const rsaOptions = {
name: 'RSA-OAEP', name: 'RSA-OAEP',
modulusLength: 2048, modulusLength: 2048,
@ -404,22 +376,17 @@
hash: { name: 'SHA-1' } hash: { name: 'SHA-1' }
}; };
let keypair, publicKey; try {
return window.crypto.subtle.generateKey(rsaOptions, true, ['encrypt', 'decrypt']) const keyPair = await window.crypto.subtle.generateKey(rsaOptions, true, ['encrypt', 'decrypt']);
.then((generatedKey) => { const publicKey = new ByteData(await window.crypto.subtle.exportKey('spki', keyPair.publicKey));
keypair = generatedKey; const privateKey = new ByteData(await window.crypto.subtle.exportKey('pkcs8', keyPair.privateKey));
return window.crypto.subtle.exportKey('spki', keypair.publicKey); return {
}).then((exportedKey) => { publicKey: publicKey,
publicKey = new ByteData(exportedKey); privateKey: privateKey
return window.crypto.subtle.exportKey('pkcs8', keypair.privateKey); };
}).then((exportedKey) => { } catch (err) {
return { console.error(err);
publicKey: publicKey, }
privateKey: new ByteData(exportedKey)
};
}).catch((err) => {
console.error(err);
});
} }
async function stretchKey(key) { async function stretchKey(key) {
@ -488,31 +455,27 @@
} }
}, },
watch: { watch: {
masterKey(newValue) { async masterKey(newValue) {
const self = this; const self = this;
if (!newValue || !newValue.arr || !self.masterPasswordBuffer) { if (!newValue || !newValue.arr || !self.masterPasswordBuffer) {
return new ByteData(); return new ByteData();
} }
pbkdf2(newValue.arr.buffer, self.masterPasswordBuffer, 1, 256) self.masterKeyHash = await pbkdf2(newValue.arr.buffer, self.masterPasswordBuffer, 1, 256);
.then((masterKeyHash) => {
self.masterKeyHash = masterKeyHash;
});
} }
}, },
methods: { methods: {
generateKeys() { async generateKeys() {
const self = this; const self = this;
const symKey = new Uint8Array(512 / 8); const symKey = new Uint8Array(512 / 8);
window.crypto.getRandomValues(symKey); window.crypto.getRandomValues(symKey);
self.symKey = new SymmetricCryptoKey(symKey); self.symKey = new SymmetricCryptoKey(symKey);
generateRsaKeypair().then((keypair) => { const keyPair = await generateRsaKeypair();
self.publicKey = keypair.publicKey; self.publicKey = keyPair.publicKey;
self.privateKey = keypair.privateKey; self.privateKey = keyPair.privateKey;
});
} }
} }
}); });
@ -523,16 +486,13 @@
email: vm.emailBuffer, email: vm.emailBuffer,
iterations: vm.pbkdf2Iterations iterations: vm.pbkdf2Iterations
}; };
}, (newVal, oldVal) => { }, async (newVal, oldVal) => {
if (!newVal.masterPassword || !newVal.email || !newVal.iterations || newVal.iterations < 1) { if (!newVal.masterPassword || !newVal.email || !newVal.iterations || newVal.iterations < 1) {
vm.masterKey = new ByteData(); vm.masterKey = new ByteData();
return; return;
} }
pbkdf2(newVal.masterPassword, newVal.email, newVal.iterations, 256) vm.masterKey = await pbkdf2(newVal.masterPassword, newVal.email, newVal.iterations, 256);
.then((masterKey) => {
vm.masterKey = masterKey;
});
}); });
vm.$watch(() => { vm.$watch(() => {
@ -540,20 +500,16 @@
symKey: vm.symKey, symKey: vm.symKey,
secret: vm.secretBuffer secret: vm.secretBuffer
}; };
}, (newVal, oldVal) => { }, async (newVal, oldVal) => {
if (!newVal.symKey || !newVal.secret) { if (!newVal.symKey || !newVal.secret) {
vm.protectedSecret = new Cipher(); vm.protectedSecret = new Cipher();
vm.unprotectedSecret = ''; vm.unprotectedSecret = '';
return; return;
} }
aesEncrypt(newVal.secret, newVal.symKey.encKey, newVal.symKey.macKey) vm.protectedSecret = await aesEncrypt(newVal.secret, newVal.symKey.encKey, newVal.symKey.macKey);
.then((cipher) => { const secret = await aesDecrypt(vm.protectedSecret, newVal.symKey.encKey, newVal.symKey.macKey);
vm.protectedSecret = cipher; vm.unprotectedSecret = toUtf8(secret);
return aesDecrypt(vm.protectedSecret, newVal.symKey.encKey, newVal.symKey.macKey);
}).then((secret) => {
vm.unprotectedSecret = toUtf8(secret);
});
}); });
vm.$watch(() => { vm.$watch(() => {
@ -561,19 +517,15 @@
masterKey: vm.masterKey, masterKey: vm.masterKey,
symKey: vm.symKey symKey: vm.symKey
}; };
}, (newVal, oldVal) => { }, async (newVal, oldVal) => {
if (!newVal.masterKey || !newVal.masterKey.arr || !newVal.symKey || !newVal.symKey.key) { if (!newVal.masterKey || !newVal.masterKey.arr || !newVal.symKey || !newVal.symKey.key) {
vm.protectedSymKey = new Cipher(); vm.protectedSymKey = new Cipher();
return; return;
} }
aesEncrypt(newVal.symKey.key.arr, newVal.masterKey, null) vm.protectedSymKey = await aesEncrypt(newVal.symKey.key.arr, newVal.masterKey, null);
.then((cipher) => { const unprotectedSymKey = await aesDecrypt(vm.protectedSymKey, newVal.masterKey, null);
vm.protectedSymKey = cipher; vm.unprotectedSymKey = new ByteData(unprotectedSymKey);
return aesDecrypt(vm.protectedSymKey, newVal.masterKey, null);
}).then((unprotectedSymKey) => {
vm.unprotectedSymKey = new ByteData(unprotectedSymKey);
});
}); });
vm.$watch(() => { vm.$watch(() => {
@ -581,19 +533,17 @@
symKey: vm.symKey, symKey: vm.symKey,
privateKey: vm.privateKey privateKey: vm.privateKey
}; };
}, (newVal, oldVal) => { }, async (newVal, oldVal) => {
if (!newVal.symKey || !newVal.symKey.key || !newVal.privateKey || !newVal.privateKey.arr) { if (!newVal.symKey || !newVal.symKey.key || !newVal.privateKey || !newVal.privateKey.arr) {
vm.protectedPrivateKey = new Cipher(); vm.protectedPrivateKey = new Cipher();
return; return;
} }
aesEncrypt(newVal.privateKey.arr, newVal.symKey.encKey, newVal.symKey.macKey) vm.protectedPrivateKey = await aesEncrypt(newVal.privateKey.arr, newVal.symKey.encKey,
.then((cipher) => { newVal.symKey.macKey);
vm.protectedPrivateKey = cipher; const unprotectedPrivateKey = await aesDecrypt(vm.protectedPrivateKey, newVal.symKey.encKey,
return aesDecrypt(vm.protectedPrivateKey, newVal.symKey.encKey, newVal.symKey.macKey); newVal.symKey.macKey);
}).then((unprotectedPrivateKey) => { vm.unprotectedPrivateKey = new ByteData(unprotectedPrivateKey);
vm.unprotectedPrivateKey = new ByteData(unprotectedPrivateKey);
});
}); });
// Set default values // Set default values

Loading…
Cancel
Save