SlintORM
Docsnpm

@hash — Balloon & PBKDF2 Hashing

One-way hashes a string field before writing to the database. Defaults to Balloon Hashing (memory-hard, SHA-256 based) since v1.9.5. Falls back to PBKDF2 with :(algo=pbkdf2). Exposes a .verify(plaintext) method for constant-time comparison on read.

Syntax

src/interfaces.ts
// Balloon Hashing (default — memory-hard, SHA-256)
// space=65536 (2MB), time=3, delta=3
// @hash
password?: string;

// Explicit Balloon with custom params
// @hash:(algo=balloon,space=4096,time=2,delta=2)

// PBKDF2 opt-in (backward compat)
// @hash:(algo=pbkdf2,iterations=600000)
pinHash?: string;

Stored Format

(database column value)
// Balloon (default since v1.9.5):
balloon$<space>$<time>$<delta>$<salt>$<hash>
// Example:
balloon$65536$3$3$Ys0HFPkNgc1aGRp6Y8reug==$uWLzg3CQ...

// PBKDF2 (opt-in):
pbkdf2$<iterations>$<salt>$<hash>
// Example:
pbkdf2$600000$Ys0HFPkNgc1aGRp6Y8reug==$uWLzg3CQtcDZ37JGoVGyor8Qg7yh9BU9sM2jTdilCN0=

Usage

src/auth.ts
// Insert — auto-hashed (Balloon) before write
const user = await User.insert({
  email: "alice@example.com",
  password: "correct-horse-battery-staple",
});
// DB stores: balloon$65536$3$3$... (never the plaintext)

// Fetch — .verify() attached to the field
const fetched = await User.get({ email: "alice@example.com" });
const match = await fetched.password.verify("correct-horse-battery-staple");
// true

const wrong = await fetched.password.verify("wrong-password");
// false

Gotcha: .verify() returns a wrapper object

src/auth.ts
const user = await User.get({ id: 1 });

typeof user.password;               // "string" at runtime (object coercion)
user.password === "balloon$...";    // true — comparison works via valueOf()
user.password.verify("secret");     // ✅ works

// BUT direct === against a plain string literal fails:
if (user.password === "balloon$...") {} // false — different object identity
// Use .verify() instead, or compare via toString()

Errors

ErrorCauseFix
Expected 'balloon$...' or 'pbkdf2$...' format, got '...'Stored value doesn't start with recognized prefixVerify the column contains a properly hashed value
Expected 'pbkdf2$iterations$salt$hash' (new) or 'pbkdf2$salt$hash' (legacy), got N partsMalformed PBKDF2 stored hashRe-hash the field by writing to it again

Conventions

See also