diff --git a/GamestatsBase/GamestatsHandler.cs b/GamestatsBase/GamestatsHandler.cs
index 200d411..c9fb959 100644
--- a/GamestatsBase/GamestatsHandler.cs
+++ b/GamestatsBase/GamestatsHandler.cs
@@ -18,8 +18,8 @@ namespace GamestatsBase
{
public class GamestatsHandler : IHttpHandler, IRequiresSessionState
{
- public GamestatsHandler(String initString, GamestatsRequestVersions reqVersion,
- GamestatsResponseVersions respVersion)
+ public GamestatsHandler(String initString, GamestatsRequestVersions reqVersion,
+ GamestatsResponseVersions respVersion, bool encryptedRequest = true)
{
if (initString.Length < 44) throw new FormatException();
@@ -30,19 +30,21 @@ namespace GamestatsBase
uint hashMask = UInt32.Parse(initString.Substring(44, 8), NumberStyles.AllowHexSpecifier);
String gameId = initString.Substring(52);
- Initialize(salt, rngMul, rngAdd, rngMask, hashMask, gameId, reqVersion, respVersion);
+ Initialize(salt, rngMul, rngAdd, rngMask, hashMask, gameId, reqVersion, respVersion, encryptedRequest);
}
public GamestatsHandler(String salt, uint rngMul, uint rngAdd, uint rngMask,
uint hashMask,
- String gameId, GamestatsRequestVersions reqVersion, GamestatsResponseVersions respVersion)
+ String gameId, GamestatsRequestVersions reqVersion, GamestatsResponseVersions respVersion,
+ bool encryptedRequest = true)
{
- Initialize(salt, rngMul, rngAdd, rngMask, hashMask, gameId, reqVersion, respVersion);
+ Initialize(salt, rngMul, rngAdd, rngMask, hashMask, gameId, reqVersion, respVersion, encryptedRequest);
}
private void Initialize(String salt, uint rngMul, uint rngAdd, uint rngMask,
uint hashMask,
- String gameId, GamestatsRequestVersions reqVersion, GamestatsResponseVersions respVersion)
+ String gameId, GamestatsRequestVersions reqVersion, GamestatsResponseVersions respVersion,
+ bool encryptedRequest)
{
if (salt.Length != 20) throw new FormatException();
Salt = salt;
@@ -53,16 +55,18 @@ namespace GamestatsBase
GameId = gameId;
RequestVersion = reqVersion;
ResponseVersion = respVersion;
+ EncryptedRequest = encryptedRequest;
}
- public String Salt { get; private set; }
- public uint RngMul { get; private set; }
- public uint RngAdd { get; private set; }
- public uint RngMask { get; private set; }
- public uint HashMask { get; private set; }
- public String GameId { get; private set; }
- public GamestatsRequestVersions RequestVersion { get; private set; }
- public GamestatsResponseVersions ResponseVersion { get; private set; }
+ public String Salt { get; protected set; }
+ public uint RngMul { get; protected set; }
+ public uint RngAdd { get; protected set; }
+ public uint RngMask { get; protected set; }
+ public uint HashMask { get; protected set; }
+ public String GameId { get; protected set; }
+ public GamestatsRequestVersions RequestVersion { get; protected set; }
+ public GamestatsResponseVersions ResponseVersion { get; protected set; }
+ public bool EncryptedRequest { get; protected set; }
public GamestatsSessionManager SessionManager
{
@@ -273,7 +277,7 @@ namespace GamestatsBase
}
///
- /// Decrypts the NDS &data= querystring into readable binary data.
+ /// Decrypts the NDS &data= querystring into readable binary data.
/// The PID (little endian) is left at the start of the output
/// but the (unencrypted) checksum is removed.
///
@@ -283,16 +287,17 @@ namespace GamestatsBase
if (RequestVersion == GamestatsRequestVersions.Version1) return data2;
if (data2.Length < 4) throw new FormatException("Data must contain at least 4 bytes.");
- byte[] data3 = new byte[data2.Length - 4];
int checksum = BitConverter.ToInt32(data2, 0);
checksum = IPAddress.NetworkToHostOrder(checksum); // endian flip
checksum ^= (int)HashMask;
- int rand = checksum | (checksum << 16);
- for (int pos = 0; pos < data3.Length; pos++)
+ byte[] data3;
+ if (EncryptedRequest)
+ data3 = DecryptMain(data2, checksum | (checksum << 16));
+ else
{
- rand = DecryptRNG(rand);
- data3[pos] = (byte)(data2[pos + 4] ^ (byte)(rand >> 16));
+ data3 = new byte[data2.Length - 4];
+ Array.Copy(data2, 4, data3, 0, data2.Length - 4);
}
int checkedsum = 0;
@@ -304,6 +309,18 @@ namespace GamestatsBase
return data3;
}
+ private byte[] DecryptMain(byte[] data2, int rand)
+ {
+ byte[] data3 = new byte[data2.Length - 4];
+
+ for (int pos = 0; pos < data3.Length; pos++)
+ {
+ rand = DecryptRNG(rand);
+ data3[pos] = (byte)(data2[pos + 4] ^ (byte)(rand >> 16));
+ }
+ return data3;
+ }
+
private static int DecryptRNG(int prev, uint mul, uint add, uint mask)
{
return (prev * (int)mul + (int)add) & ~(int)mask;
@@ -351,7 +368,7 @@ namespace GamestatsBase
Version1,
///
/// Data contains an obfuscated checksum and pid, and supports
- /// enryption.
+ /// encryption.
///
Version2,
///
@@ -368,7 +385,7 @@ namespace GamestatsBase
///
Version1,
///
- /// Response contains a salted hash at the end, encoded in hex.
+ /// Response contains a salted hash at the end, in hex coded ASCII.
///
Version2
}