package org.pokenet.client.network; import org.apache.mina.core.session.IoSession; import org.pokenet.client.GameClient; import org.pokenet.client.backend.entity.Player.Direction; /** * Generates packets and sends them to the server * @author shadowkanji * */ public class PacketGenerator { private IoSession m_tcpSession; private IoSession m_udpSession; private IoSession m_chatSession; //private long m_lastMovement = 0; // Used when attempting to update passwords with old hash method to the new method private boolean updatePasswordHashMethod = false; private String lastUsername; private String lastPassword; /** * Sets the UDP session * @param s */ public void setUdpSession(IoSession s) { m_udpSession = s; } /** * Sets the TCP session * @param s */ public void setTcpSession(IoSession s) { m_tcpSession = s; } /** * Sets the chat session * @param s */ public void setChatSession(IoSession s) { m_chatSession = s; } /** * Returns the chat session * @return */ public IoSession getChatSession() { return m_chatSession; } /** * Returns the UDP session * @return */ public IoSession getUdpSession() { return m_udpSession; } /** * Returns the TCP session * @return */ public IoSession getTcpSession() { return m_tcpSession; } /** * Writes a message to chat server * @param message */ public void writeChatServerMessage(String message) { System.out.println("WRITING " + message); if(m_chatSession != null) m_chatSession.write(message); } /** * Sends a packet over TCP * @param message */ public void writeTcpMessage(String message) { m_tcpSession.write(message); } /** * Sends a packet over UDP * @param message */ public void writeUdpMessage(String message) { m_udpSession.write(message); } /** * Sends a login packet to server and chat server * @param username * @param password */ public void login(String username, String password) { // store values in case we need to attempt to update to the salted hashes this.lastUsername = username; this.lastPassword = password; char language = '0'; if(GameClient.getLanguage().equalsIgnoreCase("english")) { language = '0'; } else if(GameClient.getLanguage().equalsIgnoreCase("portuguese")) { language = '1'; } else if(GameClient.getLanguage().equalsIgnoreCase("italian")) { language = '2'; } else if(GameClient.getLanguage().equalsIgnoreCase("french")) { language = '3'; } else if(GameClient.getLanguage().equalsIgnoreCase("finnish")) { language = '4'; } else if(GameClient.getLanguage().equalsIgnoreCase("spanish")) { language = '5'; } else if(GameClient.getLanguage().equalsIgnoreCase("dutch")) { language = '6'; } else if(GameClient.getLanguage().equalsIgnoreCase("german")) { language = '7'; } m_tcpSession.write("l" + language + username + "," + (getPasswordHash(username, password))); if(GameClient.getInstance().getPacketGenerator().m_chatSession != null) m_chatSession.write("l" + language + username + "," + (getPasswordHash(username, password))); } /** * Sends a registration packet * @param username * @param password * @param email * @param dob * @param starter */ public void register( String username, String password, String email, String dob, int starter, int sprite, int region) { m_tcpSession.write("r" + region + username + "," + (getPasswordHash(username, password)) + "," + email + "," + dob + "," + starter + "," + sprite); } /** * Sends a password change packet * @param username * @param newPassword * @param oldPassword */ public void changePassword(String username, String newPassword, String oldPassword) { m_tcpSession.write("c" + username + "," + (getPasswordHash(username, newPassword)) + "," + (getPasswordHash(username, oldPassword))); } /** * Sends a password change packet to update to the new hash function * @param lastUsername * @param lastPassword */ public void updatePasswordHashMethod() { m_tcpSession.write("c" + lastUsername + "," + (getPasswordHash(lastUsername, lastPassword)) + "," + (getOldPasswordHash(lastPassword))); updatePasswordHashMethod = true; } /** * Sends a movement packet * @param d */ public void move(Direction d) { switch(d) { case Down: m_tcpSession.write("D"); break; case Up: m_tcpSession.write("U"); break; case Left: m_tcpSession.write("L"); break; case Right: m_tcpSession.write("R"); break; } } /** * Returns whether or not we are in the process of trying to update their password hash from the old method to the new one. * @return */ public boolean isUpdatingHashMethod() { return updatePasswordHashMethod; } /** * Resets values after attempting to update a password hash */ public void endUpdateHashMethod() { // ended attempt to update their password hash, reset values to default updatePasswordHashMethod = false; lastUsername = ""; lastPassword = ""; } /** * Returns the username last attempted to log on as (used to update hashes) * @return */ public String getLastUsername() { return lastUsername; } /** * Returns the password last used during attempt to log on (used to update hashes) * @return */ public String getLastPassword() { return lastPassword; } /** * Returns the hashed password * @param password * @return */ private String getPasswordHash(String user, String password) { String salt = "M0z3ah4SKieNwBboZ94URhIdDbgTNT"; String user_lowercase = user.toLowerCase(); // mix the user with the salt to create a unique salt String uniqueSalt = ""; for (int i = 0; i < user_lowercase.length(); i++) { uniqueSalt = uniqueSalt + user_lowercase.substring(i, i+1) + salt.substring(i, i+1); // last iteration, add remaining salt to the end if (i == user_lowercase.length() - 1) uniqueSalt = uniqueSalt + salt.substring(i+1); } Whirlpool hasher = new Whirlpool(); hasher.NESSIEinit(); //add plaintext password with salt to hasher hasher.NESSIEadd(password + uniqueSalt); // create array to hold the hashed bytes byte[] hashed = new byte[64]; // run the hash hasher.NESSIEfinalize(hashed); // turn the byte array into a hexstring char[] val = new char[2*hashed.length]; String hex = "0123456789ABCDEF"; for (int i = 0; i < hashed.length; i++) { int b = hashed[i] & 0xff; val[2*i] = hex.charAt(b >>> 4); val[2*i + 1] = hex.charAt(b & 15); } return String.valueOf(val); } /** * Returns the hashed password using the old method * @param password * @return */ private String getOldPasswordHash(String password) { Whirlpool hasher = new Whirlpool(); hasher.NESSIEinit(); // add the plaintext password to it hasher.NESSIEadd(password); // create an array to hold the hashed bytes byte[] hashed = new byte[64]; // run the hash hasher.NESSIEfinalize(hashed); // this stuff basically turns the byte array into a hexstring java.math.BigInteger bi = new java.math.BigInteger(hashed); String hashedStr = bi.toString(16); // 120ff0 if (hashedStr.length() % 2 != 0) { // Pad with 0 hashedStr = "0"+hashedStr; } return hashedStr; } }