public override MazeErrorCode onReceiveData(byte[] Data, ref byte[] ResponseData) { ResponseData = new byte[0]; if (LastErrorCode != MazeErrorCode.Success) { //don't continue if the client/server messed something up return LastErrorCode; } switch (base.Step) { case 1: { //step 2 if (Data.Length != Mazing.ByteCode.Length) { SysLogger.Log("[MazeHandShake][Server] ByteCode Length Missmatch", SysLogType.Debug); return MazeErrorCode.WrongByteCode; } for (int i = 0; i < Mazing.ByteCode.Length; i++) { if (Mazing.ByteCode[i] != Data[i]) { SysLogger.Log("[MazeHandShake][Server] WrongByteCode from client", SysLogType.Debug); return MazeErrorCode.WrongByteCode; } } Step++; break; } case 2: { if (onFindKeyInDatabase == null) //programmer error { SysLogger.Log("[MazeHandShake][Server] onFindKeyInDatabase is null", SysLogType.Debug); ResponseData = GetFailResponseData(); //not encrypted, client knows this will fail return MazeErrorCode.Error; } string EncHashedMsg = BitConverter.ToString(SHA512Managed.Create().ComputeHash(Data, 0, Data.Length)).Replace("-", ""); byte[] _key = new byte[0]; byte[] _salt = new byte[0]; byte[] _publicKey = new byte[0]; string _userName = ""; if (onFindKeyInDatabase(EncHashedMsg, ref _key, ref _salt, ref _publicKey, ref _userName)) { this.PublicKeyData = TrimArray(_publicKey, Mazing.MAX_KEY_SIZE); this.wopEx = base.GetWopEncryption(_key, _salt); base.FinalKey = _key; base.FinalSalt = _salt; //let's try to decrypt the data, should go successful wopEx.Decrypt(Data, 0, Data.Length); if (Data.Length != _publicKey.Length) { SysLogger.Log("[MazeHandShake][Server] Public key length missmatch", SysLogType.Debug); //key size not the same... strange ResponseData = GetFailResponseData(); return MazeErrorCode.Error; } for (int i = 0; i < _publicKey.Length; i++) { if (Data[i] != _publicKey[i]) { SysLogger.Log("[MazeHandShake][Server] Public key missmatch", SysLogType.Debug); //public key did not match... strange ResponseData = GetFailResponseData(); return MazeErrorCode.Error; } } //encryption / public key went successful for now this.server_Prime = BigInteger.genPseudoPrime(256, 50, new Random(BitConverter.ToInt32(_key, 0))); byte[] primeData = server_Prime.getBytes(); wopEx.Encrypt(primeData, 0, primeData.Length); ResponseData = primeData; this.Username = _userName; Step++; } else { SysLogger.Log("[MazeHandShake][Server] No user key found in database", SysLogType.Debug); ResponseData = GetFailResponseData(); return MazeErrorCode.UserKeyNotFound; } break; } case 3: { //response back from client with his prime number wopEx.Decrypt(Data, 0, Data.Length); this.client_Prime = new BigInteger(Data); if (this.client_Prime.isProbablePrime()) { //verify the prime from the client BigInteger client_Prime_test = BigInteger.genPseudoPrime(256, 50, new Random(this.server_Prime.IntValue())); if (this.client_Prime != client_Prime_test) { //Attacker detected ? SysLogger.Log("[MazeHandShake][Server] Man-In-The-Middle detected", SysLogType.Debug); return MazeErrorCode.Error; } BigInteger key = base.ModKey(server_Prime, client_Prime); //apply key to encryption ApplyKey(wopEx, key); return MazeErrorCode.Finished; } else { SysLogger.Log("[MazeHandShake][Server] Invalid response", SysLogType.Debug); return MazeErrorCode.Error; } } } return MazeErrorCode.Success; }
internal void ApplyKey(WopEx wopEx, BigInteger prime) { PatchKey(ref prime); byte[] primeKey = prime.getBytes(); ApplyKey(wopEx, primeKey); }
/// <summary> /// Patches the key by removing the 255 in the beginning of the key /// </summary> /// <param name="key"></param> private void PatchKey(ref BigInteger key) { byte[] _key = key.getBytes(); int count = 0; for (int i = 0; i < _key.Length; i++, count++) { if (_key[i] != 255) break; } if (count > 0) { byte[] tempKey = new byte[count]; new FastRandom(PrivateSalt.IntValue()).NextBytes(tempKey); Array.Copy(tempKey, _key, tempKey.Length); key = new BigInteger(_key); } }
public void WriteBigInteger(BigInteger BigInt) { byte[] temp = BigInt.getBytes(); WriteByte((byte)temp.Length); WriteBytes(temp); }