예제 #1
0
        private void InitializePatcher()
        {
            patcher = SPTUtils.CreatePatcher(Path.GetDirectoryName(PatchUtils.GetCurrentExecutablePath()), versionInfoURL);

            if (!string.IsNullOrEmpty(versionInfoRSA))
            {
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
            }

            if (!string.IsNullOrEmpty(patchInfoRSA))
            {
                patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
            }

            // = checkVersionOnly =
            // true (default): only version number (e.g. 1.0) is compared against VersionInfo to see if there is an update
            // false: hashes and sizes of the local files are compared against VersionInfo (if there are any different/missing files, we'll patch the app)
            if (patcher.CheckForUpdates(checkVersionOnly))
            {
                StartCoroutine(CheckForUpdatesCoroutine());
            }
            else
            {
                Debug.LogError("Something went wrong");
            }
        }
        private void DrawSecurityTab()
        {
            s_xmlPath        = PathField(xmlPathGUI, s_xmlPath, false);
            s_publicKeyPath  = PathField(publicKeyPathGUI, s_publicKeyPath, false);
            s_PrivateKeyPath = PathField(privateKeyPathGUI, s_PrivateKeyPath, false);

            if (GUILayout.Button("Sign XML", GUILayout.Height(35f)))
            {
                s_xmlPath        = s_xmlPath.Trim();
                s_PrivateKeyPath = s_PrivateKeyPath.Trim();

                if (s_xmlPath.Length == 0 || s_PrivateKeyPath.Length == 0)
                {
                    return;
                }

                XMLSigner.SignXMLFile(s_xmlPath, File.ReadAllText(s_PrivateKeyPath));
            }

            if (GUILayout.Button("Verify XML", GUILayout.Height(35f)))
            {
                s_xmlPath       = s_xmlPath.Trim();
                s_publicKeyPath = s_publicKeyPath.Trim();

                if (s_xmlPath.Length == 0 || s_publicKeyPath.Length == 0)
                {
                    return;
                }

                Debug.Log("Is genuine: " + XMLSigner.VerifyXMLFile(s_xmlPath, File.ReadAllText(s_publicKeyPath)));
            }

            GUILayout.Space(10f);

            EditorGUILayout.HelpBox("Store your private key in a safe location and don't share it with unknown parties!", MessageType.Warning);

            if (GUILayout.Button("Create RSA Key Pair", GUILayout.Height(35f)))
            {
                string selectedPath = EditorUtility.OpenFolderPanel("Create keys at", "", "");
                if (string.IsNullOrEmpty(selectedPath) || !Directory.Exists(selectedPath))
                {
                    return;
                }

                string publicKey, privateKey;
                SecurityUtils.CreateRSAKeyPair(out publicKey, out privateKey);

                File.WriteAllText(Path.Combine(selectedPath, "public.key"), publicKey);
                File.WriteAllText(Path.Combine(selectedPath, "private.key"), privateKey);

                AssetDatabase.Refresh();
            }

            if (GUILayout.Button("Help", GUILayout.Height(25f)))
            {
                Application.OpenURL("https://github.com/yasirkula/SimplePatchTool/wiki/Signing-&-Verifying-Patches#built-in-method");
            }
        }
예제 #3
0
        private void DrawSecurityTab()
        {
            s_xmlPath        = PathField("XML file: ", s_xmlPath, false);
            s_publicKeyPath  = PathField("Public RSA key: ", s_publicKeyPath, false);
            s_PrivateKeyPath = PathField("Private RSA key: ", s_PrivateKeyPath, false);

            if (GUILayout.Button("Sign XML", GUILayout.Height(35f)))
            {
                s_xmlPath        = s_xmlPath.Trim();
                s_PrivateKeyPath = s_PrivateKeyPath.Trim();

                if (string.IsNullOrEmpty(s_xmlPath) || string.IsNullOrEmpty(s_PrivateKeyPath))
                {
                    return;
                }

                XMLSigner.SignXMLFile(s_xmlPath, File.ReadAllText(s_PrivateKeyPath));
            }

            if (GUILayout.Button("Verify XML", GUILayout.Height(35f)))
            {
                s_xmlPath       = s_xmlPath.Trim();
                s_publicKeyPath = s_publicKeyPath.Trim();

                if (string.IsNullOrEmpty(s_xmlPath) || string.IsNullOrEmpty(s_publicKeyPath))
                {
                    return;
                }

                Debug.Log("Is genuine: " + XMLSigner.VerifyXMLFile(s_xmlPath, File.ReadAllText(s_publicKeyPath)));
            }

            GUILayout.Space(10f);

            EditorGUILayout.HelpBox("Store your private key in a safe location and don't share it with unknown parties!", MessageType.Warning);

            if (GUILayout.Button("Create RSA Key Pair", GUILayout.Height(35f)))
            {
                string selectedPath = EditorUtility.OpenFolderPanel("Create keys at", "", "");
                if (string.IsNullOrEmpty(selectedPath) || !Directory.Exists(selectedPath))
                {
                    return;
                }

                string publicKey, privateKey;
                SecurityUtils.CreateRSAKeyPair(out publicKey, out privateKey);

                File.WriteAllText(Path.Combine(selectedPath, "rsa_public.bytes"), publicKey);
                File.WriteAllText(Path.Combine(selectedPath, "rsa_private.bytes"), privateKey);

                AssetDatabase.Refresh();
            }
        }
예제 #4
0
        private void PatchButtonClicked()
        {
            bool isPatcherActive = runningPatcher != null && !runningPatcher.Equals(null);

            if (!isPatcherActive || !runningPatcher.Patcher.IsRunning)
            {
#if UNITY_EDITOR
                if (selfPatchingInput.isOn)
                {
                    Debug.LogWarning("Can't self patch while testing on editor");
                    selfPatchingInput.isOn = false;
                }
#endif

                SimplePatchTool patcher = new SimplePatchTool(rootPathInput.text, versionInfoURLInput.text).
                                          UseRepair(repairInput.isOn).UseIncrementalPatch(incrementalPatchInput.isOn).
                                          UseCustomDownloadHandler(() => new CookieAwareWebClient()). // to support https in Unity
                                          UseCustomFreeSpaceCalculator((drive) => long.MaxValue).     // DriveInfo.AvailableFreeSpace is not supported on Unity
                                          LogProgress(true);

                if (versionInfoVerifier != null)
                {
                    string versionInfoRSA = versionInfoVerifier.text;
                    patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
                }

                if (patchInfoVerifier != null)
                {
                    string patchInfoRSA = patchInfoVerifier.text;
                    patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
                }

                if (patcher.Run(selfPatchingInput.isOn))
                {
                    Debug.Log("Started patching...");
                    if (!isPatcherActive)
                    {
                        runningPatcher = Instantiate(patcherUiPrefab);
                    }

                    runningPatcher.Initialize(patcher);
                }
                else
                {
                    Debug.Log("Operation could not be started; maybe it is already executing?");
                }
            }
            else
            {
                Debug.LogWarning("An instance of SimplePatchTool is already running, cancel/dismiss it first!");
            }
        }
예제 #5
0
        private void InitializePatcher(string rootPath, string versionInfoURL)
        {
            patcher = SPTUtils.CreatePatcher(rootPath, versionInfoURL).UseRepairPatch(true).UseIncrementalPatch(true).LogProgress(true);

            if (!string.IsNullOrEmpty(versionInfoRSA))
            {
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
            }

            if (!string.IsNullOrEmpty(patchInfoRSA))
            {
                patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
            }
        }
        private void InitializePatcher(string rootPath, string versionInfoURL)
        {
            patcher = SPTUtils.CreatePatcher(rootPath, versionInfoURL).SetListener(patcherListener);

            if (!string.IsNullOrEmpty(versionInfoRSA))
            {
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
            }

            if (!string.IsNullOrEmpty(patchInfoRSA))
            {
                patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
            }
        }
예제 #7
0
        private void PatchButtonClicked()
        {
            bool isPatcherActive = runningPatcher != null && !runningPatcher.Equals(null);

            if (!isPatcherActive || !runningPatcher.Patcher.IsRunning)
            {
#if UNITY_EDITOR
                if (selfPatchingInput.isOn)
                {
                    Debug.LogWarning("Can't self patch while testing on editor");
                    selfPatchingInput.isOn = false;
                }
#endif

                SimplePatchTool patcher = SPTUtils.CreatePatcher(rootPathInput.text, versionInfoURLInput.text).
                                          UseRepairPatch(repairPatchInput.isOn).UseIncrementalPatch(incrementalPatchInput.isOn).UseInstallerPatch(installerPatchInput.isOn).
                                          VerifyFilesOnServer(verifyServerFilesInput.isOn).CheckForMultipleRunningInstances(checkMultipleInstancesInput.isOn);

                if (!string.IsNullOrEmpty(versionInfoRSA))
                {
                    patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
                }

                if (!string.IsNullOrEmpty(patchInfoRSA))
                {
                    patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
                }

                if (patcher.Run(selfPatchingInput.isOn))
                {
                    Debug.Log("Started patching...");
                    if (!isPatcherActive)
                    {
                        runningPatcher = Instantiate(patcherUiPrefab);
                    }

                    runningPatcher.Initialize(patcher, selfPatcherExecutable);
                }
                else
                {
                    Debug.Log("Operation could not be started; maybe it is already executing?");
                }
            }
            else
            {
                Debug.LogWarning("An instance of SimplePatchTool is already running, cancel/dismiss it first!");
            }
        }
예제 #8
0
        private SimplePatchTool InitializePatcher(string rootPath, string versionInfoURL)
        {
            SimplePatchTool patcher = SPTUtils.CreatePatcher(rootPath, versionInfoURL);

            if (!string.IsNullOrEmpty(versionInfoRSA))
            {
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, versionInfoRSA));
            }

            if (!string.IsNullOrEmpty(patchInfoRSA))
            {
                patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, patchInfoRSA));
            }

            return(patcher);
        }
예제 #9
0
        private static void CheckForUpdates()
        {
            bool   silent             = HasArgument("silent");
            string versionInfoKeyPath = GetArgument("versionInfoKey");

            SimplePatchTool patcher = new SimplePatchTool(GetArgument("root"), GetArgument("versionURL")).SilentMode(silent);

            if (versionInfoKeyPath != null)
            {
                string publicKey = File.ReadAllText(versionInfoKeyPath);
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, publicKey));
            }

            bool hasStarted = patcher.CheckForUpdates(HasArgument("checkVersionOnly"));

            if (hasStarted)
            {
                while (patcher.IsRunning)
                {
                    Thread.Sleep(100);

                    string log = patcher.FetchLog();
                    while (log != null)
                    {
                        LogToConsole(log);
                        log = patcher.FetchLog();
                    }
                }

                if (patcher.Result == PatchResult.Failed)
                {
                    Console.WriteLine("\nOperation failed: " + patcher.FailReason + " " + (patcher.FailDetails ?? ""));
                }
                else if (patcher.Result == PatchResult.AlreadyUpToDate)
                {
                    Console.WriteLine("\nAlready up-to-date!");
                }
                else
                {
                    Console.WriteLine("\nThere is an update!");
                }
            }
            else
            {
                Console.WriteLine("\nCould not check for updates; maybe an operation is already running?");
            }
        }
예제 #10
0
        private static void ApplyPatch()
        {
            bool   silent             = HasArgument("silent");
            string versionInfoKeyPath = GetArgument("versionInfoKey");
            string patchInfoKeyPath   = GetArgument("patchInfoKey");

            SimplePatchTool patcher = new SimplePatchTool(GetArgument("root"), GetArgument("versionURL")).
                                      UseIncrementalPatch(!HasArgument("dontUseIncrementalPatch")).UseRepairPatch(!HasArgument("dontUseRepairPatch")).
                                      CheckForMultipleRunningInstances(false).VerifyFilesOnServer(HasArgument("verifyFiles")).LogProgress(!silent).SilentMode(silent);

            if (versionInfoKeyPath != null)
            {
                string publicKey = File.ReadAllText(versionInfoKeyPath);
                patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, publicKey));
            }

            if (patchInfoKeyPath != null)
            {
                string publicKey = File.ReadAllText(patchInfoKeyPath);
                patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, publicKey));
            }

            bool hasPatchStarted = patcher.Run(false);

            if (hasPatchStarted)
            {
                WaitForPatcher(patcher);

                if (patcher.Result == PatchResult.Failed)
                {
                    Console.WriteLine("\nPatch failed: " + patcher.FailReason + " " + (patcher.FailDetails ?? ""));
                }
                else if (patcher.Result == PatchResult.AlreadyUpToDate)
                {
                    Console.WriteLine("\nAlready up-to-date!");
                }
                else
                {
                    Console.WriteLine("\nPatch is successful!");
                }
            }
            else
            {
                Console.WriteLine("\nPatch could not be started; maybe it is already executing?");
            }
        }
예제 #11
0
        public static void SignXml(this XmlElement unsignedXml, X509Certificate2 certificate, Guid signObjectUid)
        {
            var idAttribute = unsignedXml.Attributes["Id"];

            if (idAttribute == null)
            {
                idAttribute = unsignedXml.OwnerDocument.CreateAttribute("Id");
            }

            var attribute = unsignedXml.Attributes.Append(idAttribute);

            attribute.Value = signObjectUid.ToString();

            var signature = XMLSigner.GenerateXMLSignature(unsignedXml, unsignedXml.Attributes["Id"].Value, certificate);

            unsignedXml.AppendChild(signature);
        }
예제 #12
0
        public static bool ValidateSignature(this XmlElement signedXml)
        {
            var sig = (XmlElement)signedXml.GetSubnode("Signature");

            if (sig == null || sig.ParentNode != signedXml)
            {
                throw new Exception("Signature element not found");
            }

            signedXml.RemoveChild(sig);

            var result = XMLSigner.VerifyXMLSignature(signedXml, sig);

            signedXml.AppendChild(sig);

            return(result);
        }
예제 #13
0
 private static void VerifyXML()
 {
     Console.WriteLine("Result: " + XMLSigner.VerifyXMLFile(GetArgument("xml"), File.ReadAllText(GetArgument("key"))));
 }
예제 #14
0
 private static void SignXML()
 {
     XMLSigner.SignXMLFile(GetArgument("xml"), File.ReadAllText(GetArgument("key")));
 }
예제 #15
0
        private void InitializePatcher()
        {
            if (m_patcher != null)
            {
                return;
            }

            m_patcher = SPTUtils.CreatePatcher(RootPath, VersionInfoURL).CheckForMultipleRunningInstances(CheckForMultipleRunningInstances).
                        UseRepairPatch(UseRepairPatch).UseIncrementalPatch(UseIncrementalPatch).UseInstallerPatch(UseInstallerPatch).
                        VerifyFilesOnServer(VerifyFilesOnServer).SilentMode(SilentMode).LogProgress(LogProgress).LogToFile(LogToFile);

            if (!string.IsNullOrEmpty(VersionInfoRSA))
            {
                m_patcher.UseVersionInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, VersionInfoRSA));
            }

            if (!string.IsNullOrEmpty(PatchInfoRSA))
            {
                m_patcher.UsePatchInfoVerifier(( ref string xml ) => XMLSigner.VerifyXMLContents(xml, PatchInfoRSA));
            }

            PatcherListener listener = new PatcherListener();

            listener.OnStart += () =>
            {
                if (m_patcher.Operation == PatchOperation.CheckingForUpdates)
                {
                    CheckForUpdatesStarted.Invoke();
                }
                else if (m_patcher.Operation == PatchOperation.Patching || m_patcher.Operation == PatchOperation.SelfPatching)
                {
                    PatchStarted.Invoke();
                }
            };
            listener.OnLogReceived += (log) =>
            {
                LogReceived.Invoke(log);

                if (LogToConsole)
                {
                    Debug.Log(log);
                }
            };
            listener.OnProgressChanged += (progress) =>
            {
                CurrentProgressPercentageChanged.Invoke(progress.Percentage);
                CurrentProgressTextChanged.Invoke(progress.ProgressInfo);
            };
            listener.OnOverallProgressChanged += (progress) =>
            {
                OverallProgressPercentageChanged.Invoke(progress.Percentage);
                OverallProgressTextChanged.Invoke(progress.ProgressInfo);
            };
            listener.OnPatchStageChanged  += PatchStageChanged.Invoke;
            listener.OnPatchMethodChanged += PatchMethodChanged.Invoke;
            listener.OnVersionInfoFetched += (versionInfo) =>
            {
                for (int i = 0; i < AdditionalIgnoredPaths.Length; i++)
                {
                    if (!string.IsNullOrEmpty(AdditionalIgnoredPaths[i]))
                    {
                        versionInfo.AddIgnoredPath(AdditionalIgnoredPaths[i]);
                    }
                }

                VersionInfoFetched.Invoke(versionInfo);
            };
            listener.OnVersionFetched += (currentVersion, newVersion) =>
            {
                CurrentVersionDetermined.Invoke(currentVersion);
                NewVersionDetermined.Invoke(newVersion);
            };
            listener.OnFinish += () =>
            {
                if (m_patcher.Operation == PatchOperation.CheckingForUpdates)
                {
                    if (m_patcher.Result == PatchResult.AlreadyUpToDate)
                    {
                        AppIsUpToDate.Invoke();
                    }
                    else if (m_patcher.Result == PatchResult.Success)
                    {
                        UpdateAvailable.Invoke();
                    }
                    else
                    {
                        CheckForUpdatesFailed.Invoke(m_patcher.FailDetails);

                        if (LogToConsole)
                        {
                            Debug.LogError(m_patcher.FailDetails);
                        }
                    }
                }
                else if (m_patcher.Operation == PatchOperation.Patching || m_patcher.Operation == PatchOperation.SelfPatching)
                {
                    if (m_patcher.Result == PatchResult.AlreadyUpToDate)
                    {
                        AppIsUpToDate.Invoke();
                    }
                    else if (m_patcher.Result == PatchResult.Success)
                    {
                        PatchSuccessful.Invoke();

                        if (m_patcher.Operation == PatchOperation.Patching)
                        {
                            CurrentVersionDetermined.Invoke(m_patcher.NewVersion);
                        }
                    }
                    else
                    {
                        PatchFailed.Invoke(m_patcher.FailDetails);

                        if (LogToConsole)
                        {
                            Debug.LogError(m_patcher.FailDetails);
                        }
                    }
                }
                else
                {
                    if (m_patcher.Result == PatchResult.AlreadyUpToDate)
                    {
                        AppIsUpToDate.Invoke();
                    }
                    else if (m_patcher.Result == PatchResult.Failed)
                    {
                        SelfPatchingFailed.Invoke(m_patcher.FailDetails);

                        if (LogToConsole)
                        {
                            Debug.LogError(m_patcher.FailDetails);
                        }
                    }
                }
            };

            m_patcher.SetListener(listener);
        }