예제 #1
0
        private string GenerateToken()
        {
            var password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + ClientKey;
            var token    = AES128.Encrypt(password, SecretKey);

            return(token);
        }
예제 #2
0
        /// <summary>
        /// token issue
        /// </summary>
        /// <param name="data">access token data</param>
        /// <typeparam name="T">type of access token</typeparam>
        /// <returns></returns>
        public static string IssueToken <T>(T data) where T : AccessToken
        {
            string dataString = JsonConvert.SerializeObject(data);
            string token      = AES128.Encrypt(dataString, DefaultKey);

            return(token);
        }
예제 #3
0
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="file"></param>
        /// <param name="curIndex"></param>
        /// <returns></returns>
        private byte[] DealTS(byte[] file, int curIndex)
        {
            //偏移量
            byte[] arrayIv = default;
            if (string.IsNullOrEmpty(aesConf.iv))
            {
                arrayIv = ListToBytes(new ArrayList()
                {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, curIndex / 255, curIndex % 255
                });
            }
            else
            {
                arrayIv = Encoding.UTF8.GetBytes(aesConf.iv);
            }
            byte[] data = default;
            if (file != null && file.Length != 0)
            {
                data = !string.IsNullOrEmpty(aesConf.uri) ? AES128.AESDecrypt(file, arrayIv, aesConf.key) : file;
            }
            else
            {
                //IsComplete = false;
                Logger.LogDebug("file为空");
            }
            //解密 AES

            return(data);
        }
예제 #4
0
        public void SetPin(string pin, UserAccount user, string deviceNumber)
        {
            if (!string.IsNullOrEmpty(user.Pin))
            {
                throw new ApplicationException(MessageResources.PINHasSet);
            }
            var _pin = AES128.Decrypt(pin, AES128.DefaultKey);

            using (var scope = new TransactionScope())
            {
                new UserAccountDAC().SetPinById(user.Id, PasswordHasher.HashPassword(_pin));
                if (new UserDeviceDAC().GetUserDeviceByAccountId(user.Id)
                    .All(item => item.DeviceNumber != deviceNumber))
                {
                    new UserDeviceDAC().Insert(new UserDevice()
                    {
                        DeviceNumber   = deviceNumber,
                        LastActiveTime = DateTime.UtcNow,
                        Name           = " ",
                        UserAccountId  = user.Id
                    });
                }
                new UserAccountDAC().UpdateIsBindingDevice(user.Id);
                scope.Complete();
            }
        }
예제 #5
0
        private static string GenerateToken(string clientKey, string secretKey)
        {
            string password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + clientKey;
            string token    = AES128.Encrypt(password, secretKey);

            return(token);
        }
예제 #6
0
        private string GenerateToken(ProfileRouter router)
        {
            var password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + router.ClientKey;
            var token    = AES128.Encrypt(password, router.SecretKey);

            return(token);
        }
예제 #7
0
        private string GenerateToken()
        {
            string password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + server.ClientKey;
            string token    = AES128.Encrypt(password, server.SecretKey);

            return(token);
        }
예제 #8
0
        public void TestKey()
        {
            byte[] key = Enumerable.Range(100, 16).Select(val => (byte)val).ToArray();

            byte[] testData = Enumerable.Range(0, 16).Select(val => (byte)val).ToArray();

            byte[] result;
            using (var outStream = new MemoryStream())
            {
                using (var encStream = AES128.EncryptStream(outStream, key))
                {
                    encStream.Write(testData, 0, testData.Length);
                }
                result = outStream.ToArray();
            }

            byte[] decrypted;
            using (var outStream2 = new MemoryStream())
            {
                using (var encStream = AES128.DecryptStream(new MemoryStream(result), key))
                {
                    encStream.CopyTo(outStream2);
                }
                decrypted = outStream2.ToArray();
            }

            Assert.IsTrue(testData.SequenceEqual(decrypted));
        }
예제 #9
0
        public void ChangePassword(string oldPassword, string newPassword)
        {
            SettingComponent sComponent = new SettingComponent();
            var setting = sComponent.GetSetting();

            if (MD5Helper.EncryptTo32(oldPassword) == setting.PassCiphertext)
            {
                var aclist = AccountDac.Default.SelectAll();
                foreach (var item in aclist)
                {
                    item.PrivateKey = AES128.Decrypt(item.PrivateKey, oldPassword);
                    item.PrivateKey = AES128.Encrypt(item.PrivateKey, newPassword);
                }
                try
                {
                    AccountDac.Default.UpdatePrivateKeyAr(aclist);
                    setting                = sComponent.GetSetting();
                    setting.Encrypt        = true;
                    setting.PassCiphertext = MD5Helper.EncryptTo32(newPassword);
                    sComponent.SaveSetting(setting);
                }
                catch (Exception ex)
                {
                    throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex);
                }
            }
            else
            {
                throw new CommonException(ErrorCode.Engine.Wallet.CHECK_PASSWORD_ERROR);
            }
        }
예제 #10
0
        private T LoadFile <T>(string filePath, string salt)
        {
            if (!File.Exists(filePath))
            {
                throw new CommonException(ErrorCode.Engine.Wallet.IO.FILE_NOT_FOUND);
            }
            string fileString = string.Empty;

            try
            {
                fileString = FileHelper.LoadFileString(filePath);
            }
            catch (Exception ex)
            {
                throw new CommonException(ErrorCode.Engine.Wallet.IO.FILE_DATA_INVALID, ex);
            }

            try
            {
                if (!string.IsNullOrEmpty(salt))
                {
                    fileString = AES128.Decrypt(fileString, salt);
                }
            }
            catch (Exception ex)
            {
                throw new CommonException(ErrorCode.Engine.Wallet.DECRYPT_DATA_ERROR, ex);
            }
            return(JsonConvert.DeserializeObject <T>(fileString));
        }
예제 #11
0
        public bool EncryptWallet(string salt)
        {
            bool result = false;
            var  aclist = AccountDac.Default.SelectAll();

            foreach (var item in aclist)
            {
                item.PrivateKey = AES128.Encrypt(item.PrivateKey, salt);
            }
            try
            {
                AccountDac.Default.UpdatePrivateKeyAr(aclist);

                SettingComponent sComponent = new SettingComponent();
                var setting = sComponent.GetSetting();
                setting.Encrypt        = true;
                setting.PassCiphertext = MD5Helper.EncryptTo32(salt);
                sComponent.SaveSetting(setting);
                result = true;
            }
            catch (Exception ex)
            {
                throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex);
            }

            return(result);
        }
예제 #12
0
        public static void Verify(FixValueVerifier verifier, SystemPlatform plateForm, string uniqueKey, string hashedCode, string toCheckCode, bool needDecrypt = true)
        {
            var errorCountKey = verifier.GetErrorCountKey(plateForm, uniqueKey);
            int errorCount    = CheckErrorCount(verifier, errorCountKey);

            bool result = true;

            if (needDecrypt)
            {
                try
                {
                    toCheckCode = AES128.Decrypt(toCheckCode, AES128.DefaultKey);
                }
                catch
                {
                    result = false;
                }
            }

            result = result && verifier.Verify(plateForm, uniqueKey, hashedCode, toCheckCode);
            if (result)
            {
                if (errorCount > 0)
                {
                    DeleteErrorCount(errorCountKey);
                }
            }
            else
            {
                IncreaseErrorCount(verifier, errorCountKey);
            }
        }
예제 #13
0
        private string GetHeaders()
        {
            var password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + "FiiiPay";
            var token    = AES128.Encrypt(password, "nHf29ryC31hQXrzsSjM7bDYs8v7AT8n54tl3nHBrpB1TM9HhXJ48hOpQrzy9XrQB");

            return(token);
        }
예제 #14
0
        public void Challenge7()
        {
            var encrypted = Convert.FromBase64String(File.ReadAllText(TestContext.CurrentContext.TestDirectory + "\\resources\\7.txt"));
            var output    = Encoding.UTF8.GetString(AES128.DecryptECB(encrypted, Encoding.UTF8.GetBytes("YELLOW SUBMARINE")));

            Assert.IsTrue(output.StartsWith("I'm back and I'm ringin' the bell"));
        }
예제 #15
0
        private string DecryptPrivateKey(string privateKey)
        {
            var setting = new SettingComponent().GetSetting();

            if (setting.Encrypt)
            {
                if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase")))
                {
                    try
                    {
                        return(AES128.Decrypt(privateKey, _cache.Get <string>("WalletPassphrase")));
                    }
                    catch
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.WALLET_DECRYPT_FAIL);
                    }
                }
                else
                {
                    //是否需要调用解密的逻辑
                    throw new CommonException(ErrorCode.Service.Transaction.WALLET_DECRYPT_FAIL);
                }
            }
            else
            {
                return(privateKey);
            }
        }
        /// <summary>Asynchronously authenticates the request.</summary>
        /// <returns>The task that completes the authentication.</returns>
        /// <param name="context">The authentication context.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var request = context.Request;

            if (request == null)
            {
                throw new InvalidOperationException("Request must not be null");
            }

            if (context.Request.Headers.Authorization == null)
            {
                return(Task.FromResult(0));
            }

            try
            {
                var authHeader = request.Headers.Authorization.Parameter;
                var clientKey  = ConfigurationManager.AppSettings["ClientKey"];
                var secretKey  = ConfigurationManager.AppSettings["SecretKey"];

                try
                {
                    var decryptedPIN = AES128.Decrypt(authHeader, secretKey);

                    if (decryptedPIN.Length > 14)
                    {
                        var date      = decryptedPIN.Substring(0, 14);
                        var timestamp = DateTime.ParseExact(date, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);

                        //Payment PIN submission must be within accepted time.
                        //This is to prevent hacker copy the encrypted string and use it to authorize victim payment PIN without the need
                        //to know the exact PIN
                        if (timestamp.AddMinutes(5) >= DateTime.UtcNow && timestamp.AddMinutes(-5) <= DateTime.UtcNow)
                        {
                            var actualPIN = decryptedPIN.Substring(14);

                            if (actualPIN == clientKey)
                            {
                                SetSecurityPrincipal(ref context, "1", "FiiiPay", "");
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    //DANGER: Need to write log here
                }
            }
            catch (Exception)
            {
                //DANGER: Need to write log here
            }
            return(Task.FromResult(0));
        }
예제 #17
0
        private Dictionary <string, string> GetHeaders()
        {
            var password = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + _router.ClientKey;
            var token    = AES128.Encrypt(password, _router.SecretKey);

            return(new Dictionary <string, string> {
                { "Authorization", "bearer " + token }
            });
        }
예제 #18
0
        private string GenerateToken()
        {
            string clientKey = ConfigurationManager.AppSettings["ClientKey"];
            string secretKey = ConfigurationManager.AppSettings["SecretKey"];
            string password  = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + clientKey;
            string token     = AES128.Encrypt(password, secretKey);

            return(token);
        }
예제 #19
0
        private static string GetToken()
        {
            string clientKey = "FiiiPay";
            string secretKey = "u6lvFYbMPlWf9nIHM5KItktyAl2trgUfWSnVB6qW4Uf6IrU8I0LciAK7ZvaLU5fW";
            string password  = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + clientKey;
            string token     = AES128.Encrypt(password, secretKey);

            return(token);
        }
예제 #20
0
        private static void SaveFile <T>(T obj, string filePath, string salt)
        {
            string jsonString    = JsonConvert.SerializeObject(obj);
            string encryptString = jsonString;

            if (!string.IsNullOrEmpty(salt))
            {
                encryptString = AES128.Encrypt(jsonString, salt);
            }
            FileHelper.StringSaveFile(encryptString, filePath);
        }
예제 #21
0
        public IRpcMethodResult GetNewAddress(string tag)
        {
            try
            {
                var       accountComponent = new AccountComponent();
                Account   account          = null;
                var       setting          = new SettingComponent().GetSetting();
                AccountOM result           = null;

                if (setting.Encrypt)
                {
                    if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase")))
                    {
                        account            = accountComponent.GenerateNewAccount();
                        account.IsDefault  = true;
                        account.PrivateKey = AES128.Encrypt(account.PrivateKey, _cache.Get <string>("WalletPassphrase"));
                        accountComponent.UpdatePrivateKeyAr(account);
                    }
                    else
                    {
                        throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED);
                    }
                }
                else
                {
                    account           = accountComponent.GenerateNewAccount();
                    account.IsDefault = true;
                }

                if (account != null)
                {
                    account.Tag = tag;
                    accountComponent.UpdateTag(account.Id, tag);

                    result           = new AccountOM();
                    result.Address   = account.Id;
                    result.PublicKey = account.PublicKey;
                    result.Balance   = account.Balance;
                    result.IsDefault = account.IsDefault;
                    result.WatchOnly = account.WatchedOnly;
                    result.Tag       = account.Tag;
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
예제 #22
0
        public void ModifyPIN(InvestorAccount investor, string oldPIN, string newPIN)
        {
            string plainNewPIN = AES128.Decrypt(newPIN, AES128.DefaultKey);

            if (PasswordHasher.VerifyHashedPassword(investor.PIN, plainNewPIN))
            {
                throw new CommonException(ReasonCode.PIN_MUST_BE_DIFFERENT, R.新旧Pin码不能一致);
            }
            VerifyPIN(investor, oldPIN);
            new InvestorAccountDAC().UpdatePIN(investor.Id, PasswordHasher.HashPassword(plainNewPIN));
            new InvestorAccountDAC().UpdatePINStatus(investor.Id, 1);
        }
예제 #23
0
        public void TestBytes()
        {
            byte[] key = Enumerable.Range(100, 16).Select(val => (byte)val).ToArray();
            byte[] IV  = Enumerable.Range(128, 16).Select(val => (byte)val).ToArray();

            byte[] testData = Enumerable.Range(0, 256).Select(val => (byte)val).ToArray();

            var encData = AES128.Encrypt(testData, key, IV);

            var decodeData = AES128.Decrypt(encData, key, IV);

            Assert.IsTrue(testData.SequenceEqual(decodeData));
        }
예제 #24
0
        public void ModifyPassword(InvestorAccount investor, string oldPassword, string newPassword)
        {
            string plainNewPassword = AES128.Decrypt(newPassword, AES128.DefaultKey);
            string plainOldPassword = AES128.Decrypt(oldPassword, AES128.DefaultKey);

            if (!PasswordHasher.VerifyHashedPassword(investor.Password, plainOldPassword))
            {
                throw new CommonException(ReasonCode.WRONG_OLD_PASSWORD_ENTERRED, R.原密码不正确);
            }
            if (PasswordHasher.VerifyHashedPassword(investor.Password, plainNewPassword))
            {
                throw new CommonException(ReasonCode.WRONG_OLD_PASSWORD_ENTERRED, R.新旧密码不能一致);
            }
            new InvestorAccountDAC().UpdatePassword(investor.Id, PasswordHasher.HashPassword(plainNewPassword));
            new InvestorAccountDAC().UpdatePasswordStatus(investor.Id, 1);
        }
예제 #25
0
        public void UpdatePin(UserAccount user, string oldPin, string newPin)
        {
            SecurityVerify.Verify <UpdatePinVerify>(new CustomVerifier("UpdatePin"), SystemPlatform.FiiiPay, user.Id.ToString(), (model) =>
            {
                return(model.PinVerified && model.CombinedVerified);
            });

            newPin = AES128.Decrypt(newPin, AES128.DefaultKey);
            var _oldPin = AES128.Decrypt(oldPin, AES128.DefaultKey);

            if (_oldPin.Equals(newPin))
            {
                throw new CommonException(ReasonCode.PIN_MUST_BE_DIFFERENT, MessageResources.NewPINOldPINDifferent);
            }
            new UserAccountDAC().SetPinById(user.Id, PasswordHasher.HashPassword(newPin));
        }
예제 #26
0
        public static bool TryParse(string cipherPin, out string pinText)
        {
            try
            {
                pinText = AES128.Decrypt(cipherPin, AES128.DefaultKey);
            }
            catch (Exception)
            {
                pinText = null;
                return(false);
            }

            var reg = new Regex("^\\d{6}$");

            return(reg.IsMatch(pinText) && !ContinuousNumber.Contains(pinText));
        }
예제 #27
0
        /// <summary>
        /// 对Ts文件加密
        /// </summary>
        /// <param name="file"></param>
        /// <param name="curIndex"></param>
        /// <returns></returns>
        private byte[] TsEncrypt(byte[] file, int curIndex)
        {
            byte[] arrayIv = default;
            arrayIv = ListToBytes(new ArrayList()
            {
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, curIndex / 255, curIndex % 255
            });
            byte[] data = default;
            if (file != null && file.Length != 0)
            {
                data = AES128.AESEncrypt(file, arrayIv, outFileConfig.tsAESKey);
            }
            else
            {
                Logger.LogDebug("file为空");
            }

            return(data);
        }
예제 #28
0
        public ServiceResult ModifyEmail(ModifyEmailModel model)
        {
            var result = new ServiceResult();

            if (!ModelState.IsValid)
            {
                result.Code = ReasonCode.MISSING_REQUIRED_FIELDS;
                foreach (string error in ModelState.Values.SelectMany(v => v.Errors.Select(b => b.ErrorMessage)))
                {
                    result.Message += error + Environment.NewLine;
                }

                return(result);
            }
            var accountId = this.WorkContext.MerchantId;


            new ProfileComponent().ModifyEmail(accountId, model.Code, AES128.Encrypt(model.Token, AES128.DefaultKey));

            return(result);
        }
예제 #29
0
        /// <summary>
        /// 登录
        /// </summary>
        /// <returns></returns>
        private async Task LoginToBilibili()
        {
            async Task WriteLoginDataToFile(Account account)
            {
                if (account == null)
                {
                    throw new Exception("Write to file data can not null.");
                }
                string dataBeforeEncrypt = JsonUtil.SerializeObject(account);
                string dataAfterEncrypt  = AES128.AESEncrypt(dataBeforeEncrypt, _config.AppSetting.Key, "40863a4f-7cbe-4be2-bb54-765233c83d25");
                await File.WriteAllBytesAsync(_dataFilePath, Encoding.UTF8.GetBytes(dataAfterEncrypt));
            }

            async Task LoginByPassword()
            {
                Account account = ByPassword.LoginByPassword(_config.UserSetting.Account, _config.UserSetting.Password);

                if (account == null)
                {
                    throw new Exception("Get account info failed.");
                }
                if (account.LoginStatus != Account.LoginStatusEnum.ByPassword)
                {
                    throw new Exception($"登录失败,登录失败原因:{account.LoginStatus}");
                }
                await WriteLoginDataToFile(account);

                _account = account;
            }

            try
            {
                if (!File.Exists(_dataFilePath))
                {
                    await LoginByPassword();

                    return;
                }
                //获取历史登录信息
                string fileStr = await File.ReadAllTextAsync(_dataFilePath);

                if (string.IsNullOrEmpty(fileStr))
                {
                    await LoginByPassword();

                    return;
                }
                Account account = null;
                try
                {
                    string decodeStr = AES128.AESDecrypt(fileStr, _config.AppSetting.Key, "40863a4f-7cbe-4be2-bb54-765233c83d25");
                    if (string.IsNullOrEmpty(decodeStr))
                    {
                        await LoginByPassword();

                        return;
                    }
                    account = JsonUtil.DeserializeJsonToObject <Account>(decodeStr);
                }
                catch
                {
                    await LoginByPassword();

                    return;
                }
                //判断AccessToken是否有效
                if (account == null || !ByPassword.IsTokenAvailable(account.AccessToken) || account.UserName != _config.UserSetting.Account)
                {
                    await LoginByPassword();

                    return;
                }
                //判断AccessToken是否需要续期
                if (account.Expires_AccessToken != DateTime.MinValue &&
                    account.Expires_AccessToken.AddDays(-7) < DateTime.Now)
                {
                    DateTime?dt = ByPassword.RefreshToken(account.AccessToken, account.RefreshToken);
                    if (dt == null)
                    {
                        await LoginByPassword();

                        return;
                    }
                    account.Expires_AccessToken = dt.Value;
                    //更新
                    await WriteLoginDataToFile(account);

                    _account = account;
                }
                else
                {
                    _account = account;
                    return;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Login to bilibili failed, login account is {_config.UserSetting.Account}. {ex.Message}", ex);
            }
        }
예제 #30
0
        public IRpcMethodResult SendMany(string fromAccount, SendManyOutputIM[] receivers, string[] feeDeductAddresses)
        {
            try
            {
                string result                      = null;
                var    utxoComponent               = new UtxoComponent();
                var    txComponent                 = new TransactionComponent();
                var    settingComponent            = new SettingComponent();
                var    addressBookComponent        = new AddressBookComponent();
                var    accountComponent            = new AccountComponent();
                var    transactionCommentComponent = new TransactionCommentComponent();
                var    blockComponent              = new BlockComponent();
                var    lastBlockHeight             = blockComponent.GetLatestHeight();

                var    setting     = settingComponent.GetSetting();
                var    utxos       = utxoComponent.GetAllConfirmedOutputs();
                var    tx          = new TransactionMsg();
                double totalOutput = 0;
                var    totalSize   = tx.Serialize().Length;

                if (receivers == null || receivers.Length == 0)
                {
                    throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID);
                }

                foreach (var receiver in receivers)
                {
                    if (!AccountIdHelper.AddressVerify(receiver.address))
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID);
                    }

                    var output = new OutputMsg();
                    output.Amount     = receiver.amount;
                    output.Index      = tx.Outputs.Count;
                    output.LockScript = Script.BuildLockScipt(receiver.address);
                    output.Size       = output.LockScript.Length;
                    tx.Outputs.Add(output);

                    totalSize   += output.Serialize().Length;
                    totalOutput += receiver.amount;
                }

                foreach (var address in feeDeductAddresses)
                {
                    if (receivers.Where(r => r.address == address).Count() == 0)
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.FEE_DEDUCT_ADDRESS_INVALID);
                    }
                }

                var    totalInput  = 0L;
                var    index       = 0;
                double totalFee    = setting.FeePerKB * ((double)totalSize / 1024.0);
                double totalAmount = totalOutput;

                while (index < utxos.Count)
                {
                    var account = accountComponent.GetAccountById(utxos[index].AccountId);

                    if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                    {
                        var   utxoTX    = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash);
                        Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash);

                        if (utxoTX == null || utxoBlock == null)
                        {
                            index++;
                            continue;
                        }

                        if (!utxoBlock.IsVerified)
                        {
                            index++;
                            continue;
                        }

                        if (Time.EpochTime < utxoTX.Locktime)
                        {
                            index++;
                            continue;
                        }

                        if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()))
                        {
                            var blockHeight = utxoBlock.Height;

                            if (lastBlockHeight - blockHeight < 100L)
                            {
                                index++;
                                continue;
                            }
                        }

                        var input = new InputMsg();
                        input.OutputTransactionHash = utxos[index].TransactionHash;
                        input.OutputIndex           = utxos[index].OutputIndex;
                        input.UnlockScript          = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey));
                        input.Size = input.UnlockScript.Length;
                        tx.Inputs.Add(input);

                        var size = input.Serialize().Length;
                        totalSize  += size;
                        totalFee   += setting.FeePerKB * ((double)size / 1024.0);
                        totalInput += utxos[index].Amount;
                    }
                    else
                    {
                        index++;
                        continue;
                    }

                    if (feeDeductAddresses == null || feeDeductAddresses.Length == 0)
                    {
                        totalAmount = totalOutput + totalFee;
                    }

                    if (totalInput >= (long)Math.Ceiling(totalAmount))
                    {
                        var size = tx.Outputs[0].Serialize().Length;

                        if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0))
                        {
                            totalSize += size;
                            totalFee  += setting.FeePerKB * ((double)size / 1024.0);

                            if (feeDeductAddresses == null || feeDeductAddresses.Length == 0)
                            {
                                totalAmount = totalOutput + totalFee;
                            }


                            var newAccount = accountComponent.GenerateNewAccount();

                            if (setting.Encrypt)
                            {
                                if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase")))
                                {
                                    newAccount.PrivateKey = AES128.Encrypt(newAccount.PrivateKey, _cache.Get <string>("WalletPassphrase"));
                                    accountComponent.UpdatePrivateKeyAr(newAccount);
                                }
                                else
                                {
                                    throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED);
                                }
                            }

                            var newOutput = new OutputMsg();
                            newOutput.Amount     = totalInput - (long)Math.Ceiling(totalAmount);
                            newOutput.Index      = tx.Outputs.Count;
                            newOutput.LockScript = Script.BuildLockScipt(newAccount.Id);
                            newOutput.Size       = newOutput.LockScript.Length;
                            tx.Outputs.Add(newOutput);
                        }

                        break;
                    }

                    index++;
                }

                if (totalInput < totalAmount)
                {
                    throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH);
                }

                if (feeDeductAddresses != null && feeDeductAddresses.Length > 0)
                {
                    var averageFee = totalFee / feeDeductAddresses.Length;

                    for (int i = 0; i < receivers.Length; i++)
                    {
                        if (feeDeductAddresses.Contains(receivers[i].address))
                        {
                            tx.Outputs[i].Amount -= (long)Math.Ceiling(averageFee);

                            if (tx.Outputs[i].Amount <= 0)
                            {
                                throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE);
                            }
                        }
                    }
                }

                tx.Timestamp = Time.EpochTime;
                tx.Hash      = tx.GetHash();
                txComponent.AddTransactionToPool(tx);
                Startup.P2PBroadcastTransactionAction(tx.Hash);
                result = tx.Hash;

                for (int i = 0; i < receivers.Length; i++)
                {
                    var receiver = receivers[i];

                    if (!string.IsNullOrWhiteSpace(receiver.tag))
                    {
                        addressBookComponent.SetTag(receiver.address, receiver.tag);
                    }

                    if (!string.IsNullOrWhiteSpace(receiver.comment))
                    {
                        transactionCommentComponent.Add(tx.Hash, i, receiver.comment);
                    }
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }