{"record":{"id":"3b4453e9331485f3","repo":"ory/kratos","slug":"firescrypt-p-d-not-in-1-d","errorCode":null,"errorMessage":"firescrypt p=%d not in [1, %d]","messagePattern":"firescrypt p=(.+?) not in \\[1, (.+?)\\]","errorType":"validation","errorClass":"ErrHashParametersOutOfBounds","httpStatus":null,"severity":"error","filePath":"hash/hash_limits.go","lineNumber":87,"sourceCode":"\tmaxPbkdf2Iterations uint32 = 10_000_000\n\n\t// maxBcryptCost bounds bcrypt cost. The format spec allows 4–31, but\n\t// cost grows exponentially: cost 12 (Kratos, PHP, Django default) is\n\t// ~250 ms; cost 14 (high-security guidance) is ~1 s; cost 15 (practical\n\t// max for interactive use) is ~2 s; cost 17 is ~8 s. No mainstream\n\t// platform defaults above cost 12.\n\tmaxBcryptCost = 15\n)\n\nfunc validateFirebaseScryptParams(logN, r, p uint32) error {\n\tif logN > maxScryptLogN {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"firescrypt ln=%d exceeds max %d\", logN, maxScryptLogN)\n\t}\n\tif r == 0 || r > maxScryptR {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"firescrypt r=%d not in [1, %d]\", r, maxScryptR)\n\t}\n\tif p == 0 || p > maxScryptP {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"firescrypt p=%d not in [1, %d]\", p, maxScryptP)\n\t}\n\treturn nil\n}\n\nfunc validateScryptParams(n, r, p uint32) error {\n\tif n == 0 || n > maxScryptN {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"scrypt N=%d not in [1, %d]\", n, maxScryptN)\n\t}\n\tif r == 0 || r > maxScryptR {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"scrypt r=%d not in [1, %d]\", r, maxScryptR)\n\t}\n\tif p == 0 || p > maxScryptP {\n\t\treturn errors.Wrapf(ErrHashParametersOutOfBounds, \"scrypt p=%d not in [1, %d]\", p, maxScryptP)\n\t}\n\treturn nil\n}\n\nfunc validateArgon2Params(memoryKiB uint64, iterations uint32, parallelism uint8) error {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/hash/hash_limits.go#L69-L105","documentation":"This error means a Firebase scrypt hash declares a p (parallelization) parameter outside the valid range [1, 10]. p=0 is invalid because it would make the hash do no work; large p multiplies CPU cost linearly (Go runs the p iterations serially), enabling CPU-exhaustion attacks via crafted hashes. It wraps ErrHashParametersOutOfBounds from validateFirebaseScryptParams.","triggerScenarios":"decodeFirebaseScryptHash parses a $firescrypt hash with p=0 or p>10, reached via ValidateImportedHash on admin import or during a password comparison of a stored hash.","commonSituations":"Importing hashes generated with unusually high parallelization; forged or malformed hash strings; copying parameter values from plain scrypt configs where p can legitimately be much larger.","solutions":["Check the p field in the hash string and set it within [1, 10] (Firebase uses p=1)","Re-export or regenerate the hash with standard parameters (ln<=17, r=8, p=1)","If the source account genuinely used p>10, plan a forced password reset / rehash-on-login instead of importing"],"exampleFix":"// before (p=32, rejected)\n$firescrypt$ln=14$r=8$p=32$...\n// after (p=1, accepted)\n$firescrypt$ln=14$r=8$p=1$...","handlingStrategy":"validation","validationCode":"func firebaseScryptPOK(p uint32) bool { return p >= 1 && p <= 10 }\n// Or pre-validate the whole hash: hash.ValidateImportedHash(hashed)","typeGuard":null,"tryCatchPattern":"if err := hash.ValidateImportedHash(raw); errors.Is(err, hash.ErrHashParametersOutOfBounds) {\n    return fmt.Errorf(\"invalid firescrypt p: %w\", err)\n}","preventionTips":["Use p=1 for all Firebase scrypt hashes (Firebase's standard)","Check errors.Is(err, hash.ErrHashParametersOutOfBounds) to distinguish parameter errors from format errors","Validate imported hashes before persisting"],"tags":["hashing","scrypt","firebase"],"backgroundTag":"value-out-of-range","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}