Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions packages/security/src/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,28 @@ import { createHash } from 'node:crypto'
* content passes as a Uint8Array/Buffer. Use for indexed lookup of sensitive
* values (e.g. API key hash columns) and content-integrity receipts where the
* caller only needs to verify equality without ever reversing the hash.
*
* NOT for human-chosen passwords — those are low-entropy and need a slow KDF.
* User credentials never reach this helper: Better Auth owns them and applies
* its own KDF. What does reach it is high-entropy material where a fast digest
* is the correct construction:
*
* - API keys (`sim_`/`sk-sim-` + `generateSecureToken(24)`, 192 random bits).
* A slow KDF here would buy nothing against a keyspace that cannot be
* searched, while forcing every authenticated request through it.
* - Already-encrypted values, content digests, and cache/idempotency keys.
*
* CodeQL's `js/insufficient-password-hash` flags the sink because callers pass
* arguments it name-matches as passwords (`apiKey`, `encryptedPassword`). The
* suppressions below record that judgement; keep the invariant above true, and
* route any genuine password through Better Auth rather than this function.
*/
export function sha256Hex(input: string | Uint8Array): string {
const hash = createHash('sha256')
if (typeof input === 'string') {
hash.update(input, 'utf8')
hash.update(input, 'utf8') // lgtm[js/insufficient-password-hash]
} else {
hash.update(input)
hash.update(input) // lgtm[js/insufficient-password-hash]
}
return hash.digest('hex')
}
Expand Down
Loading