ory/kratos · error · ErrHashParametersOutOfBounds
firescrypt ln= exceeds max
Error message
firescrypt ln=%d exceeds max %d
What it means
This error means a Firebase scrypt password hash declares a ln (log2 of N) parameter above the package ceiling of 17. The limit exists because firebase-scrypt allocates 128*N*r bytes of memory, so an attacker-controlled hash with an enormous ln could cause an OOM or multi-second CPU burn every time the comparator runs at login. It wraps ErrHashParametersOutOfBounds and is raised by validateFirebaseScryptParams when a stored or imported hash is decoded.
Solutions
- Check the ln field in the hash string (format ...|ln=NN|...) and confirm it is <= 17
- Re-hash affected users' passwords on next login instead of importing the high-cost hash directly
- If legitimate high costs are needed, lower the hash to ln<=17 (e.g. re-encode with ln=14, Firebase's strongest documented profile)
- File an issue / fork to raise maxScryptLogN if your deployment genuinely requires higher costs
Example fix
// before (hash with ln=20, rejected) $firescrypt$ln=20$r=8$p=1$... // after (re-encoded with ln=14, accepted) $firescrypt$ln=14$r=8$p=1$...
Defensive patterns
Strategy: validation
Validate before calling
// Before importing a $firescrypt hash, check its ln parameter.
func firebaseScryptLnOK(ln uint32) bool { return ln <= 17 }
// Or pre-validate the full hash without persisting it:
// if err := hash.ValidateImportedHash(hashedPassword); err != nil {
// if errors.Is(err, hash.ErrHashParametersOutOfBounds) { /* reject */ }
// } Try / catch
if _, _, _, _, _, err := hash.ValidateImportedHash(raw); errors.Is(err, hash.ErrHashParametersOutOfBounds) {
return fmt.Errorf("import rejected: %w", err)
} Prevention
- Run hash.ValidateImportedHash on every hash before persisting via the admin import API
- Keep Firebase migration profiles within ln<=14 (Firebase's strongest documented setting)
- Alert on any stored hash whose parameters approach the ceilings
- Reject user- or admin-supplied hash strings at intake rather than at login time
When it happens
Trigger: Calling ValidateImportedHash (or the admin identity import API) with a $firescrypt hash whose ln parameter exceeds 17, or comparing passwords against a stored hash with such a ln during decodeFirebaseScryptHash.
Common situations: Migrating users from Firebase Auth with hashes generated under a very high scrypt cost; hand-edited or forged hash strings; importing hashes exported from a system tuned for higher security than this package allows.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- firescrypt r= not in [1, ]
- firescrypt p= not in [1, ]
- scrypt N= not in [1, ]
- scrypt r= not in [1, ]
- scrypt p= not in [1, ]
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/6ec2c5052df6ba60.
Report an issue: GitHub.
Appendix: source
Thrown at hash/hash_limits.go:81
// up to 8-core hosts.
maxArgon2Parallelism uint8 = 16
// maxPbkdf2Iterations bounds PBKDF2 i. OWASP 2023 recommends 600k
// (SHA-256) / 210k (SHA-512). 10M ≈ 10× the strongest published
// recommendation and bounds CPU to a few seconds on modern hardware.
maxPbkdf2Iterations uint32 = 10_000_000
// maxBcryptCost bounds bcrypt cost. The format spec allows 4–31, but
// cost grows exponentially: cost 12 (Kratos, PHP, Django default) is
// ~250 ms; cost 14 (high-security guidance) is ~1 s; cost 15 (practical
// max for interactive use) is ~2 s; cost 17 is ~8 s. No mainstream
// platform defaults above cost 12.
maxBcryptCost = 15
)
func validateFirebaseScryptParams(logN, r, p uint32) error {
if logN > maxScryptLogN {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt ln=%d exceeds max %d", logN, maxScryptLogN)
}
if r == 0 || r > maxScryptR {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt r=%d not in [1, %d]", r, maxScryptR)
}
if p == 0 || p > maxScryptP {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt p=%d not in [1, %d]", p, maxScryptP)
}
return nil
}
func validateScryptParams(n, r, p uint32) error {
if n == 0 || n > maxScryptN {
return errors.Wrapf(ErrHashParametersOutOfBounds, "scrypt N=%d not in [1, %d]", n, maxScryptN)
}
if r == 0 || r > maxScryptR {
return errors.Wrapf(ErrHashParametersOutOfBounds, "scrypt r=%d not in [1, %d]", r, maxScryptR)
}
if p == 0 || p > maxScryptP {View on GitHub (pinned to b86338da04)