187 lines
5.2 KiB
JavaScript
187 lines
5.2 KiB
JavaScript
import { postData, verifyLogin } from "./client.js";
|
|
|
|
const token = window.localStorage.getItem("token");
|
|
|
|
const infoForm = document.getElementById("infoForm");
|
|
|
|
const error = document.querySelector(".error");
|
|
const errorMessage = document.querySelector(".error p");
|
|
const success = document.querySelector(".success");
|
|
const successMessage = document.querySelector(".success p");
|
|
|
|
openKeyDB();
|
|
const encryptionKey = await getEncryptionKey()
|
|
|
|
//console.log(`Encryption Key:`);
|
|
//console.log(encryptionKey);
|
|
//
|
|
await verifyLogin();
|
|
|
|
async function handlePasswordSubmission(e) {
|
|
console.log(await verifyLogin());
|
|
e.preventDefault();
|
|
const formData = {
|
|
name: document.getElementById("name").value,
|
|
password: document.getElementById("password").value,
|
|
}
|
|
const set = document.getElementById("set").checked;
|
|
|
|
console.log(set);
|
|
|
|
if (set) {
|
|
//console.log("formdata SET so SETTING");
|
|
setPassword(formData.name, formData.password);
|
|
} else {
|
|
//console.log("formdata GET so GETTING");
|
|
getPassword(formData.name);
|
|
}
|
|
}
|
|
|
|
infoForm.onsubmit = handlePasswordSubmission;
|
|
|
|
async function setPassword(name, password) {
|
|
const encoder = new TextEncoder();
|
|
const encodedData = encoder.encode(password);
|
|
|
|
const iv = window.crypto.getRandomValues(new Uint8Array(12));
|
|
|
|
const cyphertextBuffer = await window.crypto.subtle.encrypt(
|
|
{
|
|
name: "AES-GCM",
|
|
iv: iv
|
|
},
|
|
encryptionKey,
|
|
encodedData
|
|
);
|
|
|
|
const data = {
|
|
name: name,
|
|
iv: bufferToBase64(iv),
|
|
password: bufferToBase64(cyphertextBuffer)
|
|
}
|
|
|
|
var resultObject = await postData("/setPassword", data, token);
|
|
|
|
if (resultObject.message.includes("UNIQUE")) {
|
|
resultObject = await postData("/updatePassword", data, token);
|
|
}
|
|
|
|
if (resultObject.success) {
|
|
error.style.display = "none";
|
|
success.style.display = "flex";
|
|
successMessage.innerHTML = `Password for "${name}" successfully set to "${password}"`
|
|
} else {
|
|
errorMessage.innerHTML = resultObject.message;
|
|
success.style.display = "none";
|
|
error.style.display = "flex";
|
|
}
|
|
}
|
|
|
|
async function getPassword(name) {
|
|
const data = {
|
|
name: name
|
|
}
|
|
const resultObject = await postData("/getPassword", data, token);
|
|
|
|
if (resultObject.success) {
|
|
error.style.display = "none";
|
|
success.style.display = "flex";
|
|
} else {
|
|
errorMessage.innerHTML = resultObject.message;
|
|
success.style.display = "none";
|
|
error.style.display = "flex";
|
|
return;
|
|
}
|
|
|
|
const ivBuffer = base64ToBuffer(resultObject.iv);
|
|
const cyphertextBuffer = base64ToBuffer(resultObject.password);
|
|
|
|
const decryptedBuffer = await window.crypto.subtle.decrypt(
|
|
{
|
|
name: "AES-GCM",
|
|
iv: ivBuffer
|
|
},
|
|
encryptionKey,
|
|
cyphertextBuffer
|
|
);
|
|
|
|
const decoder = new TextDecoder();
|
|
const pw = decoder.decode(decryptedBuffer);
|
|
document.getElementById("password").value = pw;
|
|
//console.log("Password: " + pw);
|
|
|
|
//console.log(resultObject);
|
|
|
|
successMessage.innerHTML = `Password for "${name}" is "${pw}"`
|
|
}
|
|
|
|
|
|
|
|
|
|
function openKeyDB() {
|
|
return new Promise((resolve, reject) => {
|
|
const request = indexedDB.open("PasswordManagerVault", 1);
|
|
|
|
request.onupgradeneeded = (event) => {
|
|
const db = event.target.result;
|
|
if (!db.objectStoreNames.contains("cryptoKeys")) {
|
|
db.createObjectStore("cryptoKeys");
|
|
}
|
|
};
|
|
|
|
request.onsuccess = () => resolve(request.result);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
async function saveEncryptionKey(cryptoKeyObject) {
|
|
const db = await openKeyDB();
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(["cryptoKeys"], "readwrite");
|
|
const store = transaction.objectStore("cryptoKeys");
|
|
|
|
// We store the object under the label "masterEncryptionKey"
|
|
const request = store.put(cryptoKeyObject, "masterEncryptionKey");
|
|
|
|
request.onsuccess = () => resolve(true);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
async function getEncryptionKey() {
|
|
const db = await openKeyDB();
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(["cryptoKeys"], "readonly");
|
|
const store = transaction.objectStore("cryptoKeys");
|
|
|
|
const request = store.get("masterEncryptionKey");
|
|
|
|
request.onsuccess = () => {
|
|
if (request.result) {
|
|
resolve(request.result);
|
|
} else {
|
|
resolve(null);
|
|
}
|
|
};
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
function bufferToBase64(buffer) {
|
|
const bytes = new Uint8Array(buffer);
|
|
let binary = '';
|
|
for (let i = 0; i < bytes.byteLength; i++) {
|
|
binary += String.fromCharCode(bytes[i]);
|
|
}
|
|
return window.btoa(binary);
|
|
}
|
|
|
|
function base64ToBuffer(base64) {
|
|
const binaryString = window.atob(base64);
|
|
const bytes = new Uint8Array(binaryString.length);
|
|
for (let i = 0; i < binaryString.length; i++) {
|
|
bytes[i] = binaryString.charCodeAt(i);
|
|
}
|
|
return bytes;
|
|
}
|