/// <summary> /// Waits for a handshake from the server. /// </summary> /// <param name="rsa">The RSA crypter.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="rsa" /> is <see langword="null" />. /// </exception> protected bool WaitForHandshake(RSACryptoServiceProvider rsa) { if (rsa == null) { throw new ArgumentNullException("rsa"); } byte[] buffer; buffer = this.Stream.WaitAndRead(2); if (buffer.Length != 2) { return(false); } // content length var contentLength = buffer.ToUInt16().Value; if (contentLength < 1) { // no data return(false); } buffer = this.Stream.WaitAndRead(contentLength); if (buffer.Length != contentLength) { return(false); } var uncrypted = rsa.Decrypt(buffer, false); if (uncrypted.Length < 1) { return(false); } CryptAlgorithm algo; if (!Enum.TryParse <CryptAlgorithm>(uncrypted[0].ToString(), out algo)) { return(false); } ICrypter crypter = null; switch (algo) { case CryptAlgorithm.UNKNOWN: break; case CryptAlgorithm.Rijndael: crypter = RijndaelCrypter.FromParameters(uncrypted.Skip(1)); break; default: throw new NotImplementedException(algo.ToString()); } if (crypter == null) { return(false); } this.Crypter = crypter; return(true); }
/// <summary> /// Waits for a handshake from client. /// </summary> protected bool WaitForHandshake() { byte[] buffer; buffer = this.Stream.WaitAndRead(1); if (buffer.Length != 1) { return(false); } var version = buffer[0]; if (version != 1) { // not supported return(false); } buffer = this.Stream.WaitAndRead(2); if (buffer.Length != 2) { return(false); } var keySize = buffer.ToUInt16().Value; if (keySize < 1) { // no key return(false); } var key = this.Stream.WaitAndRead(keySize); if (key.Length != keySize) { return(false); } RijndaelCrypter crypter; using (var rsa = new RSACryptoServiceProvider()) { rsa.ImportCspBlob(key); crypter = new RijndaelCrypter(); byte[] content; using (var temp = new MemoryStream()) { // algorithm var algo = CryptAlgorithm.Rijndael; temp.WriteByte((byte)algo); // parameters var @params = crypter.ExportParameters(); temp.Write(@params, 0, @params.Length); content = rsa.Encrypt(temp.ToArray(), false); } // content length var contentLength = (ushort)content.Length; this.Stream.Write(contentLength.GetBytes(), 0, 2); // content this.Stream.Write(content, 0, content.Length); } this.Crypter = crypter; return(true); }