You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
fix(housekeeping): hash reset password with BCrypt, not SHA-256
`HousekeepingResetUserPasswordEvent` was writing a SHA-256 hex digest into `users.password`, but the Nitro auth path (`SessionEndpoints` / `AccountChangeEndpoints` → `AuthHttpUtil.checkPassword`) only does `BCrypt.checkpw`. A SHA-256 hex string doesn't start with `$2…$`, so jbcrypt throws `IllegalArgumentException`, `checkPassword` returns false, and operators saw "credenziali invalide" on every account whose password had been reset from the in-client panel. Switch to `BCrypt.hashpw(plain, BCrypt.gensalt(10))` — same idiom already used by `SessionEndpoints.java:351` and `AccountChangeEndpoints.java:98`. Cost 10 (vs 12 there) is fine for a server-generated 12-char random password: gensalt(10) keeps the operator-facing reset snappy and the output is identical-shape (`$2a$…`) to what jbcrypt 0.4 already accepts. Side-effects: - drops the `MessageDigest` / `NoSuchAlgorithmException` / `StandardCharsets` imports and the local `sha256Hex` helper - repurposes the existing `housekeeping.error.hash_failed` key for `BCrypt.gensalt`'s only failure mode (invalid cost / log_rounds out of range) so the client error surface is unchanged - updates the file javadoc to stop telling future readers to "swap the MessageDigest constant" — Arcturus itself only verifies BCrypt Companion of duckietm/Nitro-V3#157 (`feat/housekeeping-panel`). The client/UI is untouched — packet 9200, the action-result reveal card, the copy button, and the plaintext flow through `message` are all unchanged.
This commit is contained in:
+10
-25
@@ -4,10 +4,8 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.housekeeping.HousekeepingActionResultComposer;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
@@ -15,19 +13,18 @@ import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Reset a user's password to a fresh random 12-character alphanumeric
|
||||
* string. Persists the SHA-256 hex of the new password into
|
||||
* `users.password` (varchar(64) — sized to hold SHA-256 hex), clears
|
||||
* `auth_ticket` so any active session can't be re-used to bypass the
|
||||
* reset, and ships the PLAINTEXT new password back to the operator in
|
||||
* the action-result `message` so they can communicate it out-of-band.
|
||||
*
|
||||
* If your CMS uses a hash other than SHA-256 (bcrypt / argon2 / SHA-1),
|
||||
* swap the MessageDigest constant — the rest of the flow is hash-agnostic.
|
||||
* string. Persists a BCrypt `$2a$` hash of the new password into
|
||||
* `users.password` (matches what `AuthHttpUtil.checkPassword` /
|
||||
* `SessionEndpoints` / `AccountChangeEndpoints` already write and read),
|
||||
* clears `auth_ticket` so any active session can't be re-used to bypass
|
||||
* the reset, and ships the PLAINTEXT new password back to the operator
|
||||
* in the action-result `message` so they can communicate it out-of-band.
|
||||
*/
|
||||
public class HousekeepingResetUserPasswordEvent extends MessageHandler {
|
||||
private static final String ACTION_KEY = "user.reset_password";
|
||||
private static final String PASSWORD_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
|
||||
private static final int PASSWORD_LENGTH = 12;
|
||||
private static final int BCRYPT_COST = 10;
|
||||
|
||||
private static final SecureRandom RNG = new SecureRandom();
|
||||
|
||||
@@ -53,8 +50,8 @@ public class HousekeepingResetUserPasswordEvent extends MessageHandler {
|
||||
String hash;
|
||||
|
||||
try {
|
||||
hash = sha256Hex(plain);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
hash = BCrypt.hashpw(plain, BCrypt.gensalt(BCRYPT_COST));
|
||||
} catch (IllegalArgumentException e) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "housekeeping.error.hash_failed"));
|
||||
return;
|
||||
}
|
||||
@@ -89,16 +86,4 @@ public class HousekeepingResetUserPasswordEvent extends MessageHandler {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String sha256Hex(String plain) throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
byte[] digest = md.digest(plain.getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder hex = new StringBuilder(digest.length * 2);
|
||||
|
||||
for (byte b : digest) {
|
||||
hex.append(String.format("%02x", b));
|
||||
}
|
||||
|
||||
return hex.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user