async Task SendData(byte[] Data, IncomingClient client) { try { byte[] nonce = new byte[8]; Common.rngCsp.GetBytes(nonce); byte[] counter_sender_data = Utils.GetLengthAsBytes((int)client.PacketCounter).Concat(Data).ToArray(); byte[] CryptedCounterSenderData = Salsa20.ProcessSalsa20(counter_sender_data, client.TransportKey, nonce, 0); byte[] HMAC = (new HMACSHA256(client.AuthenticationKey)).ComputeHash(CryptedCounterSenderData).Take(16).ToArray(); byte[] NONCE_MAC_DATA = nonce.Concat(HMAC).Concat(CryptedCounterSenderData).ToArray(); await PacketSender.SendTransportPacket(client.client.GetStream(), TransportPacketType.DataCrypted, NONCE_MAC_DATA); } catch { } }
public void StartListeningInternal() { try { listener.Start(); while (Constants.ApplicationRunning) { IncomingClient _inClient = new IncomingClient(); _inClient.client = listener.AcceptTcpClient(); Constants.SERVER_GLOBAL_TOTAL_ACC_CONNS++; Hash hsh = new Hash(Utils.GenerateUniqueGUID_Bytes(8)); _inClient.Identifier = hsh; ThreadList.Add(hsh, _inClient); Task.Run(() => { ClientHandler(_inClient); }); /*Thread clientThread = new Thread(new ParameterizedThreadStart(ClientHandler)); _inClient.thread = clientThread; clientThread.Start(_inClient);*/ } } catch (Exception ex) { DisplayUtils.Display("Listening", ex); } }
//System.Diagnostics.Stopwatch sw_timer = new System.Diagnostics.Stopwatch(); async Task ProcessIncomingUserInternal(IncomingClient iClient, TransportPacket p) { BinaryReader reader = new BinaryReader(iClient.client.GetStream()); //BinaryWriter writer = new BinaryWriter(iClient.client.GetStream()); NetworkStream writer = iClient.client.GetStream(); //DisplayUtils.Display("Packet Received: " + p.Type); switch (p.Type) { case TransportPacketType.Initialize: iClient.ConnTimeStart = DateTime.UtcNow.Ticks; //DisplayUtils.Display("Init Received", DisplayType.Info); if ((!iClient.WorkProven) && (!iClient.KeyExchanged)) { await PacketSender.SendTransportPacket(writer, TransportPacketType.WorkProofRequest, iClient.WorkTask); } break; case TransportPacketType.WorkProofKeyResponse: //DisplayUtils.Display("WorkProofResponse Received : " + p.Data.Length, DisplayType.Info); if ((!iClient.WorkProven) && (!iClient.KeyExchanged)) { if (p.Data.Length == 60) { Constants.SERVER_GLOBAL_AUTH_PACKETS++; byte[] Proof = new byte[4]; byte[] DHClientPublic = new byte[32]; byte[] AuthRandom = new byte[24]; Array.Copy(p.Data, 0, Proof, 0, 4); Array.Copy(p.Data, 4, DHClientPublic, 0, 32); Array.Copy(p.Data, 36, AuthRandom, 0, 24); iClient.WorkProven = WorkProof.VerifyProof(iClient.WorkTask, Proof, Constants.Difficulty); if (iClient.WorkProven) { //DisplayUtils.Display("Work Proved", DisplayType.Info); Common.rngCsp.GetBytes(iClient.DHRandomBytes); iClient.DHPrivateKey = Curve25519.ClampPrivateKey(iClient.DHRandomBytes); iClient.DHPublicKey = Curve25519.GetPublicKey(iClient.DHPrivateKey); // Generate the shared-secret using the provided client Public Key byte[] sharedSecret = (new SHA512Managed()).ComputeHash(Curve25519.GetSharedSecret(iClient.DHPrivateKey, DHClientPublic)); Array.Copy(sharedSecret, iClient.TransportKey, 32); Array.Copy(sharedSecret, 32, iClient.AuthenticationKey, 0, 32); // Sign the data using the Node-Private key, so that the client can know that the connection is secure. // This thwarts MITM attacks. byte[] Client_ServerAuthSignature = nodeConfig.SignDataWithPrivateKey(AuthRandom); // 64 bytes Signature byte[] signPlain = Client_ServerAuthSignature; if (signPlain.Length != 64) throw new Exception("Improbable Assertion failed : 1"); // Encrypt the Signature and Identifier using Salsa20 byte[] signCrypted = Salsa20.ProcessSalsa20(signPlain, iClient.TransportKey, new byte[8], 0); // EtM -> Encrypt then MAC byte[] signMAC = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(signCrypted); // SERVER_PUBLIC[32] || signMAC[32] || signCrypted[64] => 128 bytes byte[] KeysSignature = iClient.DHPublicKey.Concat(signMAC).Concat(signCrypted).ToArray(); await PacketSender.SendTransportPacket(writer, TransportPacketType.ServerPublicTransfer, KeysSignature); } else { DisplayUtils.Display("Work Proof invalid : " + p.Data.Length, DisplayType.Exception); await PacketSender.SendTransportPacket(writer, TransportPacketType.InvalidAuthDisconnect, new byte[0]); } } else { DisplayUtils.Display("Invalid Packet Length : " + p.Data.Length, DisplayType.Exception); await PacketSender.SendTransportPacket(writer, TransportPacketType.InvalidAuthDisconnect, new byte[0]); } } break; case TransportPacketType.KeyExComplete_1: if ((iClient.WorkProven) && (!iClient.KeyExchanged)) { if (p.Data.Length == 128) { // cryptedSigPK_MAC[32] || cryptedSigPK[96] = 128 bytes byte[] cryptedSigPK_MAC = new byte[32]; byte[] cryptedSigPK = new byte[96]; Array.Copy(p.Data, 0, cryptedSigPK_MAC, 0, 32); Array.Copy(p.Data, 32, cryptedSigPK, 0, 96); byte[] cryptedSigPK_MAC_Expected = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(cryptedSigPK); if (CryptoBytes.ConstantTimeEquals(cryptedSigPK_MAC_Expected, cryptedSigPK_MAC)) { byte[] workSignPK = Salsa20.ProcessSalsa20(cryptedSigPK, iClient.TransportKey, new byte[8], 0); // workSignPK[96] = workSign[64] || nodeConfig.PublicKey[32] byte[] workSign = new byte[64]; byte[] remotePK = new byte[32]; Array.Copy(workSignPK, 0, workSign, 0, 64); Array.Copy(workSignPK, 64, remotePK, 0, 32); bool serverVerified = Ed25519.Verify(workSign, iClient.WorkTask, remotePK); if (serverVerified) { iClient.PublicKey = new Hash(remotePK); if (Constants.NetworkVerbosity >= Verbosity.Info) { /*DisplayUtils.Display(NodeSocketData.GetString(nodeSocketData) + " : Key Exchanged 1: Shared KEY [TransportKey] : {" + (HexUtil.ToString(TransportKey)) + "}", DisplayType.Info);*/ DisplayUtils.Display(iClient.PublicKey.ToString() + " Client Authenticated", DisplayType.Info); } await PacketSender.SendTransportPacket(writer, TransportPacketType.KeyExComplete_2, new byte[0]); iClient.KeyExchanged = true; IncomingConnections.Add(iClient.PublicKey, iClient); DisplayUtils.Display("Exchange Complete 2, Shared KEY [TransportKey] : " + HexUtil.ToString(iClient.TransportKey), DisplayType.Info); } } } } break; case TransportPacketType.DataCrypted: if (iClient.KeyExchanged && p.Data.Length > 28) { Constants.SERVER_GLOBAL_DATA_PACKETS++; byte[] nonce = new byte[8]; byte[] hmac = new byte[16]; byte[] crypted_data = new byte[p.Data.Length - 24]; Array.Copy(p.Data, 0, nonce, 0, 8); Array.Copy(p.Data, 8, hmac, 0, 16); Array.Copy(p.Data, 24, crypted_data, 0, crypted_data.Length); byte[] MAC_EXPECTED = (new HMACSHA256(iClient.AuthenticationKey)).ComputeHash(crypted_data).Take(16).ToArray(); if (CryptoBytes.ConstantTimeEquals(MAC_EXPECTED, hmac)) { byte[] DeCryptedData = Salsa20.ProcessSalsa20(crypted_data, iClient.TransportKey, nonce, 0); byte[] counter = new byte[4]; byte[] rec_data = new byte[p.Data.Length - 28]; Array.Copy(DeCryptedData, 0, counter, 0, 4); Array.Copy(DeCryptedData, 4, rec_data, 0, rec_data.Length); Array.Copy(DeCryptedData, 0, counter, 0, 4); Array.Copy(DeCryptedData, 4, rec_data, 0, rec_data.Length); NetworkPacket np = new NetworkPacket(); np.Deserialize(rec_data); if (iClient.PublicKey == np.PublicKeySource) { if (PacketReceived != null) PacketReceived(np); } else { DisplayUtils.Display("Packet Source Incoming Mismatch", DisplayType.Warning); } } else { DisplayUtils.Display("HMAC FAILED : "); } } break; } }