diff --git a/core/src/main/java/com/xujiayao/discord_mc_chat/utils/CryptUtils.java b/core/src/main/java/com/xujiayao/discord_mc_chat/utils/CryptUtils.java new file mode 100644 index 00000000..f079aa40 --- /dev/null +++ b/core/src/main/java/com/xujiayao/discord_mc_chat/utils/CryptUtils.java @@ -0,0 +1,54 @@ +package com.xujiayao.discord_mc_chat.utils; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.SecureRandom; + +/** + * Cryptographic utilities. + * + * @author Xujiayao + */ +public class CryptUtils { + + private static final SecureRandom RANDOM = new SecureRandom(); + private static final char[] ALPHANUMERIC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); + + /** + * Calculates the SHA-256 hash of a string. + * + * @param input The input string. + * @return The hex string of the hash. + */ + public static String sha256(String input) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(); + for (byte b : hash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (Exception e) { + throw new RuntimeException("SHA-256 algorithm not found", e); + } + } + + /** + * Generates a random alphanumeric string. + * + * @param length The length of the string. + * @return The random string. + */ + public static String generateRandomString(int length) { + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + sb.append(ALPHANUMERIC[RANDOM.nextInt(ALPHANUMERIC.length)]); + } + return sb.toString(); + } +} diff --git a/core/src/main/java/com/xujiayao/discord_mc_chat/utils/config/ConfigManager.java b/core/src/main/java/com/xujiayao/discord_mc_chat/utils/config/ConfigManager.java index 215aca5e..15512166 100644 --- a/core/src/main/java/com/xujiayao/discord_mc_chat/utils/config/ConfigManager.java +++ b/core/src/main/java/com/xujiayao/discord_mc_chat/utils/config/ConfigManager.java @@ -1,6 +1,7 @@ package com.xujiayao.discord_mc_chat.utils.config; import com.fasterxml.jackson.databind.JsonNode; +import com.xujiayao.discord_mc_chat.utils.CryptUtils; import com.xujiayao.discord_mc_chat.utils.StringUtils; import com.xujiayao.discord_mc_chat.utils.YamlUtils; import com.xujiayao.discord_mc_chat.utils.i18n.I18nManager; @@ -11,8 +12,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.SecureRandom; -import java.util.Base64; import java.util.function.Function; import static com.xujiayao.discord_mc_chat.Constants.LOGGER; @@ -62,7 +61,7 @@ public class ConfigManager { // If in standalone mode, generate a secure random shared secret if ("standalone".equals(expectedMode)) { - String randomSecret = generateRandomSecret(); + String randomSecret = CryptUtils.generateRandomString(32); template = template.replace("shared_secret: \"to_be_auto_replaced\"", StringUtils.format("shared_secret: \"{}\"", randomSecret)); } @@ -108,18 +107,6 @@ public class ConfigManager { } } - /** - * Generates a cryptographically strong random string for the shared secret. - * - * @return A random 32-character string. - */ - private static String generateRandomSecret() { - SecureRandom random = new SecureRandom(); - byte[] bytes = new byte[24]; // 24 bytes becomes 32 chars in Base64 - random.nextBytes(bytes); - return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); - } - /** * Gets a specific configuration value as a JsonNode. *