...
This commit is contained in:
249
www/js/index.js
249
www/js/index.js
@@ -1,5 +1,5 @@
|
||||
// Import our WebAssembly module
|
||||
import init, {
|
||||
import init, {
|
||||
create_key_space,
|
||||
encrypt_key_space,
|
||||
decrypt_key_space,
|
||||
@@ -10,6 +10,10 @@ import init, {
|
||||
keypair_pub_key,
|
||||
keypair_sign,
|
||||
keypair_verify,
|
||||
derive_public_key,
|
||||
verify_with_public_key,
|
||||
encrypt_asymmetric,
|
||||
decrypt_asymmetric,
|
||||
generate_symmetric_key,
|
||||
derive_key_from_password,
|
||||
encrypt_symmetric,
|
||||
@@ -121,6 +125,30 @@ function updateLoginUI() {
|
||||
loginStatus.className = 'status logged-out';
|
||||
currentSpaceName.textContent = '';
|
||||
}
|
||||
|
||||
// Update the spaces list
|
||||
updateSpacesList();
|
||||
}
|
||||
|
||||
// Update the spaces dropdown list
|
||||
function updateSpacesList() {
|
||||
const spacesList = document.getElementById('space-list');
|
||||
|
||||
// Clear existing options
|
||||
while (spacesList.options.length > 1) {
|
||||
spacesList.remove(1);
|
||||
}
|
||||
|
||||
// Get spaces list
|
||||
const spaces = listSpacesFromStorage();
|
||||
|
||||
// Add options for each space
|
||||
spaces.forEach(spaceName => {
|
||||
const option = document.createElement('option');
|
||||
option.value = spaceName;
|
||||
option.textContent = spaceName;
|
||||
spacesList.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
// Login to a space
|
||||
@@ -346,7 +374,36 @@ async function performSelectKeypair() {
|
||||
function displaySelectedKeypairPublicKey() {
|
||||
try {
|
||||
const pubKey = keypair_pub_key();
|
||||
document.getElementById('selected-pubkey-display').textContent = `Public Key: ${bufferToHex(pubKey)}`;
|
||||
const pubKeyHex = bufferToHex(pubKey);
|
||||
|
||||
// Create a more user-friendly display with copy button
|
||||
const pubKeyDisplay = document.getElementById('selected-pubkey-display');
|
||||
pubKeyDisplay.innerHTML = `
|
||||
<div class="pubkey-container">
|
||||
<div class="pubkey-label">Public Key (hex):</div>
|
||||
<div class="pubkey-value" id="pubkey-hex-value">${pubKeyHex}</div>
|
||||
<button id="copy-pubkey-button" class="secondary">Copy Public Key</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add event listener for the copy button
|
||||
document.getElementById('copy-pubkey-button').addEventListener('click', () => {
|
||||
const pubKeyText = document.getElementById('pubkey-hex-value').textContent;
|
||||
navigator.clipboard.writeText(pubKeyText)
|
||||
.then(() => {
|
||||
alert('Public key copied to clipboard!');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
// Also populate the public key field in the verify with public key section
|
||||
document.getElementById('pubkey-verify-pubkey').value = pubKeyHex;
|
||||
|
||||
// And in the asymmetric encryption section
|
||||
document.getElementById('asymmetric-encrypt-pubkey').value = pubKeyHex;
|
||||
|
||||
} catch (e) {
|
||||
document.getElementById('selected-pubkey-display').textContent = `Error getting public key: ${e}`;
|
||||
}
|
||||
@@ -357,7 +414,15 @@ function saveCurrentSpace() {
|
||||
if (!isLoggedIn || !currentSpace) return;
|
||||
|
||||
try {
|
||||
// Store the password in a session variable when logging in
|
||||
// and use it here to avoid issues when the password field is cleared
|
||||
const password = document.getElementById('space-password').value;
|
||||
if (!password) {
|
||||
console.error('Password not available for saving space');
|
||||
alert('Please re-enter your password to save changes');
|
||||
return;
|
||||
}
|
||||
|
||||
const encryptedSpace = encrypt_key_space(password);
|
||||
saveSpaceToStorage(currentSpace, encryptedSpace);
|
||||
} catch (e) {
|
||||
@@ -365,6 +430,26 @@ function saveCurrentSpace() {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a space from localStorage
|
||||
function deleteSpace(spaceName) {
|
||||
if (!spaceName) return false;
|
||||
|
||||
// Check if space exists
|
||||
if (!getSpaceFromStorage(spaceName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove from localStorage
|
||||
removeSpaceFromStorage(spaceName);
|
||||
|
||||
// If this was the current space, logout
|
||||
if (isLoggedIn && currentSpace === spaceName) {
|
||||
performLogout();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function run() {
|
||||
// Initialize the WebAssembly module
|
||||
await init();
|
||||
@@ -375,6 +460,32 @@ async function run() {
|
||||
document.getElementById('login-button').addEventListener('click', performLogin);
|
||||
document.getElementById('create-space-button').addEventListener('click', performCreateSpace);
|
||||
document.getElementById('logout-button').addEventListener('click', performLogout);
|
||||
document.getElementById('delete-space-button').addEventListener('click', () => {
|
||||
if (confirm(`Are you sure you want to delete the space "${currentSpace}"? This action cannot be undone.`)) {
|
||||
if (deleteSpace(currentSpace)) {
|
||||
document.getElementById('space-result').textContent = `Space "${currentSpace}" deleted successfully`;
|
||||
} else {
|
||||
document.getElementById('space-result').textContent = `Error deleting space "${currentSpace}"`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('delete-selected-space-button').addEventListener('click', () => {
|
||||
const selectedSpace = document.getElementById('space-list').value;
|
||||
if (!selectedSpace) {
|
||||
document.getElementById('space-result').textContent = 'Please select a space to delete';
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(`Are you sure you want to delete the space "${selectedSpace}"? This action cannot be undone.`)) {
|
||||
if (deleteSpace(selectedSpace)) {
|
||||
document.getElementById('space-result').textContent = `Space "${selectedSpace}" deleted successfully`;
|
||||
updateSpacesList();
|
||||
} else {
|
||||
document.getElementById('space-result').textContent = `Error deleting space "${selectedSpace}"`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the keypair management
|
||||
document.getElementById('create-keypair-button').addEventListener('click', performCreateKeypair);
|
||||
@@ -530,6 +641,140 @@ async function run() {
|
||||
document.getElementById('password-decrypt-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the public key verification example
|
||||
document.getElementById('pubkey-verify-button').addEventListener('click', () => {
|
||||
try {
|
||||
const publicKeyHex = document.getElementById('pubkey-verify-pubkey').value.trim();
|
||||
if (!publicKeyHex) {
|
||||
document.getElementById('pubkey-verify-result').textContent = 'Please enter a public key';
|
||||
return;
|
||||
}
|
||||
|
||||
const message = document.getElementById('pubkey-verify-message').value;
|
||||
const messageBytes = new TextEncoder().encode(message);
|
||||
const signatureHex = document.getElementById('pubkey-verify-signature').value;
|
||||
const signatureBytes = hexToBuffer(signatureHex);
|
||||
const publicKeyBytes = hexToBuffer(publicKeyHex);
|
||||
|
||||
try {
|
||||
const isValid = verify_with_public_key(publicKeyBytes, messageBytes, signatureBytes);
|
||||
document.getElementById('pubkey-verify-result').textContent =
|
||||
isValid ? 'Signature is valid!' : 'Signature is NOT valid!';
|
||||
} catch (e) {
|
||||
document.getElementById('pubkey-verify-result').textContent = `Error verifying: ${e}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('pubkey-verify-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the derive public key example
|
||||
document.getElementById('derive-pubkey-button').addEventListener('click', () => {
|
||||
try {
|
||||
const privateKeyHex = document.getElementById('derive-pubkey-privkey').value.trim();
|
||||
if (!privateKeyHex) {
|
||||
document.getElementById('derive-pubkey-result').textContent = 'Please enter a private key';
|
||||
return;
|
||||
}
|
||||
|
||||
const privateKeyBytes = hexToBuffer(privateKeyHex);
|
||||
|
||||
try {
|
||||
const publicKey = derive_public_key(privateKeyBytes);
|
||||
const publicKeyHex = bufferToHex(publicKey);
|
||||
|
||||
// Create a more user-friendly display with copy button
|
||||
const pubKeyDisplay = document.getElementById('derive-pubkey-result');
|
||||
pubKeyDisplay.innerHTML = `
|
||||
<div class="pubkey-container">
|
||||
<div class="pubkey-label">Derived Public Key (hex):</div>
|
||||
<div class="pubkey-value" id="derived-pubkey-hex-value">${publicKeyHex}</div>
|
||||
<button id="copy-derived-pubkey-button" class="secondary">Copy Public Key</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add event listener for the copy button
|
||||
document.getElementById('copy-derived-pubkey-button').addEventListener('click', () => {
|
||||
const pubKeyText = document.getElementById('derived-pubkey-hex-value').textContent;
|
||||
navigator.clipboard.writeText(pubKeyText)
|
||||
.then(() => {
|
||||
alert('Public key copied to clipboard!');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
// Also populate the public key field in the verify with public key section
|
||||
document.getElementById('pubkey-verify-pubkey').value = publicKeyHex;
|
||||
|
||||
// And in the asymmetric encryption section
|
||||
document.getElementById('asymmetric-encrypt-pubkey').value = publicKeyHex;
|
||||
|
||||
} catch (e) {
|
||||
document.getElementById('derive-pubkey-result').textContent = `Error deriving public key: ${e}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('derive-pubkey-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the asymmetric encryption example
|
||||
document.getElementById('asymmetric-encrypt-button').addEventListener('click', () => {
|
||||
try {
|
||||
const publicKeyHex = document.getElementById('asymmetric-encrypt-pubkey').value.trim();
|
||||
if (!publicKeyHex) {
|
||||
document.getElementById('asymmetric-encrypt-result').textContent = 'Please enter a recipient public key';
|
||||
return;
|
||||
}
|
||||
|
||||
const message = document.getElementById('asymmetric-encrypt-message').value;
|
||||
const messageBytes = new TextEncoder().encode(message);
|
||||
const publicKeyBytes = hexToBuffer(publicKeyHex);
|
||||
|
||||
try {
|
||||
const ciphertext = encrypt_asymmetric(publicKeyBytes, messageBytes);
|
||||
const ciphertextHex = bufferToHex(ciphertext);
|
||||
document.getElementById('asymmetric-encrypt-result').textContent = `Ciphertext: ${ciphertextHex}`;
|
||||
|
||||
// Store for decryption
|
||||
document.getElementById('asymmetric-decrypt-ciphertext').value = ciphertextHex;
|
||||
} catch (e) {
|
||||
document.getElementById('asymmetric-encrypt-result').textContent = `Error encrypting: ${e}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('asymmetric-encrypt-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the asymmetric decryption example
|
||||
document.getElementById('asymmetric-decrypt-button').addEventListener('click', () => {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('asymmetric-decrypt-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedKeypair) {
|
||||
document.getElementById('asymmetric-decrypt-result').textContent = 'Please select a keypair first';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const ciphertextHex = document.getElementById('asymmetric-decrypt-ciphertext').value;
|
||||
const ciphertext = hexToBuffer(ciphertextHex);
|
||||
|
||||
try {
|
||||
const plaintext = decrypt_asymmetric(ciphertext);
|
||||
const decodedText = new TextDecoder().decode(plaintext);
|
||||
document.getElementById('asymmetric-decrypt-result').textContent = `Decrypted: ${decodedText}`;
|
||||
} catch (e) {
|
||||
document.getElementById('asymmetric-decrypt-result').textContent = `Error decrypting: ${e}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('asymmetric-decrypt-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize UI
|
||||
updateLoginUI();
|
||||
|
Reference in New Issue
Block a user