attempting to fix legacy user accounts with less than 20 characters.

This commit is contained in:
2026-05-22 15:34:23 +02:00
parent 6c6764202e
commit df312009b8
5 changed files with 28 additions and 8 deletions

View File

@@ -525,7 +525,7 @@ window.cancelAnimFrame = (function () {
const formData = new FormData(loginForm);
const params = new URLSearchParams(formData);
if (formData.get('password') && formData.get('password').length < 10) {
if (!formData.get('password')) {
let errDiv = loginForm.querySelector('.flash-error');
if (!errDiv) {
errDiv = document.createElement('div');

View File

@@ -183,10 +183,30 @@ export default new class {
return "$f0ck$" + salt + ":" + derivedKey.toString("hex");
};
async verify(str, hash) {
const [salt, key] = hash.substring(6).split(":");
const keyBuffer = Buffer.from(key, "hex");
const derivedKey = await scrypt(str, salt, 64);
return crypto.timingSafeEqual(keyBuffer, derivedKey);
if (typeof hash !== 'string') return false;
if (hash.startsWith("$f0ck$")) {
const parts = hash.substring(6).split(":");
if (parts.length !== 2) return false;
const [salt, key] = parts;
try {
const keyBuffer = Buffer.from(key, "hex");
const derivedKey = await scrypt(str, salt, 64);
return crypto.timingSafeEqual(keyBuffer, derivedKey);
} catch (e) {
return false;
}
}
if (hash.length === 32) {
return this.md5(str) === hash;
}
if (hash.length === 64) {
return this.sha256(str) === hash;
}
return false;
};
async getTags(itemid) {
const tags = await db`

View File

@@ -14,7 +14,7 @@
<div class="flash-error" style="margin-bottom: 15px;">{{ error }}</div>
@endif
<input type="text" name="username" placeholder="{{ t('auth.username_placeholder') }}" autocomplete="off" required />
<input type="password" name="password" placeholder="{{ t('auth.password_placeholder') }}" autocomplete="off" required minlength="20" />
<input type="password" name="password" placeholder="{{ t('auth.password_placeholder') }}" autocomplete="off" required />
<p><input type="checkbox" id="kmsi" name="kmsi" /> <label for="kmsi">{{ t('auth.stay_signed_in_label') }}</label></p>
<button type="submit">{{ t('auth.login_title') }}</button>
@if(smtp_enabled)

View File

@@ -195,7 +195,7 @@
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(loginForm);
if (formData.get('password') && formData.get('password').length < 20) {
if (!formData.get('password')) {
let errDiv = loginForm.querySelector('.flash-error');
if (!errDiv) { errDiv = document.createElement('div'); errDiv.className = 'flash-error'; loginForm.insertBefore(errDiv, loginForm.firstChild); }
errDiv.textContent = 'Invalid username or password.';

View File

@@ -220,7 +220,7 @@
<form class="login-form" method="post" action="/login" novalidate>
<h2 style="text-align: center; margin-bottom: 20px;">{{ t('auth.login_title') }}</h2>
<input type="text" name="username" placeholder="{{ t('auth.username_or_email') }}" autocomplete="off" required />
<input type="password" name="password" placeholder="{{ t('auth.password_placeholder_min') }}" autocomplete="off" required minlength="20" />
<input type="password" name="password" placeholder="{{ t('auth.password_placeholder_min') }}" autocomplete="off" required />
<p style="text-align: left; font-size: 0.9em; margin: 0;"><input type="checkbox" id="kmsi-modal" name="kmsi" />
<label for="kmsi-modal">{{ t('auth.stay_signed_in') }}</label>
</p>