{"record":{"id":"04bf3eb2f79426fe","repo":"alibaba/spring-ai-alibaba","slug":"invalid-encoded-argon2-hash","errorCode":null,"errorMessage":"Invalid encoded Argon2-hash","messagePattern":"Invalid encoded Argon2-hash","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/utils/security/PasswordCryptUtils.java","lineNumber":94,"sourceCode":"\t\t\t.append(params.getLanes())\n\t\t\t.append(\"$\")\n\t\t\t.append(b64encoder.encodeToString(salt))\n\t\t\t.append(\"$\")\n\t\t\t.append(b64encoder.encodeToString(hash));\n\t\treturn stringBuilder.toString();\n\t}\n\n\t/**\n\t * Verifies if a password matches the encoded password.\n\t * @param password The password to verify\n\t * @param encodedPassword The encoded password to check against\n\t * @return true if the password matches, false otherwise\n\t * @throws IllegalArgumentException if the encoded password format is invalid\n\t */\n\tpublic static boolean match(String password, String encodedPassword) {\n\t\tString[] parts = encodedPassword.split(\"\\\\$\");\n\t\tif (parts.length < 4) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid encoded Argon2-hash\");\n\t\t}\n\n\t\tArgon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id);\n\n\t\tif (parts[2].startsWith(\"$v=\")) {\n\t\t\tint version = Integer.parseInt(parts[0].substring(2));\n\t\t\tbuilder.withVersion(version);\n\t\t}\n\n\t\tString[] perfParams = parts[3].split(\",\");\n\t\tif (perfParams.length != 3) {\n\t\t\tthrow new IllegalArgumentException(\"Amount of performance parameters invalid\");\n\t\t}\n\n\t\tif (!perfParams[0].startsWith(\"m=\")) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid memory parameter\");\n\t\t}\n\t\tbuilder.withMemoryAsKB(Integer.parseInt(perfParams[0].substring(2)));","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/utils/security/PasswordCryptUtils.java#L76-L112","documentation":"PasswordCryptUtils.match verifies a plaintext password against an Argon2-encoded hash by splitting the encoded string on '$'. If the encoded password has fewer than 4 '$'-separated parts, it is not a valid Argon2 PHC-style string and an IllegalArgumentException(\"Invalid encoded Argon2-hash\") is thrown.","triggerScenarios":"Calling PasswordCryptUtils.match(password, encodedPassword) where encodedPassword is null-safe but malformed: plaintext stored instead of a hash, truncated hash, a bcrypt/MD5 hash passed in, or a hash corrupted by DB migration/trimming.","commonSituations":"Legacy user rows whose password column predates Argon2; seeds/fixtures with fake strings like \"password123\"; copy-paste truncation; switching hashing algorithms without a migration path.","solutions":["Inspect the stored value; re-hash passwords with PasswordCryptUtils for accounts with malformed hashes","Add a migration that resets or lazily re-hashes non-Argon2 stored credentials","Validate the hash format (starts with $argon2 and has >=4 '$'-parts) before calling match, and treat invalid as login failure","Check for DB-level corruption/truncation (column width, encoding) if many rows fail"],"exampleFix":"// before\nboolean ok = PasswordCryptUtils.match(raw, user.getPassword()); // may throw\n// after\nString stored = user.getPassword();\nboolean ok = stored != null && stored.startsWith(\"$argon2\") && stored.split(\"\\\\$\").length >= 4\n        && PasswordCryptUtils.match(raw, stored);","handlingStrategy":"validation","validationCode":"boolean isArgon2Hash(String stored) {\n    return stored != null && stored.startsWith(\"$\") && stored.split(\"\\\\$\").length >= 4;\n}","typeGuard":null,"tryCatchPattern":"try {\n    boolean ok = PasswordCryptUtils.match(raw, stored);\n} catch (IllegalArgumentException e) {\n    // treat malformed hash as authentication failure and flag the account for re-hash\n    ok = false;\n}","preventionTips":["Only store hashes produced by PasswordCryptUtils in the password column","Migrate legacy plaintext/MD5/bcrypt rows to Argon2","Check hash format on write, not just on read","Beware DB truncation of long Argon2 strings"],"tags":["security","argon2","password-hashing"],"backgroundTag":"invalid-argument-format","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}