internal void RefreshBucket(DhtNode dhtNode) { List <KBucket> allLeafKBuckets = GetAllLeafKBuckets(); foreach (KBucket kBucket in allLeafKBuckets) { if (kBucket._contacts != null) { if ((DateTime.UtcNow - kBucket._lastChanged).TotalSeconds > BUCKET_STALE_TIMEOUT_SECONDS) { ThreadPool.QueueUserWorkItem(delegate(object state) { //get random node ID in the bucket range BinaryNumber randomNodeID = BinaryNumber.GenerateRandomNumber256(); if (kBucket._bucketID != null) { randomNodeID = (randomNodeID >> kBucket._bucketDepth) | kBucket._bucketID; } //find closest contacts for current node id NodeContact[] initialContacts = kBucket.GetKClosestContacts(randomNodeID, true); if (initialContacts.Length > 0) { dhtNode.QueryFindNode(initialContacts, randomNodeID); } }); } } } }
public SecureChannelHandshakeHello(SecureChannelCipherSuite supportedCiphers, SecureChannelOptions options) : base(SecureChannelCode.None) { _version = 1; _nonce = BinaryNumber.GenerateRandomNumber256(); _supportedCiphers = supportedCiphers; _options = options; }
public DhtNode(IDhtConnectionManager manager, EndPoint nodeEP) { _manager = manager; switch (nodeEP.AddressFamily) { case AddressFamily.InterNetwork: case AddressFamily.InterNetworkV6: if (IPAddress.IsLoopback((nodeEP as IPEndPoint).Address)) { _currentNode = new CurrentNode(BinaryNumber.GenerateRandomNumber256(), nodeEP); } else { _currentNode = new CurrentNode(nodeEP); } break; case AddressFamily.Unspecified: _currentNode = new CurrentNode(nodeEP); break; default: throw new NotSupportedException(); } //init routing table _routingTable = new KBucket(_currentNode); //start health timer _healthTimer = new Timer(delegate(object state) { try { //remove expired data _currentNode.RemoveExpiredPeers(); //check contact health _routingTable.CheckContactHealth(this); //refresh buckets _routingTable.RefreshBucket(this); //find closest contacts for current node id NodeContact[] initialContacts = _routingTable.GetKClosestContacts(_currentNode.NodeId, true); if (initialContacts.Length > 0) { QueryFindNode(initialContacts, _currentNode.NodeId); //query manager auto add contacts that respond } } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); } }, null, HEALTH_CHECK_TIMER_INITIAL_INTERVAL, HEALTH_CHECK_TIMER_INTERVAL); }
public EndPoint[] GetKRandomNodeEPs(bool includeSelfContact) { NodeContact[] contacts = _routingTable.GetKClosestContacts(BinaryNumber.GenerateRandomNumber256(), includeSelfContact); EndPoint[] nodeEPs = new EndPoint[contacts.Length]; for (int i = 0; i < contacts.Length; i++) { nodeEPs[i] = contacts[i].NodeEP; } return(nodeEPs); }
public void EnableTcpRelayClientMode() { if (_tcpRelayClientModeTimer == null) { _tcpRelayClientModeTimer = new Timer(delegate(object state) { try { WriteFrame(ConnectionSignal.PingRequest, BinaryNumber.GenerateRandomNumber256(), null, 0, 0); } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); } }, null, 1000, TCP_RELAY_CLIENT_MODE_TIMER_INTERVAL); } }
public static DiscoveryPacket CreateQueryPacket() { return(new DiscoveryPacket(false, 0, BinaryNumber.GenerateRandomNumber256())); }
private void ProtocolV4(Stream stream) { WriteBufferedStream bufferedStream = new WriteBufferedStream(stream, 8 * 1024); #region 1. hello handshake //read client hello SecureChannelHandshakeHello clientHello = new SecureChannelHandshakeHello(bufferedStream); //select crypto option _selectedCryptoOption = _supportedOptions & clientHello.CryptoOptions; if (_selectedCryptoOption == SecureChannelCryptoOptionFlags.None) { throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } else if ((_selectedCryptoOption & SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256) > 0) { _selectedCryptoOption = SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256; } else if ((_selectedCryptoOption & SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256) > 0) { _selectedCryptoOption = SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256; } else { throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //send server hello SecureChannelHandshakeHello serverHello = new SecureChannelHandshakeHello(BinaryNumber.GenerateRandomNumber256(), _selectedCryptoOption); serverHello.WriteTo(bufferedStream); #endregion #region 2. key exchange SymmetricEncryptionAlgorithm encAlgo; string hashAlgo; KeyAgreement keyAgreement; switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new DiffieHellman(DiffieHellmanGroupType.RFC3526, 2048, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new TechnitiumLibrary.Security.Cryptography.ECDiffieHellman(256, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //send server key exchange data new SecureChannelHandshakeKeyExchange(keyAgreement.GetPublicKey(), _serverCredentials.PrivateKey, hashAlgo).WriteTo(bufferedStream); bufferedStream.Flush(); //read client key exchange data SecureChannelHandshakeKeyExchange clientKeyExchange = new SecureChannelHandshakeKeyExchange(bufferedStream); //generate master key byte[] masterKey = GenerateMasterKey(clientHello, serverHello, _preSharedKey, keyAgreement, clientKeyExchange.PublicKey); //verify master key using HMAC authentication { SecureChannelHandshakeAuthentication clientAuthentication = new SecureChannelHandshakeAuthentication(bufferedStream); if (!clientAuthentication.IsValid(serverHello, masterKey)) { throw new SecureChannelException(SecureChannelCode.ProtocolAuthenticationFailed, _remotePeerEP, _remotePeerCert); } SecureChannelHandshakeAuthentication serverAuthentication = new SecureChannelHandshakeAuthentication(clientHello, masterKey); serverAuthentication.WriteTo(bufferedStream); bufferedStream.Flush(); } //enable channel encryption switch (encAlgo) { case SymmetricEncryptionAlgorithm.Rijndael: //using MD5 for generating AES IV of 128bit block size HashAlgorithm md5Hash = HashAlgorithm.Create("MD5"); byte[] eIV = md5Hash.ComputeHash(serverHello.Nonce.Number); byte[] dIV = md5Hash.ComputeHash(clientHello.Nonce.Number); //create encryption and decryption objects SymmetricCryptoKey encryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, eIV, PaddingMode.None); SymmetricCryptoKey decryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, dIV, PaddingMode.None); //enable encryption EnableEncryption(stream, encryptionKey, decryptionKey, new HMACSHA256(masterKey), new HMACSHA256(masterKey)); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //channel encryption is ON! #endregion #region 3. exchange & verify certificates & signatures if (!IsReNegotiating()) { //read client certificate _remotePeerCert = new SecureChannelHandshakeCertificate(this).Certificate; //verify client certificate try { _remotePeerCert.Verify(_trustedRootCertificates); } catch (Exception ex) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificate, _remotePeerEP, _remotePeerCert, "Invalid remote certificate.", ex); } } //verify key exchange signature switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: if (_remotePeerCert.PublicKeyEncryptionAlgorithm != AsymmetricEncryptionAlgorithm.RSA) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificateAlgorithm, _remotePeerEP, _remotePeerCert); } if (!clientKeyExchange.IsSignatureValid(_remotePeerCert, "SHA256")) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteKeyExchangeSignature, _remotePeerEP, _remotePeerCert); } break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } if ((_manager != null) && !_manager.ProceedConnection(_remotePeerCert)) { throw new SecureChannelException(SecureChannelCode.SecurityManagerDeclinedAccess, _remotePeerEP, _remotePeerCert, "Security manager declined access."); } //send server certificate if (!IsReNegotiating()) { new SecureChannelHandshakeCertificate(_serverCredentials.Certificate).WriteTo(this); this.Flush(); } #endregion }
public BitChat CreateGroupChat(string networkName, string sharedSecret, bool enableTracking, bool dhtOnlyTracking) { Uri[] trackerURIs; if (dhtOnlyTracking) { trackerURIs = new Uri[] { } } ; else { trackerURIs = _profile.TrackerURIs; } BitChatNetwork network = new BitChatNetwork(_connectionManager, _trustedRootCertificates, _supportedCryptoOptions, networkName, sharedSecret, null, null, new Certificate[] { }, BitChatNetworkStatus.Online); return(CreateBitChat(network, BinaryNumber.GenerateRandomNumber160().ToString(), BinaryNumber.GenerateRandomNumber256().Number, -1, null, new BitChatProfile.SharedFileInfo[] { }, trackerURIs, enableTracking, false, false)); }
public BitChat CreatePrivateChat(MailAddress peerEmailAddress, string sharedSecret, bool enableTracking, bool dhtOnlyTracking, string invitationMessage) { Uri[] trackerURIs; if (dhtOnlyTracking) { trackerURIs = new Uri[] { } } ; else { trackerURIs = _profile.TrackerURIs; } BitChatNetwork network = new BitChatNetwork(_connectionManager, _trustedRootCertificates, _supportedCryptoOptions, peerEmailAddress, sharedSecret, null, null, new Certificate[] { }, BitChatNetworkStatus.Online, _profile.LocalCertificateStore.Certificate.IssuedTo.EmailAddress.Address, invitationMessage); return(CreateBitChat(network, BinaryNumber.GenerateRandomNumber160().ToString(), BinaryNumber.GenerateRandomNumber256().Number, 0, null, new BitChatProfile.SharedFileInfo[] { }, trackerURIs, enableTracking, !string.IsNullOrEmpty(invitationMessage), false)); }
private void CreateInvitationPrivateChat(BinaryNumber hashedPeerEmailAddress, BinaryNumber networkID, IPEndPoint peerEP, string message) { BitChatNetwork network = new BitChatNetwork(_connectionManager, _trustedRootCertificates, _supportedCryptoOptions, hashedPeerEmailAddress, networkID, null, BitChatNetworkStatus.Offline, peerEP.ToString(), message); BitChat chat = CreateBitChat(network, BinaryNumber.GenerateRandomNumber160().ToString(), BinaryNumber.GenerateRandomNumber256().Number, 0, null, new BitChatProfile.SharedFileInfo[] { }, _profile.TrackerURIs, true, false, false); RaiseEventBitChatInvitationReceived(chat); }