I have this java code sleeping in a dusty folder...
Don't know if it's still accurate but this should help you understand what's going on everytime you send a score.
Code:
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.File;
//import java.io.BufferedWriter;
//import java.io.FileWriter;
/**
* A class to encode and decode Neopets.com flash game scores.
* @author unlimitedorb
* @since 4/20/2008
*/
public class Crypt {
private static final String scoreBase = "http://www.neopets.com/high_scores/process_flash_score.phtml";
private String username;
private String sessionHash;
private String sessionKey;
private int gameID;
private int wait;
private int modifiedGameID;
private String bin;
private int score;
private int dailyChallenge; //Setting it isn't implemented yet. (Don't do Daily Challenges!)
private int averageFrameRate = 24; //Isn't currently implemented.
private int multiple; //Confirm later! Probably determines whether it was multiplayer or not.
public Crypt(String username, String sh, String sk, int gameID, int wait, int score) {
this.username = username;
this.sessionHash = sh;
this.sessionKey = sk;
this.gameID = gameID;
this.wait = wait;
this.score = score;
this.dailyChallenge = -1;
this.bin = sh + sk;
modifiedGameID = 300 * gameID;
}
/**
* The class isn't meant to be used as a standalone, but this is provided just in case/for testing
* purposes. It's true purpose is as a utility to be used in a bot.
*/
public static void main(String[] args) {
//Crypt crypt = new Crypt("username", "4c82431c320b55797868", "fcb375decc3f7e1e83c7", 500, 500, 500);
String request = crypt.encode();
System.out.println(request);
}
/**
* Method to decode a Neopets.com flash game score. Useful for development.
* Hungarian notation in the original swf variables is stripped out.
* @param encryptedScore The score to be decoded.
*/
public static String decode(String encryptedScore, String hash, String key) {
String res = reverseEscapeString(encryptedScore);
String result = reverseStringToHex(res, hash, key);
return result;
}
/**
* A method to encode sensitive data.
* @return An encoded String.
*/
public String encode() {
//There might be extra parameters added, but that's game specific.
StringBuilder data = new StringBuilder(scoreBase + "?cn=" + modifiedGameID + "&gd=" + wait);
//Format the parameter r in the style of ActionScript's Math.random()
DecimalFormat rFormat = new DecimalFormat("0.000000000000000000");
data.append("&r=" + rFormat.format(Math.random()));
String toEncrypt = "ssnhsh=" + sessionHash + "&ssnky=" + sessionKey + "&gmd=" + gameID + "&scr=" + this.score + "&frmrt=" + averageFrameRate + "&chllng=" + (dailyChallenge == -1? "": dailyChallenge) + "&gmdrtn=" + wait;
String eScore = addSlashes(toEncrypt);
data.append("&gmd_g=" + this.gameID + "&mltpl_g=" + multiple + "&gmdt_g=" + eScore + "&sh_g=" + sessionHash + "&sk_g=" + sessionKey + "&usrnm_g=" + username + "&dc_g=" + (dailyChallenge == -1? 0: dailyChallenge));
String result = data.toString();
return result;
}
/**
* Scrambles information.
* @param data The information to be scrambled.
* @return Scrambled information.
*/
public String addSlashes(String data) {
return this.escapeString(this.stringToHex(data));
}
public String stringToHex(String data){
ArrayList<String> keys = getKeys(new File("keys.txt"));
String result = "";
int randomKey = (int) (Math.random() * keys.size());
int index = 0;
int count = 0;
String key = keys.get(randomKey);
while(index < data.length()) {
if (count >= this.bin.length()) {
count = 0;
}
int current = key.indexOf(data.charAt(index));
if (current >= 0) {
current = (current + key.indexOf(this.bin.charAt(count))) % key.length();
result += key.charAt(current);
} else {
result += data.charAt(index);
}
++count;
++index;
}
if (randomKey >= 10) {
result += String.valueOf(randomKey);
return result;
}
result += String.valueOf(0) + String.valueOf(randomKey);
return result;
}
public static String reverseStringToHex(String data, String sHash, String sKey) {
int k = Integer.parseInt(data.substring(data.length() - 2));
ArrayList<String> keys = getKeys(new File("keys.txt"));
String key = keys.get(k);
data = data.substring(0, data.length() - 2);
String bin = sHash + sKey;
String result = "";
int count = 0;
int current = 0;
for(int i = 0; i < data.length(); i++) {
if(count >= bin.length()) {
count = 0;
}
current = bin.charAt(count);
current = key.indexOf(data.charAt(i)) - key.indexOf(current);
if(current < 0) {
result += key.charAt(key.length() + current);
} else {
result += key.charAt(current);
}
count++;
}
return result;
}
/**
* Generates a String of ASCII code points with leading 0's for decoding purposes.
* @param data The String to escape.
* @return An escaped String.
*/
public String escapeString(String data) {
String result = "";
String current = "";
int index = 0;
int count = 0;
while(index < data.length()) {
current = String.valueOf((int) data.charAt(index));
//None of the key lengths are <= 1
count = 3 - current.length();
while(count > 0) {
current = "0" + current;
--count;
}
result += current;
++index;
}
return result;
}
/**
* Reverses the escapeString process.
* @param data The string to reverse.
* @return An unescaped String.
*/
public static String reverseEscapeString(String data) {
String result = "";
for(int i = 0; i < data.length(); i += 3) {
String current = data.substring(i, i + 3);
if(current.startsWith("0")) {
current = current.substring(1, current.length());
result += (char) Integer.parseInt(current);
} else {
result += (char) Integer.parseInt(current);
}
}
return result;
}
/**
* Retrieves keys from the text file "keys.txt"
* @param file The File to read the keys from.
* @return An ArrayList of Neopets.com flash game encryption keys.
*/
public static ArrayList<String> getKeys(File file) {
ArrayList<String> keys = new ArrayList<String>();
keys.ensureCapacity(20);
try {
BufferedReader stream = new BufferedReader(new FileReader(file));
String line;
//BufferedWriter out = new BufferedWriter(new FileWriter(new File("reversedkeys.txt")));
while((line = stream.readLine()) != null) {
String expression = "\\d+";
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(line);
String eLine = new String("");
while(matcher.find()) {
eLine += (char) Integer.parseInt(line.substring(matcher.start(), matcher.end()));
}
keys.add(eLine);
//out.write(eLine + "\n");
//out.flush();
}
stream.close();
//out.close();
} catch(Exception e) {
e.printStackTrace();
}
return keys;
}
/**
* @return the score
*/
public int getScore() {
return this.score;
}
public void setScore(int score) {
this.score = score;
}
}