Пример #1
0
 public void RotateSendKey()
 {
     (byte[] newChainingKey, byte[] newSendKey) = HmacSha256.ComputeHashes(ChainingKey, SendEncryptionKey);
     ChainingKey       = newChainingKey;
     SendEncryptionKey = newSendKey;
     SendNonce.Reset();
 }
Пример #2
0
        void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result)
        {
            if (result.IsEmpty())
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                CloseSocket();
                return;
            }

            ConnectToKey key = new ConnectToKey();

            _key = key.Raw = authSession.Key;

            uint   accountId = key.AccountId;
            string login     = result.Read <string>(0);

            _sessionKey = result.Read <string>(1).ToByteArray();

            HmacSha256 hmac = new HmacSha256(_sessionKey);

            hmac.Process(BitConverter.GetBytes(authSession.Key), 8);
            hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length);
            hmac.Process(_serverChallenge, 16);
            hmac.Finish(ContinuedSessionSeed, 16);

            if (!hmac.Digest.Compare(authSession.Digest))
            {
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthContinuedSession: Authentication failed for account: {0} ('{1}') address: {2}", accountId, login, GetRemoteIpAddress());
                CloseSocket();
                return;
            }

            SendPacket(new EnableEncryption());
        }
Пример #3
0
 public void RotateReceiveKey()
 {
     (byte[] newChainingKey, byte[] newReceiveKey) = HmacSha256.ComputeHashes(ChainingKey, ReceiveDecryptionKey);
     ChainingKey          = newChainingKey;
     ReceiveDecryptionKey = newReceiveKey;
     ReceiveNonce.Reset();
 }
Пример #4
0
        private static byte[] HKDF(byte[] salt, byte[] prk, byte[] info, int length)
        {
            var hmac = new HmacSha256(salt);
            var key  = hmac.ComputeHash(prk);

            return(HKDFSecondStep(key, info, length));
        }
Пример #5
0
 /// <summary>
 /// <see cref="IDisposable.Dispose"/>
 /// </summary>
 public void Dispose()
 {
     if (!(this.algorithm is null))
     {
         this.algorithm.Dispose();
         this.algorithm = null;
     }
 }
Пример #6
0
 /// <summary>
 /// <see cref="IDisposable.Dispose"/>
 /// </summary>
 public void Dispose()
 {
     if (this.algorithm != null)
     {
         this.algorithm.Dispose();
         this.algorithm = null;
     }
 }
Пример #7
0
        public void Constructor_ExceptionTest()
        {
            Assert.Throws <ArgumentNullException>(() => new HmacSha256(null));

            HmacSha256 hmac = new HmacSha256();

            Assert.Throws <ArgumentNullException>(() => hmac.Key = null);
        }
Пример #8
0
        public void ComputeHash_Empty_WithKey_Test(byte[] key, byte[] data)
        {
            using var sysHmac = new System.Security.Cryptography.HMACSHA256(key);
            byte[] expected = sysHmac.ComputeHash(data);

            using HmacSha256 hmac = new HmacSha256();
            byte[] actual = hmac.ComputeHash(data, key);
            Assert.Equal(expected, actual);
        }
Пример #9
0
        public override void Write()
        {
            HmacSha256 hash = new HmacSha256(EncryptionKey);

            hash.Process(BitConverter.GetBytes(Enabled), 1);
            hash.Finish(EnableEncryptionSeed, 16);

            _worldPacket.WriteBytes(RsaCrypt.RSA.SignHash(hash.Digest, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1).Reverse().ToArray());
            _worldPacket.WriteBit(Enabled);
            _worldPacket.FlushBits();
        }
Пример #10
0
        public static void Properties()
        {
            var a = new HmacSha256();

            Assert.Equal(32, a.MinKeySize);
            Assert.Equal(32, a.DefaultKeySize);
            Assert.Equal(int.MaxValue, a.MaxKeySize);

            Assert.Equal(16, a.MinMacSize);
            Assert.Equal(32, a.DefaultMacSize);
            Assert.Equal(32, a.MaxMacSize);
        }
Пример #11
0
 public void ComputeHash_NIST_CtorKey_Test(byte[] msg, byte[] key, byte[] expected, int len, bool truncate)
 {
     using HmacSha256 hmac = new HmacSha256(key);
     byte[] actual = hmac.ComputeHash(msg);
     if (truncate)
     {
         byte[] temp = new byte[len];
         Buffer.BlockCopy(actual, 0, temp, 0, len);
         actual = temp;
     }
     Assert.Equal(expected, actual);
 }
Пример #12
0
        private static byte[] HKDFSecondStep(byte[] key, byte[] info, int length)
        {
            var hmac       = new HmacSha256(key);
            var infoAndOne = info.Concat(new byte[] { 0x01 }).ToArray();
            var result     = hmac.ComputeHash(infoAndOne);

            if (result.Length > length)
            {
                Array.Resize(ref result, length);
            }

            return(result);
        }
        public static String GetSASToken(String baseAddress, String SASKeyName, String SASKeyValue)
        {
            TimeSpan fromEpochStart = DateTime.UtcNow - new DateTime(1970, 1, 1);
            String   expiry         = Convert.ToString((Int32)fromEpochStart.TotalSeconds + 3600);
            String   stringToSign   = WebUtility.UrlEncode(baseAddress) + "\n" + expiry;

            HmacSha256 hmac      = new HmacSha256(Encoding.UTF8.GetBytes(SASKeyValue));
            String     signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

            String sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", WebUtility.UrlEncode(baseAddress), WebUtility.UrlEncode(signature), expiry, SASKeyName);

            return(sasToken);
        }
Пример #14
0
        /// <inheritdoc/>
        public void Dispose()
        {
            if (!isDisposed)
            {
                if (!(HmacK is null))
                {
                    HmacK.Dispose();
                }
                HmacK = null;

                isDisposed = true;
            }
        }
Пример #15
0
        public void GenerateHashesTest()
        {
            String salt = "2640f52eebcd9e882958951c794250eedb28002c05d7dc2ea0f195406042caf1";
            String data = "1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3";

            (byte[] output1, byte[] output2) = HmacSha256.ComputeHashes(salt.HexToByteArray(), data.HexToByteArray());

            String output1Expected = "b61ec1191326fa240decc9564369dbb3ae2b34341d1e11ad64ed89f89180582f";
            String output2Expected = "e68f69b7f096d7917245f5e5cf8ae1595febe4d4644333c99f9c4a1282031c9f";

            Assert.Equal(output1Expected, output1.ToHex());
            Assert.Equal(output2Expected, output2.ToHex());
        }
Пример #16
0
        public void ComputeHash_WithKey_ExceptionTest()
        {
            HmacSha256 hmac = new HmacSha256();

            Exception ex = Assert.Throws <ArgumentNullException>(() => hmac.ComputeHash(null, new byte[1]));

            Assert.Contains("Data can not be null", ex.Message);

            ex = Assert.Throws <ArgumentNullException>(() => hmac.ComputeHash(new byte[1], null));
            Assert.Contains("Key can not be null", ex.Message);

            hmac.Dispose();
            ex = Assert.Throws <ObjectDisposedException>(() => hmac.ComputeHash(new byte[1], new byte[1]));
        }
Пример #17
0
        public static void Test(string key, string msg, string mac)
        {
            var a = new HmacSha256();

            using (var k = Key.Import(a, key.DecodeHex(), KeyBlobFormat.RawSymmetricKey))
            {
                var m = msg.DecodeHex();

                var expected = mac.DecodeHex();
                var actual   = a.Sign(k, m, expected.Length);

                Assert.Equal(expected, actual);
                Assert.True(a.TryVerify(k, m, expected));
            }
        }
Пример #18
0
        /// <summary>
        /// This method handles when the user press the Register button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async void btnRegister_Clicked(object sender, EventArgs e)
        {
            Activity.IsRunning = true;
            //We check if fields are entered properly
            if (String.IsNullOrEmpty(email.Text) && String.IsNullOrEmpty(username.Text) && String.IsNullOrEmpty(password.Text))
            {
                await DisplayAlert("Oops", "Please fill in the fields", "OK");
            }
            //We are using EmailValidatorBehavior to check if the email entered is correct using Regex [changes to red when wrong]
            //Display Alert if email is wrong
            else if (email.TextColor == Color.Red)
            {
                await DisplayAlert("Oops", "Invalid Email address", "OK");
            }
            else
            {
                //Initialising........Storing text/data from the Entry fields
                string newEmail = email.Text;
                string newUser  = username.Text;

                //Initailizing data to begin our HmacSHA256 encryption on the password
                //Our private key
                byte[] shaKey = Encoding.UTF8.GetBytes("test");
                //Encode password....
                //We first have to convert password to byte format
                byte[] newPassword = Encoding.UTF8.GetBytes(password.Text);
                //Encode password to sha256
                HmacSha256 newHash256      = new HmacSha256(newPassword);
                byte[]     newHashPassword = newHash256.ComputeHash(newPassword);
                //Read our password as a string this allows us to add it to our JSON file
                string newStringHashPassword = BitConverter.ToString(newHashPassword);

                //Creates a new user object and uses the data from the user and creates a JSON formatted data structure
                User NewUser = User.CreateUserFromJson("{\"Username\":\"" + newUser + "\", \"Email\":\"" + newEmail + "\", \"Password\":\"" + newStringHashPassword + "\"}");

                /* Passes NewUser object with our JSON format to the RegisterJson object
                 * RegisterJson object contains the method Save() which contacts the server
                 */
                ServerJson userjson = new ServerJson();
                userjson.Save(NewUser);

                //Registration finished pop up
                await DisplayAlert("Alert", "User Registered", "OK");

                await Navigation.PushModalAsync(new LoginPage());
            }
            Activity.IsRunning = false;
        }
Пример #19
0
        /// <summary>
        /// Releases the resources used by the <see cref="Rfc6979"/> class.
        /// </summary>
        /// <param name="disposing">
        /// True to release both managed and unmanaged resources; false to release only unmanaged resources.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (!isDisposed)
            {
                if (disposing)
                {
                    if (!(HmacK is null))
                    {
                        HmacK.Dispose();
                    }
                    HmacK = null;
                }

                isDisposed = true;
            }
        }
Пример #20
0
        public void ComputeHash_Reuse_Test(byte[] key1, byte[] data1_1, byte[] exp1_1, byte[] data1_2, byte[] exp1_2,
                                           byte[] key2, byte[] data2_1, byte[] exp2_1, byte[] data2_2, byte[] exp2_2)
        {
            using HmacSha256 hmac = new HmacSha256();
            byte[] actual1_1 = hmac.ComputeHash(data1_1, key1);
            Assert.Equal(exp1_1, actual1_1);

            byte[] actual2_1 = hmac.ComputeHash(data2_1, key2); // use different key on each call
            Assert.Equal(exp2_1, actual2_1);

            byte[] actual1_2 = hmac.ComputeHash(data1_2, key1);
            Assert.Equal(exp1_2, actual1_2);

            byte[] actual2_2 = hmac.ComputeHash(data2_2, key2);
            Assert.Equal(exp2_2, actual2_2);
        }
Пример #21
0
        /// <summary>
        /// This method handles when the users press the login button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async void btnLogin_Clicked(object sender, EventArgs e)
        {
            //Acitvity indicator
            Activity.IsRunning = true;
            ServerJson checkUser = new ServerJson();

            //Checking for empty fields
            Debug.WriteLine("Check for Empty fields");
            if (String.IsNullOrWhiteSpace(username.Text) || (String.IsNullOrWhiteSpace(password.Text)))
            {
                await DisplayAlert("Oops", "Please fill in the fields", "OK");
            }
            else
            {
                //Initailizing data to begin our HmacSHA256 encryption on the password
                //Our private key
                byte[] shaKey = Encoding.UTF8.GetBytes("test");
                //Encode password....
                //We first have to convert password to byte format
                byte[] newPassword = Encoding.UTF8.GetBytes(password.Text);
                //Encode password to sha256
                HmacSha256 newHash256      = new HmacSha256(newPassword);
                byte[]     newHashPassword = newHash256.ComputeHash(newPassword);
                //Read our password as a string this allows us to add it to our JSON file
                string newStringHashPassword = BitConverter.ToString(newHashPassword);

                //Check if user password and username match Method is called in ServerJson.cs
                Debug.WriteLine("Check true of false for matching username and password");
                bool result = await checkUser.CheckUserPasswordAsync(username.Text, newStringHashPassword);

                if (result == true)
                {
                    //If result is true we log the user in and store it's username in data
                    Application.Current.Properties["LoggedInUser"] = username.Text;
                    await Application.Current.SavePropertiesAsync();

                    //Push user to mainpage after login
                    await Navigation.PushModalAsync(new MainPage());
                }
                if (result == false)
                {
                    await DisplayAlert("Oops", "Invalid Login Credentials", "Ok");
                }
            }
            Activity.IsRunning = false;
        }
Пример #22
0
        public void ComputeHash_CtorKey_ReuseTest(byte[] key1, byte[] data1_1, byte[] exp1_1, byte[] data1_2, byte[] exp1_2,
                                                  byte[] key2, byte[] data2_1, byte[] exp2_1, byte[] data2_2, byte[] exp2_2)
        {
            using HmacSha256 hmac = new HmacSha256(key1);
            byte[] actual1_1 = hmac.ComputeHash(data1_1);
            Assert.Equal(exp1_1, actual1_1);

            byte[] actual1_2 = hmac.ComputeHash(data1_2);
            Assert.Equal(exp1_2, actual1_2);

            // change key
            hmac.Key = key2;
            byte[] actual2_1 = hmac.ComputeHash(data2_1);
            Assert.Equal(exp2_1, actual2_1);

            byte[] actual2_2 = hmac.ComputeHash(data2_2);
            Assert.Equal(exp2_2, actual2_2);
        }
Пример #23
0
        public static void Properties()
        {
            var a = new HmacSha256();

            Assert.Equal(32, HmacSha256.MinKeySize);
            Assert.Equal(32, HmacSha256.MaxKeySize);
            Assert.Equal(16, HmacSha256.MinMacSize);
            Assert.Equal(32, HmacSha256.MaxMacSize);

            Assert.Equal(32, a.KeySize);
            Assert.Equal(32, a.MacSize);

            Assert.Equal(32, MacAlgorithm.HmacSha256_128.KeySize);
            Assert.Equal(16, MacAlgorithm.HmacSha256_128.MacSize);

            Assert.Equal(32, MacAlgorithm.HmacSha256.KeySize);
            Assert.Equal(32, MacAlgorithm.HmacSha256.MacSize);
        }
Пример #24
0
        public void ComputeHash_ExceptionTest()
        {
            HmacSha256 hmac = new HmacSha256();

            Exception ex = Assert.Throws <ArgumentNullException>(() => hmac.ComputeHash(null));

            Assert.Contains("Data can not be null", ex.Message);

            ex = Assert.Throws <ArgumentNullException>(() => hmac.ComputeHash(new byte[1]));
            Assert.Contains("Key must be set before calling this function", ex.Message);

            hmac.Key = new byte[1];
            ex       = Assert.Throws <ArgumentNullException>(() => hmac.ComputeHash(null));
            Assert.Contains("Data can not be null", ex.Message);

            hmac.Dispose();
            ex = Assert.Throws <ObjectDisposedException>(() => hmac.ComputeHash(new byte[1]));
        }
Пример #25
0
        void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result)
        {
            if (result.IsEmpty())
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                CloseSocket();
                return;
            }

            ConnectToKey key = new ConnectToKey();

            _key = key.Raw = authSession.Key;

            uint   accountId = key.AccountId;
            string login     = result.Read <string>(0);

            _sessionKey = result.Read <byte[]>(1);

            HmacSha256 hmac = new HmacSha256(_sessionKey);

            hmac.Process(BitConverter.GetBytes(authSession.Key), 8);
            hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length);
            hmac.Process(_serverChallenge, 16);
            hmac.Finish(ContinuedSessionSeed, 16);

            if (!hmac.Digest.Compare(authSession.Digest))
            {
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthContinuedSession: Authentication failed for account: {0} ('{1}') address: {2}", accountId, login, GetRemoteIpAddress());
                CloseSocket();
                return;
            }

            HmacSha256 encryptKeyGen = new HmacSha256(_sessionKey);

            encryptKeyGen.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length);
            encryptKeyGen.Process(_serverChallenge, 16);
            encryptKeyGen.Finish(EncryptionKeySeed, 16);

            // only first 16 bytes of the hmac are used
            Buffer.BlockCopy(encryptKeyGen.Digest, 0, _encryptKey, 0, 16);

            SendPacket(new EnterEncryptedMode(_encryptKey, true));
            AsyncRead();
        }
Пример #26
0
        /// <summary>
        /// Encrypts a message with this public key using Elliptic Curve Integrated Encryption Scheme (ECIES)
        /// with AES-128-CBC as cipher and HMAC-SHA256 as MAC.
        /// </summary>
        /// <exception cref="ArgumentNullException"/>
        /// <param name="message">Message to encrypt</param>
        /// <param name="magic">
        /// [Default value = BIE1]
        /// A magic string added to encrypted result before computing its HMAC-SHA256
        /// </param>
        /// <returns>Encrypted result as a base-64 encoded string</returns>
        public string Encrypt(string message, string magic = "BIE1")
        {
            if (message is null)
            {
                throw new ArgumentNullException(nameof(message), "Mesage can not be null.");
            }
            if (magic is null)
            {
                throw new ArgumentNullException(nameof(magic), "Magic can not be null.");
            }

            byte[] magicBytes = Encoding.UTF8.GetBytes(magic);

            // TODO: investigate if this can become deterministic (it can't be based on message or pubkey
            //       otherwise the ephemeral key is revealed)
            using SharpRandom rng      = new SharpRandom();
            using PrivateKey ephemeral = new PrivateKey(rng);

            byte[] ecdhKey = new PublicKey(calc.Multiply(ephemeral.ToBigInt(), point)).ToByteArray(true);
            using Sha512 sha512 = new Sha512();
            byte[] key = sha512.ComputeHash(ecdhKey);

            using Aes aes = new AesManaged
                  {
                      KeySize = 128,
                      Key     = key.SubArray(16, 16),
                      Mode    = CipherMode.CBC,
                      IV      = key.SubArray(0, 16),
                      Padding = PaddingMode.PKCS7
                  };
            using ICryptoTransform encryptor = aes.CreateEncryptor();
            using MemoryStream encStream     = new MemoryStream();
            using CryptoStream cryptStream   = new CryptoStream(encStream, encryptor, CryptoStreamMode.Write);
            using (StreamWriter swEncrypt = new StreamWriter(cryptStream))
            {
                swEncrypt.Write(message);
            }

            byte[] encrypted = magicBytes.ConcatFast(ephemeral.ToPublicKey().ToByteArray(true)).ConcatFast(encStream.ToArray());
            using HmacSha256 hmac = new HmacSha256();
            byte[] mac = hmac.ComputeHash(encrypted, key.SubArray(32));

            return(encrypted.ConcatFast(mac).ToBase64());
        }
Пример #27
0
        public byte[] ApplyActOne(ECKeyPair ephemeralKeyPair = null)
        {
            if (_state.HandshakeState != HandshakeState.Initialized)
            {
                throw new InvalidOperationException($"Invalid handshake state {_state.HandshakeState}. Must be Initialized");
            }

            _state.EphemeralKeyPair = ephemeralKeyPair ?? Secp256K1.GenerateKeyPair();
            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(_state.EphemeralKeyPair.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(_state.RemoteAddress.PublicKey.PublicKeyParameters, _state.EphemeralKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK1) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            _state.ChainingKey = chainingKey;
            (_, byte[] tag)    = ChaCha20Poly1305.EncryptWithAdditionalData(tempK1, _state.SendNonce.GetBytes(), handshakeHash, new byte[0]);
            handshakeHash      = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(tag));

            _state.HandshakeHash  = handshakeHash;
            _state.HandshakeState = HandshakeState.Act1;
            return(ByteExtensions.Combine(new byte[] { 0 }, _state.EphemeralKeyPair.PublicKeyCompressed, tag));
        }
Пример #28
0
        public void Test_HmacSha256()
        {
            // http://tools.ietf.org/html/rfc4868#section-2.7.1
            {
                var key   = NetworkConverter.FromHexString("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
                var value = NetworkConverter.FromHexString("4869205468657265");

                using (MemoryStream stream = new MemoryStream(value))
                {
                    var s = NetworkConverter.ToHexString(HmacSha256.ComputeHash(stream, key));
                }

                using (HMACSHA256 hmacSha256 = new HMACSHA256(key))
                {
                    var s = NetworkConverter.ToHexString(hmacSha256.ComputeHash(value));
                }
            }

            var list = new List <int>();

            list.Add(1);
            list.Add(64);
            list.Add(128);

            byte[] buffer = new byte[1024 * 32];
            _random.NextBytes(buffer);

            for (int i = 0; i < list.Count; i++)
            {
                byte[] key = new byte[list[i]];
                _random.NextBytes(key);

                using (MemoryStream stream1 = new MemoryStream(buffer))
                    using (MemoryStream stream2 = new MemoryStream(buffer))
                    {
                        using (HMACSHA256 hmacSha256 = new HMACSHA256(key))
                        {
                            Assert.IsTrue(Unsafe.Equals(hmacSha256.ComputeHash(stream1), HmacSha256.ComputeHash(stream2, key)));
                        }
                    }
            }
        }
Пример #29
0
        public byte[] ApplyActTwo(ECKeyPair initiatorEphemeralKey, ECKeyPair localEphemeralKey = null)
        {
            if (_state.HandshakeState != HandshakeState.Act1)
            {
                throw new InvalidOperationException($"Invalid Handshake state {_state.HandshakeState}. Must be Act1");
            }

            _state.EphemeralKeyPair = localEphemeralKey ?? Secp256K1.GenerateKeyPair();
            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(_state.EphemeralKeyPair.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(initiatorEphemeralKey.PublicKeyParameters, _state.EphemeralKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK2) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            (_, byte[] tag1) = ChaCha20Poly1305.EncryptWithAdditionalData(tempK2, new byte[12], handshakeHash, new byte[0]);
            handshakeHash    = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(tag1));

            _state.HandshakeHash  = handshakeHash;
            _state.ChainingKey    = chainingKey;
            _state.TempKey2       = tempK2;
            _state.HandshakeState = HandshakeState.Act2;
            return(ByteExtensions.Combine(new byte[] { 0 }, _state.EphemeralKeyPair.PublicKeyCompressed, tag1));
        }
Пример #30
0
        public (byte[] tempK1, ECKeyPair ephemeralKey) ReadActOneRequest(Span <byte> message, int length)
        {
            if (_state.HandshakeState != HandshakeState.Initialized)
            {
                throw new InvalidOperationException($"Invalid handshake state {_state.HandshakeState}. Must be Initialized");
            }

            if (length != 50)
            {
                throw new ArgumentException("ACT1_READ_FAILED");
            }

            byte        version = message.Slice(0, 1)[0];
            ECKeyPair   responderEphemeralKey = new ECKeyPair(message.Slice(1, 33), false);
            Span <byte> c = message.Slice(34, 16);

            if (version != 0)
            {
                throw new NotSupportedException("ACT1_BAD_VERSION");
            }

            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(responderEphemeralKey.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(responderEphemeralKey.PublicKeyParameters, _state.LocalKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK1) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            _state.ChainingKey = chainingKey;

            (_, byte[] mac) = ChaCha20Poly1305.DecryptWithAdditionalData(tempK1, _state.ReceiveNonce.GetBytes(), handshakeHash, new byte[0]);

            if (!c.SequenceEqual(mac))
            {
                throw new ArgumentException("ACT1_BAD_TAG");
            }

            _state.ReceiveNonce.Increment();
            _state.HandshakeHash  = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(c.ToArray()));
            _state.HandshakeState = HandshakeState.Act1;
            return(tempK1, responderEphemeralKey);
        }