diff --git a/src/main/java/entralinked/gui/PidToolDialog.java b/src/main/java/entralinked/gui/PidToolDialog.java index 039aa60..8724ef6 100644 --- a/src/main/java/entralinked/gui/PidToolDialog.java +++ b/src/main/java/entralinked/gui/PidToolDialog.java @@ -15,6 +15,7 @@ import com.formdev.flatlaf.extras.components.FlatTextField; import entralinked.Entralinked; import entralinked.model.user.User; +import entralinked.utility.MD5; import entralinked.utility.SwingUtility; public class PidToolDialog { @@ -40,8 +41,8 @@ public class PidToolDialog { return; } - String userId = wfcIdField.getText().replace("-", ""); - String friendCode = friendCodeField.getText().replace("-", ""); + String userId = wfcIdField.getText().replace("-", "").replaceAll("\\s+", ""); + String friendCodeString = friendCodeField.getText().replace("-", "").replaceAll("\\s+", ""); // Make sure WFC ID is valid if(!WFC_ID_PATTERN.matcher(userId).matches()) { @@ -50,13 +51,12 @@ public class PidToolDialog { } // Make sure Friend Code is valid - if(!FRIEND_CODE_PATTERN.matcher(friendCode).matches()) { + if(!FRIEND_CODE_PATTERN.matcher(friendCodeString).matches()) { JOptionPane.showMessageDialog(dialog, "Please enter a valid Friend Code.", "Attention", JOptionPane.WARNING_MESSAGE); return; } User user = entralinked.getUserManager().getUser(userId.substring(0, 13)); - int profileId = (int)(Long.parseLong(friendCode) & 0x7FFFFFFF); // Make sure user exists if(user == null) { @@ -64,6 +64,26 @@ public class PidToolDialog { return; } + long friendCode = Long.parseLong(friendCodeString); + int profileId = (int)(friendCode & 0x7FFFFFFF); + int checksum = (int)(friendCode >> 32); + + // Compute friend code checksum + byte[] buffer = {0x00, 0x00, 0x00, 0x00, 0x4A, 0x41, 0x52, 0x49}; // Last 4 bytes is inverted game code (IRAJ) + buffer[0] = (byte)(profileId & 0xFF); + buffer[1] = (byte)(profileId >> 8 & 0xFF); + buffer[2] = (byte)(profileId >> 16 & 0xFF); + buffer[3] = (byte)(profileId >> 24 & 0xFF); + byte[] hash = MD5.digest(buffer); + int computedChecksum = hash[0] >> 1 & 0x7F; + + // Compare checksums + if(computedChecksum != checksum) { + JOptionPane.showMessageDialog(dialog, "This is not a valid Friend Code. Please check for typos.", "Attention", JOptionPane.WARNING_MESSAGE); + return; + } + + // Everything checks out -- update the profile id! user.setProfileIdOverride(profileId); JOptionPane.showMessageDialog(dialog, "All done! Please restart your game and use Game Sync.\nGame profile data will be updated and saved once you do so."); diff --git a/src/main/java/entralinked/utility/MD5.java b/src/main/java/entralinked/utility/MD5.java index 845a02c..7cb2e0c 100644 --- a/src/main/java/entralinked/utility/MD5.java +++ b/src/main/java/entralinked/utility/MD5.java @@ -21,6 +21,13 @@ public class MD5 { * @return A hex-formatted MD5 hash of the specified input. */ public static String digest(String string) { + return StringUtil.toHexStringPadded(digest(string.getBytes(StandardCharsets.ISO_8859_1))); + } + + /** + * @return An MD5 hash of the specified input. + */ + public static byte[] digest(byte[] bytes) { if(digest == null) { try { digest = MessageDigest.getInstance("MD5"); @@ -29,6 +36,6 @@ public class MD5 { } } - return StringUtil.toHexStringPadded(digest.digest(string.getBytes(StandardCharsets.ISO_8859_1))); + return digest.digest(bytes); } }