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; } }