コード例 #1
0
ファイル: Messages.generated.cs プロジェクト: lulzzz/omnix
            public VerificationMessage Deserialize(Omnix.Serialization.RocketPack.RocketPackReader r, int rank)
            {
                if (rank > 256)
                {
                    throw new System.FormatException();
                }

                // Read property count
                uint propertyCount = r.GetUInt32();

                ProfileMessage         p_profileMessage     = ProfileMessage.Empty;
                OmniAgreementPublicKey p_agreementPublicKey = OmniAgreementPublicKey.Empty;

                for (; propertyCount > 0; propertyCount--)
                {
                    uint id = r.GetUInt32();
                    switch (id)
                    {
                    case 0:     // ProfileMessage
                    {
                        p_profileMessage = ProfileMessage.Formatter.Deserialize(r, rank + 1);
                        break;
                    }

                    case 1:     // AgreementPublicKey
                    {
                        p_agreementPublicKey = OmniAgreementPublicKey.Formatter.Deserialize(r, rank + 1);
                        break;
                    }
                    }
                }

                return(new VerificationMessage(p_profileMessage, p_agreementPublicKey));
            }
コード例 #2
0
ファイル: OmniSecureConnection.cs プロジェクト: lulzzz/omnix
        private IEnumerable <(ReadOnlyMemory <byte>, string)> GetHashesV1(V1.Internal.ProfileMessage profileMessage, OmniAgreementPublicKey agreementPublicKey, V1.Internal.HashAlgorithm hashAlgorithm)
        {
            var results = new Dictionary <ReadOnlyMemory <byte>, string>();

            byte[] verificationMessageHash;
            {
                var verificationMessage = new V1.Internal.VerificationMessage(profileMessage, agreementPublicKey);

                if (hashAlgorithm == V1.Internal.HashAlgorithm.Sha2_256)
                {
                    var hub = new Hub();

                    verificationMessage.Export(hub.Writer, _bufferPool);
                    verificationMessageHash = Sha2_256.ComputeHash(hub.Reader.GetSequence());
                }
                else
                {
                    throw new NotSupportedException(nameof(hashAlgorithm));
                }
            }

            foreach (var password in _passwords)
            {
                if (hashAlgorithm.HasFlag(V1.Internal.HashAlgorithm.Sha2_256))
                {
                    results.Add(Hmac_Sha2_256.ComputeHash(verificationMessageHash, Sha2_256.ComputeHash(password)), password);
                }
            }

            return(results.Select(item => (item.Key, item.Value)));
        }
コード例 #3
0
ファイル: Messages.generated.cs プロジェクト: lulzzz/omnix
        public VerificationMessage(ProfileMessage profileMessage, OmniAgreementPublicKey agreementPublicKey)
        {
            if (profileMessage is null)
            {
                throw new System.ArgumentNullException("profileMessage");
            }
            if (agreementPublicKey is null)
            {
                throw new System.ArgumentNullException("agreementPublicKey");
            }

            this.ProfileMessage     = profileMessage;
            this.AgreementPublicKey = agreementPublicKey;

            {
                var __h = new System.HashCode();
                if (this.ProfileMessage != default)
                {
                    __h.Add(this.ProfileMessage.GetHashCode());
                }
                if (this.AgreementPublicKey != default)
                {
                    __h.Add(this.AgreementPublicKey.GetHashCode());
                }
                __hashCode = __h.ToHashCode();
            }
        }
コード例 #4
0
ファイル: OmniSecureConnection.cs プロジェクト: lulzzz/omnix
        private async ValueTask HandshakeV1(IConnection connection, CancellationToken token)
        {
            V1.Internal.ProfileMessage myProfileMessage;
            V1.Internal.ProfileMessage?otherProfileMessage = null;
            {
                {
                    var sessionId = new byte[32];
                    _random.GetBytes(sessionId);

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

                var enqueueTask = connection.EnqueueAsync((bufferWriter) => myProfileMessage.Export(bufferWriter, _bufferPool), token);
                var dequeueTask = connection.DequeueAsync((sequence) => otherProfileMessage = V1.Internal.ProfileMessage.Import(sequence, _bufferPool), token);

                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(V1.Internal.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, _bufferPool), token);
                        var dequeueTask = connection.DequeueAsync((sequence) => otherAgreementPublicKey = OmniAgreementPublicKey.Import(sequence, _bufferPool), token);

                        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)
                    {
                        V1.Internal.AuthenticationMessage myAuthenticationMessage;
                        V1.Internal.AuthenticationMessage?otherAuthenticationMessage = null;
                        {
                            {
                                var myHashAndPasswordList = this.GetHashesV1(myProfileMessage, myAgreement.GetOmniAgreementPublicKey(), hashAlgorithm).ToList();

                                RandomProvider.GetThreadRandom().Shuffle(myHashAndPasswordList);
                                myAuthenticationMessage = new V1.Internal.AuthenticationMessage(myHashAndPasswordList.Select(n => n.Item1).ToArray());
                            }

                            var enqueueTask = connection.EnqueueAsync((bufferWriter) => myAuthenticationMessage.Export(bufferWriter, _bufferPool), token);
                            var dequeueTask = connection.DequeueAsync((sequence) => otherAuthenticationMessage = V1.Internal.AuthenticationMessage.Import(sequence, _bufferPool), token);

                            await ValueTaskHelper.WhenAll(enqueueTask, dequeueTask);

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

                            var matchedPasswords = new List <string>();
                            {
                                var equalityComparer = new GenericEqualityComparer <ReadOnlyMemory <byte> >((x, y) => BytesOperations.SequenceEqual(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.GetHashesV1(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(V1.Internal.HashAlgorithm.Sha2_256))
                {
                    secret = OmniAgreement.GetSecret(otherAgreementPublicKey, myAgreementPrivateKey);
                }
            }

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

            if (keyDerivationAlgorithm.HasFlag(V1.Internal.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 hmacKeyLength   = 0;

                if (cryptoAlgorithm.HasFlag(V1.Internal.CryptoAlgorithm.Aes_256))
                {
                    cryptoKeyLength = 32;
                }

                if (hashAlgorithm.HasFlag(V1.Internal.HashAlgorithm.Sha2_256))
                {
                    hmacKeyLength = 32;
                }

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

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

                if (hashAlgorithm.HasFlag(V1.Internal.HashAlgorithm.Sha2_256))
                {
                    Pbkdf2_Sha2_256.TryComputeHash(secret.Span, xorSessionId, 1024, kdfResult);
                }
                else
                {
                    throw new NotSupportedException(nameof(keyDerivationAlgorithm));
                }

                using (var stream = new MemoryStream(kdfResult))
                {
                    if (_type == OmniSecureConnectionType.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 == OmniSecureConnectionType.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 NotSupportedException(nameof(keyDerivationAlgorithm));
            }

            _infoV1 = new InfoV1(cryptoAlgorithm, hashAlgorithm, myCryptoKey, otherCryptoKey, myHmacKey, otherHmacKey);
        }