style(auth): satisfy Biome in password digest helpers
CI / check (push) Successful in 4m17s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m0s

Unescape dollar signs inside character classes and use template literals
instead of string concatenation in the salted digest tests.
This commit is contained in:
openhands committed 2026-09-18 12:44:44 +02:00
1 parent d131124515
commit 4acafcfef6
2 files changed
+11 -11

No files matched your search

+8 -8
View File
@@ -169,36 +169,36 @@ describe("isCombinedDigestOf", () => {
describe("isSaltedDigestOf", () => {
it("verifies md5(salt+password) with hash:salt layout", async () => {
const salt = "pepper123";
const stored = `${await md5Hex(salt + "oldpass")}:${salt}`;
const stored = `${await md5Hex(`${salt}oldpass`)}:${salt}`;
expect(await isSaltedDigestOf("oldpass", stored)).toBe(true);
expect(await isSaltedDigestOf("wrong", stored)).toBe(false);
});
it("verifies md5(password+salt) with hash:salt layout", async () => {
const salt = "pepper123";
const stored = `${await md5Hex("oldpass" + salt)}:${salt}`;
const stored = `${await md5Hex(`oldpass${salt}`)}:${salt}`;
expect(await isSaltedDigestOf("oldpass", stored)).toBe(true);
});
it("verifies the salt:hash layout", async () => {
const salt = "abc123";
const stored = `${salt}:${await md5Hex(salt + "oldpass")}`;
const stored = `${salt}:${await md5Hex(`${salt}oldpass`)}`;
expect(await isSaltedDigestOf("oldpass", stored)).toBe(true);
expect(await isSaltedDigestOf("wrong", stored)).toBe(false);
});
it("verifies the hash$salt layout", async () => {
const salt = "s0lt_9";
const stored = `${await md5Hex("oldpass" + salt)}$s0lt_9`;
const stored = `${await md5Hex(`oldpass${salt}`)}$s0lt_9`;
expect(await isSaltedDigestOf("oldpass", stored)).toBe(true);
});
it("verifies salted sha1 and sha256 digests", async () => {
const salt = "pepper123";
const sha1Stored = `${await sha1Hex(salt + "oldpass")}:${salt}`;
const sha1Stored = `${await sha1Hex(`${salt}oldpass`)}:${salt}`;
expect(await isSaltedDigestOf("oldpass", sha1Stored)).toBe(true);
const sha256Stored = `${await sha256Hex("oldpass" + salt)}:${salt}`;
const sha256Stored = `${await sha256Hex(`oldpass${salt}`)}:${salt}`;
expect(await isSaltedDigestOf("oldpass", sha256Stored)).toBe(true);
});
@@ -268,7 +268,7 @@ describe("checkLogin", () => {
it("migrates a salted md5 hash to bcrypt (md5(salt+password))", async () => {
const salt = "pepper123";
const stored = `${await md5Hex(salt + "oldpass")}:${salt}`;
const stored = `${await md5Hex(`${salt}oldpass`)}:${salt}`;
const res = await checkLogin("oldpass", stored);
expect(res.valid).toBe(true);
expect(res.upgradedHash).toMatch(/^\$2[aby]\$/);
@@ -279,7 +279,7 @@ describe("checkLogin", () => {
it("migrates a salted sha256 hash to bcrypt (sha256(salt+password))", async () => {
const salt = "abc123";
const stored = `${salt}:${await sha256Hex(salt + "oldpass")}`;
const stored = `${salt}:${await sha256Hex(`${salt}oldpass`)}`;
const res = await checkLogin("oldpass", stored);
expect(res.valid).toBe(true);
expect(res.upgradedHash).toMatch(/^\$2[aby]\$/);
+3 -3
View File
@@ -130,7 +130,7 @@ export async function isCombinedDigestOf(
* sha256, sha512) is tried, and both md5(salt+password) and md5(password+salt)
* orderings are verified to cover both conventions.
*/
const SALTED_HASH_DELIMITER_RE = /[:\$@_]/;
const SALTED_HASH_DELIMITER_RE = /[:$@_]/;
export async function isSaltedDigestOf(
password: string,
@@ -140,10 +140,10 @@ export async function isSaltedDigestOf(
for (const { length, hash: hashFn } of DIGEST_SCHEMES) {
const hashFirst = stored.match(
new RegExp(`^([a-f0-9]{${length}})[:\$@_](.{1,64})$`, "i"),
new RegExp(`^([a-f0-9]{${length}})[:$@_](.{1,64})$`, "i"),
);
const saltFirst = stored.match(
new RegExp(`^(.{1,64})[:\$@_]([a-f0-9]{${length}})$`, "i"),
new RegExp(`^(.{1,64})[:$@_]([a-f0-9]{${length}})$`, "i"),
);
const hashHex = hashFirst?.[1] ?? saltFirst?.[2];
const salt = hashFirst?.[2] ?? saltFirst?.[1];