internal void PerformTcpHandshake() { if (Client.SymetricKey == Guid.Empty) { Client.SymetricKey = Guid.NewGuid(); } using (var client = new TcpClient()) { client.Connect(EndPoint); using (var stream = client.GetStream()) { var rdr = new BinaryReader(stream); var wrt = new BinaryWriter(stream); wrt.Write((byte)PeerCommand.Identify); wrt.Write(Client.PublicKey.Length); wrt.Write(Client.PublicKey); var sigGuid = rdr.ReadBytes(16); using (var rsa = OpenSslKey.DecodeRsaPrivateKey(Client.PrivateKey)) { var sig = rsa.SignData(sigGuid, new SHA256CryptoServiceProvider()); wrt.Write(sig.Length); wrt.Write(sig); } using (var rsa = OpenSslKey.DecodeX509PublicKey(PublicKey)) { var encSym = rsa.Encrypt(Client.SymetricKey.ToByteArray(), false); wrt.Write(encSym.Length); wrt.Write(encSym); } wrt.Write(Client.DisplayName != null); if (Client.DisplayName != null) { wrt.Write(Client.DisplayName); } wrt.Write(Client.ProfilePicture != null); if (Client.ProfilePicture != null) { wrt.Write(Client.ProfilePicture.Length); wrt.Write(Client.ProfilePicture); } DisplayName = rdr.ReadBoolean() ? rdr.ReadString() : null; if (rdr.ReadBoolean()) { rdr.ReadBytes(rdr.ReadInt32()); } } } }
/// <summary> /// Shakes hands with the client to prove that you own a private key for your claimed public key. /// </summary> /// <param name="stream">The stream to handshake on.</param> /// <param name="publicKey">The public key to transmit and verify.</param> /// <param name="privateKey">The private key to use for signing.</param> public static void ProveIdentity(Stream stream, byte[] publicKey, byte[] privateKey) { var rdr = new BinaryReader(stream); var wrt = new BinaryWriter(stream); wrt.Write(publicKey.Length); wrt.Write(publicKey); var sigGuid = rdr.ReadBytes(16); using (var rsa = OpenSslKey.DecodeRsaPrivateKey(privateKey)) { var sig = rsa.SignData(sigGuid, new SHA256CryptoServiceProvider()); wrt.Write(sig.Length); wrt.Write(sig); } }
private void TcpAcceptLoop(IAsyncResult result) { try { _tcpListener.BeginAcceptSocket(TcpAcceptLoop, null); } catch { //Called when disposed return; } using (var socket = _tcpListener.EndAcceptSocket(result)) using (var stream = new NetworkStream(socket)) { if (!(socket.RemoteEndPoint is IPEndPoint)) { return; } var rdr = new BinaryReader(stream); var wrt = new BinaryWriter(stream); switch ((PeerCommand)rdr.ReadByte()) { case PeerCommand.Identify: { byte[] pub; if (!GlobalHelpers.VerifyIdentity(stream, out pub)) { return; } var symGuid = rdr.ReadBytes(rdr.ReadInt32()); using (var rsa = OpenSslKey.DecodeRsaPrivateKey(PrivateKey)) SymetricKey = new Guid(rsa.Decrypt(symGuid, false)); var peer = new PhonemePeer(this, pub, new IPEndPoint(((IPEndPoint)socket.RemoteEndPoint).Address, NetworkPort)); if (!_knownPeersSet.Contains(peer)) { _knownPeersSet.Add(peer); //TODO: Remove this dependency Application.Current.Dispatcher.Invoke(() => KnownPeers.Add(peer)); PeerJoin?.Invoke(peer); } else { peer = _knownPeersSet.First(x => x.Equals(peer)); } peer.DisplayName = rdr.ReadBoolean() ? rdr.ReadString() : null; if (rdr.ReadBoolean()) { rdr.ReadBytes(rdr.ReadInt32()); } wrt.Write(DisplayName != null); if (DisplayName != null) { wrt.Write(DisplayName); } wrt.Write(ProfilePicture != null); if (ProfilePicture != null) { wrt.Write(ProfilePicture.Length); wrt.Write(ProfilePicture); } break; } case PeerCommand.BinaryBlob: { byte[] pub; if (!GlobalHelpers.VerifyIdentity(stream, out pub)) { return; } var peer = new PhonemePeer(this, pub, new IPEndPoint(((IPEndPoint)socket.RemoteEndPoint).Address, NetworkPort)); if (!_knownPeersSet.Contains(peer)) { return; } peer = _knownPeersSet.First(x => x.Equals(peer)); var blob = rdr.ReadBytes(rdr.ReadInt32()); GlobalHelpers.OneTimePad(blob, SymetricKey); peer.OnMessageRecieved(blob); break; } default: throw new ArgumentOutOfRangeException(); } } }