Skip to content

Commit

Permalink
Validate friend code checksum
Browse files Browse the repository at this point in the history
  • Loading branch information
kuroppoi committed Aug 11, 2023
1 parent 3224f63 commit 91eb997
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
28 changes: 24 additions & 4 deletions src/main/java/entralinked/gui/PidToolDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import entralinked.Entralinked;
import entralinked.model.user.User;
import entralinked.utility.MD5;
import entralinked.utility.SwingUtility;

public class PidToolDialog {
Expand All @@ -40,8 +41,8 @@ public PidToolDialog(Entralinked entralinked, JFrame frame) {
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()) {
Expand All @@ -50,20 +51,39 @@ public PidToolDialog(Entralinked entralinked, JFrame frame) {
}

// 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) {
JOptionPane.showMessageDialog(dialog, "This Wi-Fi Connection ID does not exist.", "Attention", JOptionPane.WARNING_MESSAGE);
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.");
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/entralinked/utility/MD5.java
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -29,6 +36,6 @@ public static String digest(String string) {
}
}

return StringUtil.toHexStringPadded(digest.digest(string.getBytes(StandardCharsets.ISO_8859_1)));
return digest.digest(bytes);
}
}

0 comments on commit 91eb997

Please sign in to comment.