aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/register.ts2
-rw-r--r--routes/users.ts19
2 files changed, 18 insertions, 3 deletions
diff --git a/lib/register.ts b/lib/register.ts
index bd1049c8..16aa5b02 100644
--- a/lib/register.ts
+++ b/lib/register.ts
@@ -32,7 +32,7 @@ export default async (user, ip) => {
if (password) {
user.password = await Bun.password.hash(password, {
algorithm: "bcrypt",
- cost: 4,
+ cost: 12,
});
}
diff --git a/routes/users.ts b/routes/users.ts
index f10b728b..63699777 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -350,7 +350,7 @@ export default {
if (password && password === confirm) {
user.password = await Bun.password.hash(password, {
algorithm: "bcrypt",
- cost: 4,
+ cost: 12,
});
}
@@ -427,6 +427,21 @@ export default {
if ((await db.ttl(ipFailKey)) < 0) await db.expire(ipFailKey, 600);
return res.code(401).send("2fa required");
}
+
+ // Transparent bcrypt upgrade: legacy accounts were hashed at cost 4
+ // (~1,300 guesses/s). Now that we hold the verified plaintext, re-hash
+ // at the current cost so the stored hash strengthens on next login.
+ const cost = Number.parseInt(
+ user.password.match(/^\$2[aby]\$(\d{2})\$/)?.[1] ?? "0",
+ 10,
+ );
+ if (cost < 12) {
+ user.password = await Bun.password.hash(password, {
+ algorithm: "bcrypt",
+ cost: 12,
+ });
+ await s(`user:${user.id}`, user);
+ }
}
if (username !== "coinos")
@@ -787,7 +802,7 @@ export default {
user.password = await Bun.password.hash(password, {
algorithm: "bcrypt",
- cost: 4,
+ cost: 12,
});
await s(`user:${id}`, user);