const gensaltBtn = document.getElementById('gensaltBtn'); const algorithm = document.getElementById('algorithm'); const password = document.getElementById('password'); const salt = document.getElementById('salt'); const hashBtn = document.getElementById('hashBtn'); const result = document.getElementById('result'); const clearBtn = document.getElementById('clearBtn'); const resultBtn = document.getElementById('resultBtn'); const username = document.getElementById('username'); const MIN_PASS_LEN = 16; const MIN_SALT_LEN = 8; const MAX_SALT_LEN = 16; gensaltBtn.addEventListener('click', async () => { const len = MAX_SALT_LEN; // can be adjusted or user-defined const res = await fetch('/gensalt?length=' + len); if (!res.ok) { alert('Could not generate salt'); return; } const data = await res.json(); salt.value = data.salt; }); const updateUI = () => { const isCopyparty = algorithm.value === 'argon2_copyparty'; salt.disabled = isCopyparty; gensaltBtn.disabled = isCopyparty; username.disabled = !isCopyparty; if (isCopyparty) { salt.value = "LVZ1TJMdAIdLyBla6nWDexFt"; salt.style.opacity = "0.5"; } else { salt.value = ""; salt.style.opacity = ""; username.value = ""; } }; algorithm.addEventListener('change', updateUI); window.addEventListener('DOMContentLoaded', updateUI); hashBtn.addEventListener('click', async () => { const pass = password.value || ''; const s = salt.value || ''; const alg = algorithm.value; const usr = username.value || ''; if (pass.length < MIN_PASS_LEN) { alert('Password must be at least ' + MIN_PASS_LEN + ' characters'); return; } if (alg !== 'argon2_copyparty') { if (s.length < MIN_SALT_LEN || s.length > MAX_SALT_LEN) { alert('Salt must be between ' + MIN_SALT_LEN + ' and ' + MAX_SALT_LEN + ' characters'); return; } } if (alg == 'argon2_copyparty') { if (usr === '') { alert('Please type your username.'); return; } } const payload = { username: usr, password: pass, salt: s, algorithm: alg }; const res = await fetch('/hash', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!res.ok) { const txt = await res.text(); alert('Error: ' + txt); return; } const data = await res.json(); result.textContent = data.hash; }); clearBtn.addEventListener('click', () => { password.value = ''; salt.value = ''; result.textContent = 'Result will appear here'; }); resultBtn.addEventListener('click', async () => { if (!result.textContent || result.textContent === 'Result will appear here') { alert('Nothing to copy.'); } try { await navigator.clipboard.writeText(result.textContent); alert('Copied to clipboard.'); } catch (err) { alert('Failed to copy: ' + err); } });