public void Test_Pbkdf2()
        {
            byte[] password = new byte[256];
            byte[] salt = new byte[256];

            _random.NextBytes(password);
            _random.NextBytes(salt);

            using (var hmac = new System.Security.Cryptography.HMACSHA1())
            {
                Pbkdf2 pbkdf2 = new Pbkdf2(hmac, password, salt, 1024);
                System.Security.Cryptography.Rfc2898DeriveBytes rfc2898DeriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt, 1024);

                Assert.IsTrue(CollectionUtilities.Equals(pbkdf2.GetBytes(1024), rfc2898DeriveBytes.GetBytes(1024)), "Pbkdf2 #1");
            }

            //_random.NextBytes(password);
            //_random.NextBytes(salt);

            //using (var hmac = new System.Security.Cryptography.HMACSHA256())
            //{
            //    CryptoConfig.AddAlgorithm(typeof(SHA256Cng),
            //        "SHA256",
            //        "SHA256Cng",
            //        "System.Security.Cryptography.SHA256",
            //        "System.Security.Cryptography.SHA256Cng");

            //    hmac.HashName = "System.Security.Cryptography.SHA256";

            //    Pbkdf2 pbkdf2 = new Pbkdf2(hmac, password, salt, 1024);
            //    var h = pbkdf2.GetBytes(10);
            //}
        }
        public override void Connect(TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);

            lock (this.ThisLock)
            {
                try
                {
                    SecureVersion3.ProtocolInformation myProtocol3;
                    SecureVersion3.ProtocolInformation otherProtocol3;

                    {
                        OperatingSystem osInfo = Environment.OSVersion;

                        // Windows Vista�ȏ�B
                        if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version >= new Version(6, 0))
                        {
                            {
                                byte[] sessionId = new byte[32];
                                _random.GetBytes(sessionId);

                                myProtocol3 = new SecureVersion3.ProtocolInformation()
                                {
                                    KeyExchangeAlgorithm = SecureVersion3.KeyExchangeAlgorithm.EcDiffieHellmanP521 | SecureVersion3.KeyExchangeAlgorithm.Rsa2048,
                                    KeyDerivationAlgorithm = SecureVersion3.KeyDerivationAlgorithm.Pbkdf2,
                                    CryptoAlgorithm = SecureVersion3.CryptoAlgorithm.Aes256,
                                    HashAlgorithm = SecureVersion3.HashAlgorithm.Sha256,
                                    SessionId = sessionId,
                                };
                            }
                        }
                        else
                        {
                            {
                                byte[] sessionId = new byte[32];
                                _random.GetBytes(sessionId);

                                myProtocol3 = new SecureVersion3.ProtocolInformation()
                                {
                                    KeyExchangeAlgorithm = SecureVersion3.KeyExchangeAlgorithm.Rsa2048,
                                    KeyDerivationAlgorithm = SecureVersion3.KeyDerivationAlgorithm.Pbkdf2,
                                    CryptoAlgorithm = SecureVersion3.CryptoAlgorithm.Aes256,
                                    HashAlgorithm = SecureVersion3.HashAlgorithm.Sha256,
                                    SessionId = sessionId,
                                };
                            }
                        }
                    }

                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();

                    using (BufferStream stream = new BufferStream(_bufferManager))
                    using (XmlTextWriter xml = new XmlTextWriter(stream, new UTF8Encoding(false)))
                    {
                        xml.WriteStartDocument();

                        xml.WriteStartElement("Protocol");

                        if (_myVersion.HasFlag(SecureConnectionVersion.Version3))
                        {
                            xml.WriteStartElement("SecureConnection");
                            xml.WriteAttributeString("Version", "3");
                            xml.WriteEndElement(); //Protocol
                        }

                        xml.WriteEndElement(); //Configuration

                        xml.WriteEndDocument();
                        xml.Flush();
                        stream.Flush();

                        stream.Seek(0, SeekOrigin.Begin);
                        _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                    }

                    otherProtocol3 = new SecureVersion3.ProtocolInformation();

                    using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                    using (XmlTextReader xml = new XmlTextReader(stream))
                    {
                        while (xml.Read())
                        {
                            if (xml.NodeType == XmlNodeType.Element)
                            {
                                if (xml.LocalName == "SecureConnection")
                                {
                                    if (xml.GetAttribute("Version") == "3")
                                    {
                                        _otherVersion |= SecureConnectionVersion.Version3;
                                    }
                                }
                            }
                        }
                    }

                    _version = _myVersion & _otherVersion;

                    // Version3
                    if (_version.HasFlag(SecureConnectionVersion.Version3))
                    {
                        using (Stream stream = myProtocol3.Export(_bufferManager))
                        {
                            _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                        }

                        using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                        {
                            otherProtocol3 = SecureVersion3.ProtocolInformation.Import(stream, _bufferManager);
                        }

                        var keyExchangeAlgorithm = myProtocol3.KeyExchangeAlgorithm & otherProtocol3.KeyExchangeAlgorithm;
                        var keyDerivationFunctionAlgorithm = myProtocol3.KeyDerivationAlgorithm & otherProtocol3.KeyDerivationAlgorithm;
                        var cryptoAlgorithm = myProtocol3.CryptoAlgorithm & otherProtocol3.CryptoAlgorithm;
                        var hashAlgorithm = myProtocol3.HashAlgorithm & otherProtocol3.HashAlgorithm;

                        byte[] myCryptoKey;
                        byte[] otherCryptoKey;
                        byte[] myHmacKey;
                        byte[] otherHmacKey;

                        byte[] myProtocolHash = null;
                        byte[] otherProtocolHash = null;

                        if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                        {
                            using (var myProtocolHashStream = myProtocol3.Export(_bufferManager))
                            using (var otherProtocolHashStream = otherProtocol3.Export(_bufferManager))
                            {
                                myProtocolHash = Sha256.ComputeHash(myProtocolHashStream);
                                otherProtocolHash = Sha256.ComputeHash(otherProtocolHashStream);
                            }
                        }

                        byte[] seed = null;

                        if (keyExchangeAlgorithm.HasFlag(SecureVersion3.KeyExchangeAlgorithm.EcDiffieHellmanP521))
                        {
                            byte[] publicKey, privateKey;
                            EcDiffieHellmanP521.CreateKeys(out publicKey, out privateKey);

                            {
                                SecureVersion3.ConnectionSignature connectionSignature = new SecureVersion3.ConnectionSignature();
                                connectionSignature.ExchangeKey = publicKey;

                                if (_digitalSignature != null)
                                {
                                    connectionSignature.CreationTime = DateTime.UtcNow;
                                    connectionSignature.ProtocolHash = myProtocolHash;
                                    connectionSignature.CreateCertificate(_digitalSignature);
                                }

                                using (Stream stream = connectionSignature.Export(_bufferManager))
                                {
                                    _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                                }
                            }

                            byte[] otherPublicKey = null;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                SecureVersion3.ConnectionSignature connectionSignature = SecureVersion3.ConnectionSignature.Import(stream, _bufferManager);

                                if (connectionSignature.VerifyCertificate())
                                {
                                    if (connectionSignature.Certificate != null)
                                    {
                                        DateTime now = DateTime.UtcNow;
                                        TimeSpan span = (now > connectionSignature.CreationTime) ? now - connectionSignature.CreationTime : connectionSignature.CreationTime - now;
                                        if (span > new TimeSpan(0, 30, 0)) throw new ConnectionException();

                                        if (!Unsafe.Equals(connectionSignature.ProtocolHash, otherProtocolHash)) throw new ConnectionException();
                                    }

                                    _certificate = connectionSignature.Certificate;
                                    otherPublicKey = connectionSignature.ExchangeKey;
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                seed = EcDiffieHellmanP521.DeriveKeyMaterial(privateKey, otherPublicKey, CngAlgorithm.Sha256);
                            }

                            if (seed == null) throw new ConnectionException();
                        }
                        else if (keyExchangeAlgorithm.HasFlag(SecureVersion3.KeyExchangeAlgorithm.Rsa2048))
                        {
                            byte[] publicKey, privateKey;
                            Rsa2048.CreateKeys(out publicKey, out privateKey);

                            {
                                SecureVersion3.ConnectionSignature connectionSignature = new SecureVersion3.ConnectionSignature();
                                connectionSignature.ExchangeKey = publicKey;

                                if (_digitalSignature != null)
                                {
                                    connectionSignature.CreationTime = DateTime.UtcNow;
                                    connectionSignature.ProtocolHash = myProtocolHash;
                                    connectionSignature.CreateCertificate(_digitalSignature);
                                }

                                using (Stream stream = connectionSignature.Export(_bufferManager))
                                {
                                    _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                                }
                            }

                            byte[] otherPublicKey;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                SecureVersion3.ConnectionSignature connectionSignature = SecureVersion3.ConnectionSignature.Import(stream, _bufferManager);

                                if (connectionSignature.VerifyCertificate())
                                {
                                    if (connectionSignature.Certificate != null)
                                    {
                                        DateTime now = DateTime.UtcNow;
                                        TimeSpan span = (now > connectionSignature.CreationTime) ? now - connectionSignature.CreationTime : connectionSignature.CreationTime - now;
                                        if (span > new TimeSpan(0, 30, 0)) throw new ConnectionException();

                                        if (!Unsafe.Equals(connectionSignature.ProtocolHash, otherProtocolHash)) throw new ConnectionException();
                                    }

                                    _certificate = connectionSignature.Certificate;
                                    otherPublicKey = connectionSignature.ExchangeKey;
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }

                            byte[] mySeed = new byte[128];
                            _random.GetBytes(mySeed);

                            using (MemoryStream stream = new MemoryStream(Rsa2048.Encrypt(otherPublicKey, mySeed)))
                            {
                                _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                            }

                            byte[] otherSeed;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                var buffer = new byte[stream.Length];
                                stream.Read(buffer, 0, buffer.Length);

                                otherSeed = Rsa2048.Decrypt(privateKey, buffer);
                            }

                            if (otherSeed == null) throw new ConnectionException();

                            seed = new byte[Math.Max(mySeed.Length, otherSeed.Length)];
                            Unsafe.Xor(mySeed, otherSeed, seed);
                        }
                        else
                        {
                            throw new ConnectionException();
                        }

                        if (keyDerivationFunctionAlgorithm.HasFlag(SecureVersion3.KeyDerivationAlgorithm.Pbkdf2))
                        {
                            byte[] xorSessionId = new byte[Math.Max(myProtocol3.SessionId.Length, otherProtocol3.SessionId.Length)];
                            Unsafe.Xor(myProtocol3.SessionId, otherProtocol3.SessionId, xorSessionId);

                            HMAC hmac = null;

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                hmac = new HMACSHA256();
                                hmac.HashName = "SHA256";
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            Pbkdf2 pbkdf2 = new Pbkdf2(hmac, seed, xorSessionId, 1024);

                            int cryptoKeyLength;
                            int hmacKeyLength;

                            if (cryptoAlgorithm.HasFlag(SecureVersion3.CryptoAlgorithm.Aes256))
                            {
                                cryptoKeyLength = 32;
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                hmacKeyLength = 32;
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            myCryptoKey = new byte[cryptoKeyLength];
                            otherCryptoKey = new byte[cryptoKeyLength];
                            myHmacKey = new byte[hmacKeyLength];
                            otherHmacKey = new byte[hmacKeyLength];

                            using (MemoryStream stream = new MemoryStream(pbkdf2.GetBytes((cryptoKeyLength + hmacKeyLength) * 2)))
                            {
                                if (_type == SecureConnectionType.Connect)
                                {
                                    stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                                    stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                                    stream.Read(myHmacKey, 0, myHmacKey.Length);
                                    stream.Read(otherHmacKey, 0, otherHmacKey.Length);
                                }
                                else if (_type == SecureConnectionType.Accept)
                                {
                                    stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                                    stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                                    stream.Read(otherHmacKey, 0, otherHmacKey.Length);
                                    stream.Read(myHmacKey, 0, myHmacKey.Length);
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }
                        }
                        else
                        {
                            throw new ConnectionException();
                        }

                        _informationVersion3 = new InformationVersion3();
                        _informationVersion3.CryptoAlgorithm = cryptoAlgorithm;
                        _informationVersion3.HashAlgorithm = hashAlgorithm;
                        _informationVersion3.MyCryptoKey = myCryptoKey;
                        _informationVersion3.OtherCryptoKey = otherCryptoKey;
                        _informationVersion3.MyHmacKey = myHmacKey;
                        _informationVersion3.OtherHmacKey = otherHmacKey;
                    }
                    else
                    {
                        throw new ConnectionException();
                    }
                }
                catch (ConnectionException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new ConnectionException(e.Message, e);
                }

                _connect = true;
            }
        }