コード例 #1
0
        private async ValueTask AddConnectionAsync(IConnection connection, OmniAddress address, ConnectionHandshakeType handshakeType, CancellationToken cancellationToken = default)
        {
            var status = new ConnectionStatus(connection, address, handshakeType);

            var myNodeProflie = new NodeProfile(await _connectionController.GetListenEndpointsAsync(cancellationToken));

            var myHelloMessage = new NodeExplorerHelloMessage(_myId, myNodeProflie);
            NodeExplorerHelloMessage?otherHelloMessage = null;

            var enqueueTask = connection.EnqueueAsync((bufferWriter) => myNodeProflie.Export(bufferWriter, _bytesPool), cancellationToken);
            var dequeueTask = connection.DequeueAsync((sequence) => otherHelloMessage = NodeExplorerHelloMessage.Import(sequence, _bytesPool), cancellationToken);

            await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

            if (otherHelloMessage == null)
            {
                return;
            }

            status.Id          = otherHelloMessage.Id;
            status.NodeProfile = otherHelloMessage.NodeProfile;

            lock (_lockObject)
            {
                _connections.Add(status);
            }
        }
コード例 #2
0
        private async ValueTask <IReadOnlyCollection <IMessage> > InternalRouteAsync(RouteHierarchy routes, IMessage serializedMessage, bool publish, CancellationToken cancellation)
        {
            var localEndPoint = await GetLocalEndPointAsync(cancellation);

            var tasks            = new List <ValueTask <(IMessage response, bool handled)> >();
            var handledEndPoints = new HashSet <EndPointAddress>();

            _logger?.LogTrace($"Routing a message ({(publish ? "publish" : "p2p")}) with routes: {routes}");

            foreach (var route in routes)
            {
                var matches = await MatchRouteAsync(route, publish, handledEndPoints, cancellation);

                if (matches.Any())
                {
                    if (!publish)
                    {
                        _logger?.LogTrace($"Found {matches.Count()} matches for route '{route}'.");

                        for (var i = matches.Count - 1; i >= 0; i--)
                        {
                            var(endPoint, options) = matches[i];

                            if (endPoint == EndPointAddress.UnknownAddress)
                            {
                                continue;
                            }

                            if ((options & RouteRegistrationOptions.PublishOnly) == RouteRegistrationOptions.PublishOnly)
                            {
                                continue;
                            }

                            var(response, handled) = await InternalRouteAsync(route, serializedMessage, publish : false, endPoint, cancellation);

                            if (handled)
                            {
                                return(response.Yield().ToArray());
                            }
                        }
                    }
                    else
                    {
                        _logger?.LogTrace($"Found {matches.Count()} matches (considering handled end-points) for route '{route}'.");

                        var endPoints = matches.Select(p => p.EndPoint);
                        handledEndPoints.UnionWith(endPoints);
                        tasks.AddRange(endPoints.Select(endPoint => InternalRouteAsync(route, serializedMessage, publish: true, endPoint, cancellation)));
                    }
                }
            }

            var result = await ValueTaskHelper.WhenAll(tasks, preserveOrder : false);

            _logger?.LogTrace($"Successfully routed a message ({(publish ? "publish" : "p2p")}) with routes: {routes}");

            return(result.Where(p => p.handled).Select(p => p.response).ToArray());
        }
コード例 #3
0
ファイル: PhotoRepository.cs プロジェクト: asm2025/MatchNBuy
 private ValueTask UpdateDefaultPhotosAsync(Photo photo, CancellationToken token = default(CancellationToken))
 {
     token.ThrowIfCancellationRequested();
     if (photo == null || !photo.IsDefault)
     {
         return(ValueTaskHelper.CompletedTask());
     }
     return(new ValueTask(DbSet.Where(e => e.UserId == photo.UserId && e.IsDefault && e.Id != photo.Id)
                          .ForEachAsync(e =>
     {
         if (!e.IsDefault)
         {
             return;
         }
         e.IsDefault = false;
         Context.Update(e);
     }, token)));
 }
コード例 #4
0
        private async ValueTask HelloAsync(CancellationToken cancellationToken)
        {
            HelloMessage sendHelloMessage;
            HelloMessage?receiveHelloMessage = null;

            {
                sendHelloMessage = new HelloMessage(new[] { _version });

                var enqueueTask = _connection.EnqueueAsync((bufferWriter) => sendHelloMessage.Export(bufferWriter, _bytesPool), cancellationToken);
                var dequeueTask = _connection.DequeueAsync((sequence) => receiveHelloMessage = HelloMessage.Import(sequence, _bytesPool), cancellationToken);

                await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

                if (receiveHelloMessage is null)
                {
                    throw new NullReferenceException();
                }
            }

            _version = GetOverlapMaxEnum(sendHelloMessage.Versions, receiveHelloMessage.Versions);
        }
コード例 #5
0
        private async Task <bool> DispatchCoreAsync(ICommit commit, CancellationToken cancellation)
        {
            IEnumerable <object> events;

            using (var scope = _serviceProvider.CreateScope())
            {
                var storageEngine    = scope.ServiceProvider.GetRequiredService <IEntityStorageEngine>();
                var settingsResolver = scope.ServiceProvider.GetRequiredService <ISerializerSettingsResolver>();
                var jsonSerializer   = JsonSerializer.Create(settingsResolver.ResolveSettings(storageEngine));

                object Deserialize(byte[] data)
                {
                    if (data == null)
                    {
                        return(null);
                    }

                    var str = CompressionHelper.Unzip(data);

                    using (var textReader = new StringReader(str))
                    {
                        return(jsonSerializer.Deserialize(textReader, typeof(object)));
                    }
                }

                // We need to evaluate the enumerable here, to ensure that the Deserialize method is not called outside the scope.
                events = commit.Events.Select(p => Deserialize(p.Body as byte[])).ToList();
            }

            var dispatchResults = await ValueTaskHelper.WhenAll(events.Select(p => DispatchEventAsync(p, cancellation)), preserveOrder : false);

            var dispatchResult = new AggregateDispatchResult(dispatchResults);

            if (!dispatchResult.IsSuccess)
            {
                _logger?.LogWarning($"Dispatching commit {commit.Headers[EntityStorageEngine.ConcurrencyTokenHeaderKey]} of stream {commit.StreamId} failed for reason: {dispatchResult.Message}.");
            }

            return(dispatchResult.IsSuccess);
        }
コード例 #6
0
        public async ValueTask Handshake(CancellationToken cancellationToken = default)
        {
            ProfileMessage myProfileMessage;
            ProfileMessage?otherProfileMessage = null;
            {
                {
                    var sessionId = new byte[32];
                    using (var randomNumberGenerator = RandomNumberGenerator.Create())
                    {
                        randomNumberGenerator.GetBytes(sessionId);
                    }

                    myProfileMessage = new ProfileMessage(
                        sessionId,
                        (_passwords.Count == 0) ? AuthenticationType.None : AuthenticationType.Password,
                        new[] { KeyExchangeAlgorithm.EcDh_P521_Sha2_256 },
                        new[] { KeyDerivationAlgorithm.Pbkdf2 },
                        new[] { CryptoAlgorithm.Aes_Gcm_256 },
                        new[] { HashAlgorithm.Sha2_256 });
                }

                var enqueueTask = _connection.EnqueueAsync((bufferWriter) => myProfileMessage.Export(bufferWriter, _bytesPool), cancellationToken);
                var dequeueTask = _connection.DequeueAsync((sequence) => otherProfileMessage = ProfileMessage.Import(sequence, _bytesPool), cancellationToken);

                await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

                if (otherProfileMessage is null)
                {
                    throw new NullReferenceException();
                }
                if (myProfileMessage.AuthenticationType != otherProfileMessage.AuthenticationType)
                {
                    throw new OmniSecureConnectionException("AuthenticationType does not match.");
                }
            }

            var keyExchangeAlgorithm   = GetOverlapMaxEnum(myProfileMessage.KeyExchangeAlgorithms, otherProfileMessage.KeyExchangeAlgorithms);
            var keyDerivationAlgorithm = GetOverlapMaxEnum(myProfileMessage.KeyDerivationAlgorithms, otherProfileMessage.KeyDerivationAlgorithms);
            var cryptoAlgorithm        = GetOverlapMaxEnum(myProfileMessage.CryptoAlgorithms, otherProfileMessage.CryptoAlgorithms);
            var hashAlgorithm          = GetOverlapMaxEnum(myProfileMessage.HashAlgorithms, otherProfileMessage.HashAlgorithms);

            if (!EnumHelper.IsValid(keyExchangeAlgorithm))
            {
                throw new OmniSecureConnectionException("key exchange algorithm does not match.");
            }
            if (!EnumHelper.IsValid(keyDerivationAlgorithm))
            {
                throw new OmniSecureConnectionException("key derivation algorithm does not match.");
            }
            if (!EnumHelper.IsValid(cryptoAlgorithm))
            {
                throw new OmniSecureConnectionException("Crypto algorithm does not match.");
            }
            if (!EnumHelper.IsValid(hashAlgorithm))
            {
                throw new OmniSecureConnectionException("Hash algorithm does not match.");
            }

            ReadOnlyMemory <byte> secret = null;

            if (keyExchangeAlgorithm.HasFlag(KeyExchangeAlgorithm.EcDh_P521_Sha2_256))
            {
                var myAgreement = OmniAgreement.Create(OmniAgreementAlgorithmType.EcDh_P521_Sha2_256);

                OmniAgreementPrivateKey myAgreementPrivateKey;
                OmniAgreementPublicKey? otherAgreementPublicKey = null;
                {
                    {
                        myAgreementPrivateKey = myAgreement.GetOmniAgreementPrivateKey();

                        var enqueueTask = _connection.EnqueueAsync((bufferWriter) => myAgreement.GetOmniAgreementPublicKey().Export(bufferWriter, _bytesPool), cancellationToken);
                        var dequeueTask = _connection.DequeueAsync((sequence) => otherAgreementPublicKey = OmniAgreementPublicKey.Import(sequence, _bytesPool), cancellationToken);

                        await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

                        if (otherAgreementPublicKey is null)
                        {
                            throw new NullReferenceException();
                        }
                        if ((DateTime.UtcNow - otherAgreementPublicKey.CreationTime.ToDateTime()).TotalMinutes > 30)
                        {
                            throw new OmniSecureConnectionException("Agreement public key has Expired.");
                        }
                    }

                    if (_passwords.Count > 0)
                    {
                        AuthenticationMessage myAuthenticationMessage;
                        AuthenticationMessage?otherAuthenticationMessage = null;
                        {
                            {
                                var myHashAndPasswordList = this.GetHashes(myProfileMessage, myAgreement.GetOmniAgreementPublicKey(), hashAlgorithm).ToList();

                                _random.Shuffle(myHashAndPasswordList);
                                myAuthenticationMessage = new AuthenticationMessage(myHashAndPasswordList.Select(n => n.Item1).ToArray());
                            }

                            var enqueueTask = _connection.EnqueueAsync((bufferWriter) => myAuthenticationMessage.Export(bufferWriter, _bytesPool), cancellationToken);
                            var dequeueTask = _connection.DequeueAsync((sequence) => otherAuthenticationMessage = AuthenticationMessage.Import(sequence, _bytesPool), cancellationToken);

                            await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

                            if (otherAuthenticationMessage is null)
                            {
                                throw new NullReferenceException();
                            }

                            var matchedPasswords = new List <string>();
                            {
                                var equalityComparer = new CustomEqualityComparer <ReadOnlyMemory <byte> >((x, y) => BytesOperations.Equals(x.Span, y.Span), (x) => Fnv1_32.ComputeHash(x.Span));
                                var receiveHashes    = new HashSet <ReadOnlyMemory <byte> >(otherAuthenticationMessage.Hashes, equalityComparer);

                                foreach (var(hash, password) in this.GetHashes(otherProfileMessage, otherAgreementPublicKey, hashAlgorithm))
                                {
                                    if (receiveHashes.Contains(hash))
                                    {
                                        matchedPasswords.Add(password);
                                    }
                                }
                            }

                            if (matchedPasswords.Count == 0)
                            {
                                throw new OmniSecureConnectionException("Password does not match.");
                            }

                            _matchedPasswords = matchedPasswords.ToArray();
                        }
                    }
                }

                if (hashAlgorithm.HasFlag(HashAlgorithm.Sha2_256))
                {
                    secret = OmniAgreement.GetSecret(otherAgreementPublicKey, myAgreementPrivateKey);
                }
            }

            byte[] myCryptoKey;
            byte[] otherCryptoKey;
            byte[] myNonce;
            byte[] otherNonce;

            if (keyDerivationAlgorithm.HasFlag(KeyDerivationAlgorithm.Pbkdf2))
            {
                byte[] xorSessionId = new byte[Math.Max(myProfileMessage.SessionId.Length, otherProfileMessage.SessionId.Length)];
                BytesOperations.Xor(myProfileMessage.SessionId.Span, otherProfileMessage.SessionId.Span, xorSessionId);

                int cryptoKeyLength = 0;
                int nonceLength     = 0;

                if (cryptoAlgorithm.HasFlag(CryptoAlgorithm.Aes_Gcm_256))
                {
                    cryptoKeyLength = 32;
                    nonceLength     = 12;
                }

                myCryptoKey    = new byte[cryptoKeyLength];
                otherCryptoKey = new byte[cryptoKeyLength];
                myNonce        = new byte[nonceLength];
                otherNonce     = new byte[nonceLength];

                var kdfResult = new byte[(cryptoKeyLength + nonceLength) * 2];

                if (hashAlgorithm.HasFlag(HashAlgorithm.Sha2_256))
                {
                    Pbkdf2_Sha2_256.TryComputeHash(secret.Span, xorSessionId, 1024, kdfResult);
                }

                using (var stream = new MemoryStream(kdfResult))
                {
                    if (_type == OmniSecureConnectionType.Connected)
                    {
                        stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                        stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                        stream.Read(myNonce, 0, myNonce.Length);
                        stream.Read(otherNonce, 0, otherNonce.Length);
                    }
                    else if (_type == OmniSecureConnectionType.Accepted)
                    {
                        stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                        stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                        stream.Read(otherNonce, 0, otherNonce.Length);
                        stream.Read(myNonce, 0, myNonce.Length);
                    }
                }
            }
            else
            {
                throw new NotSupportedException(nameof(keyDerivationAlgorithm));
            }

            _state = new State(cryptoAlgorithm, hashAlgorithm, myCryptoKey, otherCryptoKey, myNonce, otherNonce);
        }