RPC XOR encryption
Tibers
✭
Hello, recently my game players began to intercept the data and change them. For protection, I added xor encryption. I wanted to see this method in future updates Photon.
Protection was written by students who hack the game for instructions
NetworkingPeer.cs => RPC
NetworkingPeer.cs => ExecuteRpc
Protection was written by students who hack the game for instructions
NetworkingPeer.cs => RPC
//ts: changed RPCs to a one-level hashtable as described in internal.txt Hashtable rpcEvent = new Hashtable(); int encryptKey = UnityEngine.Random.Range(1,255); rpcEvent[(byte)6] = (byte)encryptKey; rpcEvent[(byte)0] = (int)view.viewID ^ encryptKey; // LIMITS NETWORKVIEWS&PLAYERS if (view.prefix > 0) { rpcEvent[(byte)1] = (short)view.prefix ^ (short)encryptKey; } rpcEvent[(byte)2] = PhotonNetwork.ServerTimestamp ^ encryptKey; // send name or shortcut (if available) int shortcut = 0; if (rpcShortcuts.TryGetValue(methodName, out shortcut)) { rpcEvent[(byte)5] = (byte)shortcut ^ (byte)encryptKey; // LIMITS RPC COUNT } else { string encryptMethodName = ""; for(int i=0;i<methodName.Length;i++){ encryptMethodName += (char)(methodName[i] ^ (char)encryptKey); } rpcEvent[(byte)3] = encryptMethodName; }
NetworkingPeer.cs => ExecuteRpc
// ts: updated with "flat" event data int encryptKey = (int)((byte)rpcData[(byte)6]); int netViewID = (int)rpcData[(byte)0] ^ encryptKey; // LIMITS PHOTONVIEWS&PLAYERS int otherSidePrefix = 0; // by default, the prefix is 0 (and this is not being sent) if (rpcData.ContainsKey((byte)1)) { otherSidePrefix = (short)rpcData[(byte)1] ^ (short)encryptKey; } string inMethodName; if (rpcData.ContainsKey((byte)5)) { int rpcIndex = (int)rpcData[(byte)5] ^ encryptKey; // LIMITS RPC COUNT if (rpcIndex > PhotonNetwork.PhotonServerSettings.RpcList.Count - 1) { Debug.LogError("Could not find RPC with index: " + rpcIndex + ". Going to ignore! Check PhotonServerSettings.RpcList"); return; } else { inMethodName = PhotonNetwork.PhotonServerSettings.RpcList[rpcIndex]; } } else { string encryptMethodName = (string)rpcData[(byte)3]; inMethodName = ""; for(int i=0;i<encryptMethodName.Length;i++){ inMethodName += (char)(encryptMethodName[i] ^ (char)encryptKey); } }
0
Comments
-
Out of curiosity: Did they achieve something useful by modifying the data on the network?
Encryption is optional in Photon (and too expensive to turn on by default) and we also have an option to include a CRC value for the messages (which help detect modified values).
Your solution is also interesting. Thanks for posting.0 -
I spent a performance test
Count = 1000 Original: 1ms Encrypt: 1ms Count = 10000 Original: 24ms Encrypt: 26ms Count = 100000 Original: 208ms Encrypt: 247ms
public int count = 10000; public bool isEncrypt; void Update(){ if(Input.GetKeyDown(KeyCode.F)){ if(isEncrypt){ TestEncrypt(); }else{ TestOriginal(); } } } void TestEncrypt(){ Stopwatch watch = Stopwatch.StartNew(); watch.Start(); for(int i=0;i<count;i++){ Hashtable rpcEvent = new Hashtable(); int encryptKey = UnityEngine.Random.Range(1,255); rpcEvent[(byte)6] = (byte)encryptKey; rpcEvent[(byte)0] = 2 ^ encryptKey; // LIMITS NETWORKVIEWS&PLAYERS rpcEvent[(byte)1] = (short)1 ^ (short)encryptKey; rpcEvent[(byte)2] = 5 ^ encryptKey; rpcEvent[(byte)5] = (byte)32 ^ (byte)encryptKey; // LIMITS RPC COUNT } watch.Stop(); print("Encrypt: " + watch.ElapsedMilliseconds + " ms"); } void TestOriginal(){ Stopwatch watch = Stopwatch.StartNew(); watch.Start(); for(int i=0;i<count;i++){ Hashtable rpcEvent = new Hashtable(); rpcEvent[(byte)0] = 2; // LIMITS NETWORKVIEWS&PLAYERS rpcEvent[(byte)1] = (short)1; rpcEvent[(byte)2] = 5; rpcEvent[(byte)5] = (byte)32; // LIMITS RPC COUNT } watch.Stop(); print("Original: " + watch.ElapsedMilliseconds + " ms"); }
0 -
Hmm, yes, this is cheap.
Do you also somehow prevent in-memory cheating? Or are your players only modifying network data currently?0