using System;
using System.Collections.Generic;
using System.Text;
using AlanThinker.Game.Chess.Connector;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Win32;
using System.Security.Cryptography;
using System.Security.Policy;
using System.IO;
using System.Threading;
using System.Xml;

namespace AlanThinker.Game.Chess
{
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // !!! 注意, 不要使用任何已经被混淆了的类, 比如Chess project中的类.
    // !!! 注意, 脚本不能包含 .Net MSBuild 4.0 和 3.5 才有的功能, 比如参数默认值, var等.
    // !!!       低版本的鹏飞象棋是基于.net 3.0运行的. 
    // !!!       因此请务必在一台只安装了.Net 3.0的XP计算机中测试修改后的脚本.
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    // !!!! 请用 自定义的签名工具签名. (先把数据sha1, 在用rsa with row 进行签名.)

    class MainWindowWrapper : IWin32Window
    {
        IntPtr _handle;
        public IntPtr Handle
        {
            get
            {
                try
                {
                    if (_handle == IntPtr.Zero)
                    {
                        // 注意!!! System.Windows.Threading.Dispatcher.CurrentDispatcher 是错误的 !!!. 可以看 CurrentDispatcher 的说明, 它只是当前线程的Dispatcher, 不是App默认的Dispatcher;
                        App.Current.Dispatcher.Invoke(new Action(delegate
                        {
                            _handle = new System.Windows.Interop.WindowInteropHelper(App.Current.MainWindow).Handle;

                        }));
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                }


                return _handle;
            }
        }
    }


    class Script : IInjection
    {
        MainWindowWrapper _mainWindowWrapper = new MainWindowWrapper();
        Random _random = new Random();

        bool skipVerification = true;

        private static string RegKeyName
        {
            get
            {
                string regKeyName;
                regKeyName = @"HKEY_CURRENT_USER\SOFTWARE\AlanThinker\Data\" + "6";
                return regKeyName;
            }
        }

        private static string RegKeyForRegisterName
        {
            get
            {
                string regKeyName;
                regKeyName = @"HKEY_CURRENT_USER\SOFTWARE\AlanThinker\Register\6";
                return regKeyName;
            }
        }

        public static void SetValueToReg(string valueName, object valueObject)
        {
            Registry.SetValue(RegKeyName, valueName, valueObject);
        }

        public static object GetValueFromReg(string valueName, object defaultValue)
        {
            return Registry.GetValue(RegKeyName, valueName, defaultValue);
        }

        public static void SetValueToRegForRegister(string valueName, object valueObject)
        {
            Registry.SetValue(RegKeyForRegisterName, valueName, valueObject);
        }

        public static object GetValueFromRegForRegister(string valueName, object defaultValue)
        {
            return Registry.GetValue(RegKeyForRegisterName, valueName, defaultValue);
        }

        #region IInjection Members

        public static string DefualtRegisterKey = @"<kv6>um3h0zA7UVpe+sZqMPIkn8TLeqcd4ewBDEC8oNrEjkk6Xj19WZWy6NRhHjKy8D6AqmgoNqETbPPuScImAcKJ6ZabIWvPdWqxoCq+JudH2gKGzs1R2XrNy47V+aqCxncXEIJMkopgn9T9tpsAw3DLm209/VvEBxg6OUh6E9jq51WDK/mTmlZ/jD8qOA4xrY0SamauaHl5xTFXWo3Leem5YNeZ7z27d8LjUblh3MFVL1HnDT5ghehU1VkRPGhLlwH+pNE4zFgqgIcc2Qert62JsFJS6xSLQifByoUpk0uBeNXs2jIt+9Mk6cFe1eux0wPi6ATnCL9ggDTrqouNZKKB2CWQ3iHiXt/bcd3yUEnfWb1lM0mNxQ9jW+UUJdgOWpthQulnK7TjKnnR0Ys/AX+WEw4PDPwqMai5eGnKQABFOh7AX1K1KpHrFsW7hl6RhtW7JgXBINkvrssR7ZrUuXgw8XvGk01Hm1ohH9vgyo5/ugi7Kk49h+CFEGW62MHLX6DS5EQCfi32aXfuL25IM0pTppHGa1k15hr6uL3pdTAbfylNqoUK116PW67p/uiPrWC9</kv6>";

        public void ExitAfterSeconds(int minSeconds, int maxSecond, string messageUrl)
        {
            new Thread(new ThreadStart(
                       delegate
                       {
                           try
                           {
                               Thread.Sleep(_random.Next(minSeconds * 1000, maxSecond * 1000));
                               Process.Start(messageUrl);
                               Environment.Exit(0);

                           }
                           catch (Exception ex)
                           {
                               Process.Start(messageUrl);
                               Debug.WriteLine(ex);
                               Environment.Exit(0);
                           }
                       })).Start();
        }

        static string _firstInstallTimeStr = "FirstInstallTime";

        public void AfterInjectionLoaded(Config config)
        {
            RegisterHelper.HasARigthFormatKey();
        }

        private static void CheckHaveSavedFirstInstallTime()
        {
            try
            {
                object firstInstallTimeOb = GetValueFromReg(_firstInstallTimeStr, null);
                if (firstInstallTimeOb == null)
                {
                    SetValueToReg(_firstInstallTimeStr, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                else
                {
                    DateTime firstInstallTime;
                    bool canParese = DateTime.TryParse(firstInstallTimeOb.ToString(), out firstInstallTime);
                    if (!canParese)
                    {
                        SetValueToReg(_firstInstallTimeStr, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else if (firstInstallTime > DateTime.Now)
                    {
                        SetValueToReg(_firstInstallTimeStr, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }

        }

        public void EngineInterval(Config config)
        {
            if (!skipVerification)
            {
                new Thread(new ThreadStart(
                 delegate
                 {
                     try
                     {
                         Thread.Sleep(_random.Next(5000, 15000));
                         new ScripHelper().VerifyAssemblyTag1(typeof(BoardControl).Assembly);
                     }
                     catch (Exception ex)
                     {
                         Debug.WriteLine(ex);
                         new ScripHelper().VerifyAssemblyTag1(typeof(BoardControl).Assembly);
                     }
                 }
                      )).Start();

            }
            else
            {
#if !DEBUG
                //MessageBox.Show(_mainWindowWrapper, "警告! 已经跳过了验证功能.");
#endif
            }
        }

        public void BeforeSolutionInitialized(Solution solution)
        {
            if (!skipVerification)
            {
                new Thread(new ThreadStart(
                   delegate
                   {
                       try
                       {
                           Thread.Sleep(_random.Next(5000, 15000));
                           new ScripHelper().VerifyAssemblyTag1(typeof(BoardControl).Assembly);
                       }
                       catch (Exception ex)
                       {
                           Debug.WriteLine(ex);
                           new ScripHelper().VerifyAssemblyTag1(typeof(BoardControl).Assembly);
                       }
                   }
                    )).Start();
            }
            else
            {
#if !DEBUG
                //MessageBox.Show(_mainWindowWrapper, "警告! 已经跳过了验证功能.");
#endif
            }

            Debug.WriteLine("--Begin-- BeforeSolutionInitialized");
            //solution.UseRealMouseSimulator = true;
            ////solution.InvertColor = true;

            ////solution.SolutionType = SolutionType.Normal;
            ////solution.ImageDiffForFixed = 3;
            ////solution.TMSimilarityThreshold = 0.5f;

            //solution.BMBlockSize = 12;
            ////solution.ChessWidthForSpecail = 30;
            //solution.BMSearchRadius = 6;
            //solution.BMSimilarityThreshold = 0.70f;

            //todo:
            //verify assembly.

            Debug.WriteLine("--End-- BeforeSolutionInitialized");

            //必须调用此函数, 否则方案无法使用, 放在此处执行是为了防止破解者跳过脚本.
            solution.InitSolution();

        }

        public void AfterSolutionInitialized(Solution solution)
        {
            Debug.WriteLine("--Begin-- AfterSolutionInitialized");

            Debug.WriteLine("--End-- AfterSolutionInitialized");
        }

        #endregion
    }

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public class ScripHelper
    {
        static string _rijKeyTag1 = "GwPZrz8H6kIYe1k0notpjR3k+c/SBx0rR3hRjq0djo0=";
        static string _rijIVTag1 = "OHdNnKCX8T6mNhi8s+I3GA==";
        //AlanThinkerCode.pfx
        static string _encryptedRsaPublicKeyTag1 = "jmSohkQcZVy1LO7B7bpB1bM5H/SaR2gn3M9l+ZyZWoEIYOAi4aCAzoE3glb3o578Vs91NcXWjiV/ULdTBT/CFjpylEMztVPwAVc2jaj0rkv9vI/gTigS3fluRtYG4ihbB0kqY9an3iH0wX7AnHkbQXqYC7bV0BsdkS5Ml8e8XV0ESJ+CC98NSuIQteA4FEB8oJ5kWRUnnCYadQsnTVA5L291P9y09dtGPUAY79iPBUUPCIKfSsTvJREIbhYr0mf6uZugyvg+LT6vYutZUQe6BbIx8LMo6C6QA+T3En4eRXa8IeCgxybMMkri+1XrPSihhX0d5pKazUd0VfTviDqVrw==";
        static RSACryptoServiceProvider _rsaTag1;


        private void PrepareTag1()
        {
            if (_rsaTag1 == null)
            {
                VerifyRSAPublicKeyTag1();
                string rsaPublicKey = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, _encryptedRsaPublicKeyTag1);
                _rsaTag1 = new RSACryptoServiceProvider();
                _rsaTag1.FromXmlString(rsaPublicKey);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assembly"></param>
        /// <remarks>
        /// Please copy this class!!!!! 
        /// Don't use this class by reference!!!!!
        /// (Avoid user replece the Security dll file)
        /// </remarks>
        private void VerifyRSAPublicKeyTag1()
        {
            string str = _encryptedRsaPublicKeyTag1 + _rijKeyTag1 + _rijIVTag1 + "AlanThinker";
            byte[] hash = ScripSecurityHelper.ComputeHashBySHA1(Encoding.UTF8.GetBytes(str));
            string hashStr = Convert.ToBase64String(hash);
            if (hashStr != "smckaRcz7lTineg72TolBR4r1hc=")
            {
                //errorMessage = "Bad RSA public key!"              
                string encryptedMessage = "SrhxJg/amjUh5PsdwOXP0d64PjWjxQTLC03nOqSbXpk=";
                string errorMessage = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, encryptedMessage);

                //三选一 Kill 或者 Exit               
                System.Windows.Application.Current.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Send,
                    new Action(System.Windows.Application.Current.Shutdown));
                //System.Diagnostics.Process.GetCurrentProcess().Kill();
                //System.Environment.Exit(0);      

            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assembly"></param>
        /// <remarks>
        /// Please copy this class!!!!! 
        /// Don't use this class by reference!!!!!
        /// (Avoid user replece the Security dll file)
        /// </remarks>
        public bool TestAssemblyTag1(object ob)
        {
            try
            {
                Assembly assembly;
                if (ob is Assembly)
                {
                    assembly = ob as Assembly;
                }
                else if (ob is Type)
                {
                    assembly = (ob as Type).Assembly;
                }
                else
                {
                    assembly = ob.GetType().Assembly;
                }

                PrepareTag1();

                Hash assHash = new Hash(assembly);
                string sigFileName = assembly.Location + ".sig";
                if (!File.Exists(sigFileName))
                {
                    //errorMessage = "Can't find the sig file! Assembly FullName: "              
                    string encryptedMessage = "VJRGsYpcLg//jGhOVg7nEWDbkxlFj0kxofHZknxFDJTrdsxr4Csck/UrrABNzkn9";
                    string errorMessage = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, encryptedMessage);

                    return false;
                }
                else
                {
                    byte[] signedFileData = ScripSecurityHelper.ReadBytesFromFile(sigFileName);
                    bool ret = _rsaTag1.VerifyHash(assHash.SHA1, "sha1", signedFileData);
                    if (!ret)
                    {
                        //errorMessage = "Bad assembly! Assembly FullName: "              
                        string encryptedMessage = "zMSce6BQM4kiaRJ5/P7+bOFS0v8N4deEOK6kAnfneMT2qCTqgcdupBITDDOZDgU5";
                        string errorMessage = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, encryptedMessage);

                        return false;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                return false;
            }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assembly"></param>
        /// <remarks>
        /// Please copy this class!!!!! 
        /// Don't use this class by reference!!!!!
        /// (Avoid user replece the Security dll file)
        /// </remarks>
        public void VerifyAssemblyTag1(object ob)
        {
            try
            {
                Assembly assembly;
                if (ob is Assembly)
                {
                    assembly = ob as Assembly;
                }
                else if (ob is Type)
                {
                    assembly = (ob as Type).Assembly;
                }
                else
                {
                    assembly = ob.GetType().Assembly;
                }

                PrepareTag1();

                Hash assHash = new Hash(assembly);
                string sigFileName = assembly.Location + ".sig";
                if (!File.Exists(sigFileName))
                {
                    //errorMessage = "Can't find the sig file! Assembly FullName: "              
                    string encryptedMessage = "VJRGsYpcLg//jGhOVg7nEWDbkxlFj0kxofHZknxFDJTrdsxr4Csck/UrrABNzkn9";
                    string errorMessage = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, encryptedMessage);


                    //三选一 Kill 或者 Exit               
                    System.Windows.Application.Current.Dispatcher.Invoke(
                        System.Windows.Threading.DispatcherPriority.Send,
                        new Action(System.Windows.Application.Current.Shutdown));
                    //System.Diagnostics.Process.GetCurrentProcess().Kill();
                    System.Environment.Exit(0);
                }
                else
                {
                    byte[] signedFileData = ScripSecurityHelper.ReadBytesFromFile(sigFileName);
                    bool ret = _rsaTag1.VerifyHash(assHash.SHA1, "sha1", signedFileData);
                    if (!ret)
                    {
                        //errorMessage = "Bad assembly! Assembly FullName: "              
                        string encryptedMessage = "zMSce6BQM4kiaRJ5/P7+bOFS0v8N4deEOK6kAnfneMT2qCTqgcdupBITDDOZDgU5";
                        string errorMessage = ScripSecurityHelper.DecryptedFromBase64String(_rijKeyTag1, _rijIVTag1, encryptedMessage);

                        //三选一 Kill 或者 Exit               
                        System.Windows.Application.Current.Dispatcher.Invoke(
                            System.Windows.Threading.DispatcherPriority.Send,
                            new Action(System.Windows.Application.Current.Shutdown));
                        //System.Diagnostics.Process.GetCurrentProcess().Kill();
                        System.Environment.Exit(0);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);

                System.Windows.Application.Current.Dispatcher.Invoke(
                        System.Windows.Threading.DispatcherPriority.Send,
                        new Action(System.Windows.Application.Current.Shutdown));
            }
        }

        public static void ThrowAExceptionInNewThreadAndKillCurrentPocessTag1(string message)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(
                        System.Windows.Threading.DispatcherPriority.Send,
                        new Action(System.Windows.Application.Current.Shutdown));
        }
    }

    public class RegisterItem2
    {
        public string softwareIdentity;
        public string encryptedKey;
        public string key;
        public string email;
        public string productFunctionEnum;
        public string expireDate;
        public string supportDate;
        public string price;
        public string description;
    }

    public class Constants2
    {
        public static readonly string registerKey = "registerKey";
        public static readonly string softwareIdentity = "softwareIdentity";
        public static readonly string hardwareCode = "hardwareCode";
        public static readonly string key = "key";
        public static readonly string email = "email";
        public static readonly string title = "title";
        public static readonly string expireDate = "expireDate";
        public static readonly string supportDate = "supportDate";
        public static readonly string price = "price";
        public static readonly string description = "description";
        public static readonly string encryptedKey = "encryptedKey";
        public static readonly string productFunctionEnum = "productFunctionEnum";
        public static readonly string totalHardwareInfo = "totalHardwareInfo";
        public static readonly string keyAcceptTime = "keyAcceptTime";
        public static readonly string isRegedBefore = "isRegedBefore";


    }

    public class RegisterHelper
    {
        static string _rijKey = "tc7ISGZr8yY90F5jmkqtrgaokBiCowmFG9u/vmITLu0=";
        static string _rijIV = "fYFym/PCxcAy5wRn8aJEkQ==";

        public static RegisterItem2 ParseKey(string encryptedkey)
        {
            RegisterItem2 item = new RegisterItem2();
            string totalkey = DecryptKey(encryptedkey);
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(totalkey);
            if (doc.DocumentElement.GetElementsByTagName(Constants2.softwareIdentity).Count > 0)
            {
                item.softwareIdentity = doc.DocumentElement[Constants2.softwareIdentity].InnerText;
            }
            item.key = doc.DocumentElement[Constants2.key].InnerText;
            item.email = doc.DocumentElement[Constants2.email].InnerText;
            item.productFunctionEnum = doc.DocumentElement[Constants2.productFunctionEnum].InnerText;
            item.expireDate = doc.DocumentElement[Constants2.expireDate].InnerText;
            item.supportDate = doc.DocumentElement[Constants2.supportDate].InnerText;
            item.price = doc.DocumentElement[Constants2.price].InnerText;
            item.description = doc.DocumentElement[Constants2.description].InnerText;
            return item;
        }

        public static string DecryptKey(string encryptedkey)
        {
            encryptedkey=System.Text.RegularExpressions.Regex.Replace(encryptedkey, @"\<kv\d+\>", "");
            encryptedkey = System.Text.RegularExpressions.Regex.Replace(encryptedkey, @"\</kv\d+\>", "");
          
            string totalkey = ScripSecurityHelper.DecryptedFromBase64String(_rijKey, _rijIV, encryptedkey);
            return totalkey;
        }

        public static string GetPureKey(string encryptedkey)
        {
            RegisterItem2 item = ParseKey(encryptedkey);
            return item.key;
        }

        static string[] forbiddenKeys = new string[]
        {
            "1D72AC23-F0EF0D90-A21308D0-6770AB1E-72878D8C-B4C7BBE7-2667BCC5-B1A201B9-2C041739-813AA5CB",
            "477B18A1-484D0F41-2B3C3A90-359D6D66-C6C11B15-3C8CDF8F-A35D6EB1-FA54257C-25CF73F0-183E6C2C",
        };

        public static bool HasARigthFormatKey()
        {
            try
            {
                string encryptedKey = Script.GetValueFromRegForRegister("encryptedKey", "").ToString();
                RegisterItem2 item = ParseKey(encryptedKey);
                DateTime dt = DateTime.Parse(item.expireDate);
                if (dt < DateTime.Now)
                {
                    System.Windows.Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Send,new Action(System.Windows.Application.Current.Shutdown));
                    return false;
                }
                return true;
            }
            catch //如果格式无法正常解析, 返回false.
            {
                return false;
            }
        }
    }

    public static class ScripSecurityHelper
    {
        static MD5 _md5 = MD5.Create();
        static SHA1 _sha1 = SHA1.Create();
        //static SHA256 _sha256;
        //static SHA384 _sha384;
        static SHA512 _sha512 = SHA512.Create();

        public static byte[] ComputeHashByMD5(Stream inputStream)
        {
            lock (_md5)
            {
                return _md5.ComputeHash(inputStream);
            }
        }

        public static byte[] ComputeHashByMD5(string fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return ComputeHashByMD5(fs);
            }
        }

        public static byte[] ComputeHashBySHA1(Stream inputStream)
        {
            lock (_sha1)
            {
                return _sha1.ComputeHash(inputStream);
            }
        }

        public static byte[] ComputeHashBySHA1(byte[] data)
        {
            lock (_sha1)
            {
                return _sha1.ComputeHash(data);
            }
        }

        public static byte[] ComputeHashBySHA1(string fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return ComputeHashBySHA1(fs);
            }
        }

        //比SHA1大约慢 55%
        public static byte[] ComputeHashBySHA512(Stream inputStream)
        {
            lock (_sha512)
            {
                return _sha512.ComputeHash(inputStream);
            }
        }

        //比SHA1大约慢 55%
        public static byte[] ComputeHashBySHA512(byte[] data)
        {
            lock (_sha512)
            {
                return _sha512.ComputeHash(data);
            }
        }

        public static byte[] ComputeHashBySHA512(string fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return ComputeHashBySHA512(fs);
            }
        }

        public static RijndaelManaged GetRijFromBase64String(string base64Key, string base64IV)
        {
            RijndaelManaged rij = new RijndaelManaged();
            rij.Key = Convert.FromBase64String(base64Key);
            rij.IV = Convert.FromBase64String(base64IV);
            return rij;
        }

        public static string EncryptToBase64String(SymmetricAlgorithm symAlg, string orignialString)
        {
            ICryptoTransform encryptor = symAlg.CreateEncryptor();
            Byte[] data = Encoding.UTF8.GetBytes(orignialString);
            byte[] encryptedData = encryptor.TransformFinalBlock(data, 0, data.Length);
            string base64 = Convert.ToBase64String(encryptedData);
            return base64;
        }

        public static string EncryptToBase64String(string base64Key, string base64IV, string orignialString)
        {
            RijndaelManaged rij = GetRijFromBase64String(base64Key, base64IV);
            return EncryptToBase64String(rij, orignialString);
        }

        public static string DecryptedFromBase64String(SymmetricAlgorithm symAlg, string encryptedString)
        {
            ICryptoTransform decryptor = symAlg.CreateDecryptor();
            byte[] encryptedData = Convert.FromBase64String(encryptedString);
            Byte[] data = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            string decryptedText = Encoding.UTF8.GetString(data);
            return decryptedText;
        }

        public static string DecryptedFromBase64String(string base64Key, string base64IV, string encryptedString)
        {
            RijndaelManaged rij = GetRijFromBase64String(base64Key, base64IV);
            return DecryptedFromBase64String(rij, encryptedString);
        }

        public static byte[] ReadBytesFromFile(string fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return ReadBytesFromStream(fs);
            }
        }

        public static byte[] ReadBytesFromFile(string fileName, int startIndex, int length)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return ReadBytesFromStrem(fs, startIndex, length);
            }
        }

        public static byte[] ReadBytesFromStream(Stream stream)
        {
            if (stream.Length > 1024 * 1024 * 10)
                throw new Exception("File bigger than 10M");
            byte[] bytes = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(bytes, 0, (int)stream.Length);
            return bytes;
        }

        public static byte[] ReadBytesFromStrem(Stream stream, int startIndex, int length)
        {
            byte[] bytes = new byte[length];
            stream.Seek(startIndex, SeekOrigin.Begin);
            stream.Read(bytes, 0, length);
            return bytes;
        }
    }
}