예제 #1
0
        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);
                            }
                        });
                    }
                }
            }
        }
예제 #2
0
 public SecureChannelHandshakeHello(SecureChannelCipherSuite supportedCiphers, SecureChannelOptions options)
     : base(SecureChannelCode.None)
 {
     _version          = 1;
     _nonce            = BinaryNumber.GenerateRandomNumber256();
     _supportedCiphers = supportedCiphers;
     _options          = options;
 }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
파일: Connection.cs 프로젝트: orf53975/Mesh
 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);
     }
 }
예제 #6
0
 public static DiscoveryPacket CreateQueryPacket()
 {
     return(new DiscoveryPacket(false, 0, BinaryNumber.GenerateRandomNumber256()));
 }
예제 #7
0
        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
        }
예제 #8
0
        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));
        }
예제 #9
0
        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));
        }
예제 #10
0
        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);
        }