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> /// Attempts to verify the public key on the other end of the stream. /// </summary> /// <param name="stream">The stream to handshake on.</param> /// <param name="publicKey">The public key claimed by the other side.</param> /// <returns>True if the identity was verified.</returns> public static bool VerifyIdentity(Stream stream, out byte[] publicKey) { var rdr = new BinaryReader(stream); var sigGuid = Guid.NewGuid(); //Length is fixed - 16 bytes stream.Write(sigGuid.ToByteArray(), 0, 16); publicKey = rdr.ReadBytes(rdr.ReadInt32()); var sig = rdr.ReadBytes(rdr.ReadInt32()); using (var rsa = OpenSslKey.DecodeX509PublicKey(publicKey)) return(rsa.VerifyData(sigGuid.ToByteArray(), new SHA256CryptoServiceProvider(), sig)); }