private static string ValidateAndDecryptWithMasterKey(byte[] rsaEncAesKeyNonceBytes, byte[] authEncryptedBytes)
        {
            var aesKeyNonceBytes = RsaUtils.Decrypt(rsaEncAesKeyNonceBytes, SecureConfig.PrivateKeyXml);

            var aesKey = new byte[AesUtils.KeySizeBytes];
            var iv     = new byte[AesUtils.BlockSizeBytes];

            Buffer.BlockCopy(aesKeyNonceBytes, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(aesKeyNonceBytes, iv.Length, aesKey, 0, aesKey.Length);

            var sha512HashBytes = aesKey.ToSha512HashBytes();
            var cryptKey        = new byte[sha512HashBytes.Length / 2];
            var authKey         = new byte[sha512HashBytes.Length / 2];

            Buffer.BlockCopy(sha512HashBytes, 0, cryptKey, 0, cryptKey.Length);
            Buffer.BlockCopy(sha512HashBytes, cryptKey.Length, authKey, 0, authKey.Length);

            if (!HmacUtils.Verify(authEncryptedBytes, authKey))
            {
                throw new Exception("Verification Failed");
            }

            var msgBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);

            var json = msgBytes.FromUtf8Bytes();

            return(json);
        }
        private static string ValidateAndDecrypt(byte[] authRsaEncCryptKey, byte[] authEncryptedBytes)
        {
            byte[]    iv        = new byte[AesUtils.BlockSizeBytes];
            const int tagLength = HmacUtils.KeySizeBytes;

            byte[] rsaEncCryptAuthKeys = new byte[authRsaEncCryptKey.Length - iv.Length - tagLength];

            Buffer.BlockCopy(authRsaEncCryptKey, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(authRsaEncCryptKey, iv.Length, rsaEncCryptAuthKeys, 0, rsaEncCryptAuthKeys.Length);

            var cryptAuthKeys = RsaUtils.Decrypt(rsaEncCryptAuthKeys, SecureConfig.PrivateKeyXml);

            byte[] cryptKey = new byte[AesUtils.KeySizeBytes];
            byte[] authKey  = new byte[AesUtils.KeySizeBytes];

            Buffer.BlockCopy(cryptAuthKeys, 0, cryptKey, 0, cryptKey.Length);
            Buffer.BlockCopy(cryptAuthKeys, cryptKey.Length, authKey, 0, authKey.Length);

            if (!HmacUtils.Verify(authRsaEncCryptKey, authKey))
            {
                throw new Exception("authRsaEncCryptKey is Invalid");
            }

            if (!HmacUtils.Verify(authEncryptedBytes, authKey))
            {
                throw new Exception("authEncryptedBytes is Invalid");
            }

            var msgBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);

            return(msgBytes.FromUtf8Bytes());
        }
        public void Does_throw_on_replayed_messages()
        {
            var client = CreateClient();

            var request = new HelloSecure {
                Name = "World"
            };

            byte[] cryptKey, iv;
            AesUtils.CreateKeyAndIv(out cryptKey, out iv);

            byte[] authKey = AesUtils.CreateKey();

            var cryptAuthKeys = cryptKey.Combine(authKey);

            var rsaEncCryptAuthKeys     = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
            var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

            var timestamp   = DateTime.UtcNow.ToUnixTime();
            var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

            var encryptedBytes     = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
            var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

            var encryptedMessage = new EncryptedMessage
            {
                EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
                EncryptedBody         = Convert.ToBase64String(authEncryptedBytes),
            };

            var encResponse = client.Post(encryptedMessage);

            try
            {
                client.Post(encryptedMessage);

                Assert.Fail("Should throw");
            }
            catch (WebServiceException ex)
            {
                ex.StatusDescription.Print();

                var errorResponse = (EncryptedMessageResponse)ex.ResponseDto;

                authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody);
                if (!HmacUtils.Verify(authEncryptedBytes, authKey))
                {
                    throw new Exception("EncryptedBody is Invalid");
                }

                var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);
                var responseJson  = responseBytes.FromUtf8Bytes();
                var response      = responseJson.FromJson <ErrorResponse>();
                Assert.That(response.ResponseStatus.Message, Is.EqualTo("Nonce already seen"));
            }
        }
        public void Can_Send_Encrypted_Message()
        {
            var client = CreateClient();

            var request = new HelloSecure {
                Name = "World"
            };

            byte[] cryptKey, authKey, iv;
            AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv);

            var cryptAuthKeys = cryptKey.Combine(authKey);

            var rsaEncCryptAuthKeys     = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
            var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

            var timestamp   = DateTime.UtcNow.ToUnixTime();
            var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

            var encryptedBytes     = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
            var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

            var encryptedMessage = new EncryptedMessage
            {
                EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
                EncryptedBody         = Convert.ToBase64String(authEncryptedBytes),
            };

            var encResponse = client.Post(encryptedMessage);

            authEncryptedBytes = Convert.FromBase64String(encResponse.EncryptedBody);

            if (!HmacUtils.Verify(authEncryptedBytes, authKey))
            {
                throw new Exception("Invalid EncryptedBody");
            }

            var decryptedBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);

            var responseJson = decryptedBytes.FromUtf8Bytes();
            var response     = responseJson.FromJson <HelloSecureResponse>();

            Assert.That(response.Result, Is.EqualTo("Hello, World!"));
        }