/// <summary> /// Initializes a new instance of the <see cref="NetworkConnectionProvider" /> class. /// </summary> /// <param name="endPoint">The endpoint to listen to.</param> /// <param name="maxConnections">Maximum number of connections to allow.</param> /// <param name="protocols">The protocols to accept.</param> /// <param name="pkCryptoFactory">The public key cryptography provider factory.</param> /// <param name="enabledHashAlgs"> /// The signature hash algorithms (in order of preference) to enable from <paramref name="pkCryptoFactory"/>. /// <c>null</c> or an empty collection will enable all of the signature hash algorithms. /// </param> /// <exception cref="ArgumentNullException"><paramref name="endPoint"/>, <paramref name="protocols" /> or <paramref name="pkCryptoFactory" /> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="maxConnections"/> is <= 0</exception> public NetworkConnectionProvider(IEnumerable<Protocol> protocols, IPEndPoint endPoint, int maxConnections, Func<IPublicKeyCrypto> pkCryptoFactory, IEnumerable<string> enabledHashAlgs = null) { if (pkCryptoFactory == null) throw new ArgumentNullException ("pkCryptoFactory"); if (protocols == null) throw new ArgumentNullException ("protocols"); if (endPoint == null) throw new ArgumentNullException ("endPoint"); if (maxConnections <= 0) throw new ArgumentOutOfRangeException ("maxConnections"); this.protocols = protocols; this.endPoint = endPoint; MaxConnections = maxConnections; this.serverConnections = new List<NetworkServerConnection> (maxConnections); this.pkCryptoFactory = pkCryptoFactory; if (protocols.Any (p => p != null && p.RequiresHandshake)) { ThreadPool.QueueUserWorkItem (s => { #if NET_4 Task encryptKeyGen = Task.Factory.StartNew (() => { #endif this.pkEncryption = this.pkCryptoFactory(); this.publicEncryptionKey = this.pkEncryption.ExportKey (false); #if NET_4 }); #endif #if NET_4 Task authKeyGen = Task.Factory.StartNew (() => { #endif this.authentication = this.pkCryptoFactory(); if (this.authenticationKey == null) this.authenticationKey = this.authentication.ExportKey (true); else this.authentication.ImportKey (this.authenticationKey); this.publicAuthenticationKey = this.authentication.ExportKey (false); if (enabledHashAlgs == null || !enabledHashAlgs.Any()) this.enabledHashAlgorithms.AddRange (this.authentication.SupportedHashAlgs); else // Need to maintain preference order this.enabledHashAlgorithms.AddRange (enabledHashAlgs.Where (a => this.authentication.SupportedHashAlgs.Contains (a))); #if NET_4 }); authKeyGen.Wait(); encryptKeyGen.Wait(); #endif this.keyWait.Set(); }); } else this.keyWait.Set(); }
protected override bool VerifyMessage(string hashAlg, Message message, byte[] signature, byte[] data, int moffset, int length) { if (this.hmac == null) { byte[] resized = new byte[length]; Buffer.BlockCopy (data, moffset, resized, 0, length); var msg = (AcknowledgeConnectMessage)message; this.serverAuthentication = this.publicKeyCryptoFactory(); this.serverAuthenticationKey = msg.PublicAuthenticationKey; this.serverAuthentication.ImportKey (this.serverAuthenticationKey); this.signingHashAlgorithm = msg.SignatureHashAlgorithm; return this.serverAuthentication.VerifySignedHash (this.signingHashAlgorithm, resized, signature); } else return base.VerifyMessage (hashAlg, message, signature, data, moffset, length); }
protected override void Recycle() { Interlocked.Add (ref sendBufferLimit, AutoSizeFactor * -1); this.serverEncryption = null; this.serverEncryptionKey = null; this.serverAuthenticationKey = null; base.Recycle(); }
protected override void OnTempestMessageReceived(MessageEventArgs e) { switch (e.Message.MessageType) { case (ushort)TempestMessageType.Ping: var ping = (PingMessage)e.Message; if (this.pingFrequency == 0 || this.activityTimer == null) { if (this.activityTimer != null) this.activityTimer.Dispose(); if (ping.Interval != 0) { this.activityTimer = new Tempest.Timer (ping.Interval); this.activityTimer.TimesUp += ActivityCallback; this.activityTimer.Start(); } } else if (ping.Interval != this.pingFrequency) this.activityTimer.Interval = ping.Interval; this.pingFrequency = ((PingMessage)e.Message).Interval; break; case (ushort)TempestMessageType.AcknowledgeConnect: var msg = (AcknowledgeConnectMessage)e.Message; this.protocols = this.protocols.Values.Intersect (msg.EnabledProtocols).ToDictionary (pr => pr.id); ConnectionId = msg.ConnectionId; this.serverEncryption = this.publicKeyCryptoFactory(); this.serverEncryption.ImportKey (msg.PublicEncryptionKey); this.serverEncryptionKey = msg.PublicEncryptionKey; var encryption = new AesManaged { KeySize = 256 }; encryption.GenerateKey(); BufferValueWriter authKeyWriter = new BufferValueWriter (new byte[1600]); this.publicAuthenticationKey.Serialize (authKeyWriter, this.serverEncryption); Send (new FinalConnectMessage { AESKey = this.serverEncryption.Encrypt (encryption.Key), PublicAuthenticationKeyType = this.publicAuthenticationKey.GetType(), PublicAuthenticationKey = authKeyWriter.ToArray() }); this.aes = encryption; this.hmac = new HMACSHA256 (this.aes.Key); break; case (ushort)TempestMessageType.Connected: var connected = (ConnectedMessage) e.Message; ConnectionId = connected.ConnectionId; OnConnected (new ClientConnectionEventArgs (this)); var tcs = Interlocked.Exchange (ref this.connectCompletion, null); if (tcs != null) tcs.SetResult (new ClientConnectionResult (ConnectionResult.Success, this.serverAuthenticationKey)); break; } base.OnTempestMessageReceived(e); }
public void Serialize(IValueWriter writer, IPublicKeyCrypto crypto) { if (writer.WriteBool (D != null)) { writer.WriteBytes (crypto.Encrypt (D)); writer.WriteBytes (crypto.Encrypt (DP)); writer.WriteBytes (crypto.Encrypt (DQ)); writer.WriteBytes (crypto.Encrypt (InverseQ)); writer.WriteBytes (crypto.Encrypt (P)); writer.WriteBytes (crypto.Encrypt (Q)); } if (writer.WriteBool (this.publicKey != null)) { writer.WriteBytes (crypto.Encrypt (Exponent)); int first = Modulus.Length / 2; writer.WriteBytes (crypto.Encrypt (Modulus.Copy (0, first))); writer.WriteBytes (crypto.Encrypt (Modulus.Copy (first, Modulus.Length - first))); } }
public void Deserialize(IValueReader reader, IPublicKeyCrypto crypto) { if (reader == null) throw new ArgumentNullException ("reader"); if (crypto == null) throw new ArgumentNullException ("crypto"); if (reader.ReadBool()) { D = crypto.Decrypt (reader.ReadBytes()); DP = crypto.Decrypt (reader.ReadBytes()); DQ = crypto.Decrypt (reader.ReadBytes()); InverseQ = crypto.Decrypt (reader.ReadBytes()); P = crypto.Decrypt (reader.ReadBytes()); Q = crypto.Decrypt (reader.ReadBytes()); } if (reader.ReadBool()) { byte[] exponent = crypto.Decrypt (reader.ReadBytes()); byte[] modulus1 = crypto.Decrypt (reader.ReadBytes()); byte[] modulus2 = crypto.Decrypt (reader.ReadBytes()); byte[] modulus = modulus1.Concat (modulus2).ToArray(); this.exponentOffset = modulus.Length; this.publicKey = new byte[exponent.Length + modulus.Length]; Buffer.BlockCopy (modulus, 0, this.publicKey, 0, modulus.Length); Buffer.BlockCopy (exponent, 0, this.publicKey, exponentOffset, exponent.Length); } SetupSignature(); }