public static int SignFile(string hash, string container, string str_store, string pin, string timestamp_url, string str_mode, string fileToSign, string timestamp_algorithm) { var certHash = hash ?? options.hash; var containerName = container ?? options.container ?? Properties.Settings.Default.Container; var targetStore = str_store ?? options.store ?? Properties.Settings.Default.Store; var tokenPin = pin ?? options.pin; var timestampUrl = timestamp_url ?? options.timestamp_url ?? Properties.Settings.Default.TimestampUrl; var mode = str_mode ?? options.mode ?? Properties.Settings.Default.Mode; var timestampAlgorithm = timestamp_algorithm ?? options.timestamp_argorithm ?? Properties.Settings.Default.TimestampAlgorithm; var verbose = options.verbose; try { var signMode = ParseMode(mode); var store = ParseStore(targetStore); // string szOID_NIST_sha256 = "2.16.840.1.101.3.4.2.1"; CodeSigner.SignFile(certHash, tokenPin, containerName, store, fileToSign, timestampUrl, signMode, null, new Logger(verbose), timestampAlgorithm); return(0); } catch (SigningException ex) { Console.Error.WriteLine("Signing operation failed. Error details:"); Console.Error.WriteLine(ex.GetBaseException().Message); return(2); } }
/** * Using the stub IPA previously compiled on the Mac, create a new IPA with assets */ static public void RepackageIPAFromStub() { if (string.IsNullOrEmpty(Config.RepackageStagingDirectory) || !Directory.Exists(Config.RepackageStagingDirectory)) { Program.Error("Directory specified with -stagedir could not be found!"); return; } DateTime StartTime = DateTime.Now; CodeSignatureBuilder CodeSigner = null; // Clean the staging directory Program.ExecuteCommand("Clean", null); // Create a copy of the IPA so as to not trash the original ZipFile Zip = SetupWorkIPA(); if (Zip == null) { return; } string ZipWorkingDir = String.Format("Payload/{0}{1}.app/", Program.GameName, Program.Architecture); FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(Zip, ZipWorkingDir); // Check for a staged plist that needs to be merged into the main one { // Determine if there is a staged one we should try to use instead string PossiblePList = Path.Combine(Config.RepackageStagingDirectory, "Info.plist"); if (File.Exists(PossiblePList)) { if (Config.bPerformResignWhenRepackaging) { Program.Log("Found Info.plist ({0}) in stage, which will be merged in with stub plist contents", PossiblePList); // Merge the two plists, using the staged one as the authority when they conflict byte[] StagePListBytes = File.ReadAllBytes(PossiblePList); string StageInfoString = Encoding.UTF8.GetString(StagePListBytes); byte[] StubPListBytes = FileSystem.ReadAllBytes("Info.plist"); Utilities.PListHelper StubInfo = new Utilities.PListHelper(Encoding.UTF8.GetString(StubPListBytes)); StubInfo.MergePlistIn(StageInfoString); // Write it back to the cloned stub, where it will be used for all subsequent actions byte[] MergedPListBytes = Encoding.UTF8.GetBytes(StubInfo.SaveToString()); FileSystem.WriteAllBytes("Info.plist", MergedPListBytes); } else { Program.Warning("Found Info.plist ({0}) in stage that will be ignored; IPP cannot combine it with the stub plist since -sign was not specified", PossiblePList); } } } // Get the name of the executable file string CFBundleExecutable; { // Load the .plist from the stub byte[] RawInfoPList = FileSystem.ReadAllBytes("Info.plist"); Utilities.PListHelper Info = new Utilities.PListHelper(Encoding.UTF8.GetString(RawInfoPList)); // Get the name of the executable file if (!Info.GetString("CFBundleExecutable", out CFBundleExecutable)) { throw new InvalidDataException("Info.plist must contain the key CFBundleExecutable"); } } // Tell the file system about the executable file name so that we can set correct attributes on // the file when zipping it up FileSystem.ExecutableFileName = CFBundleExecutable; // Prepare for signing if requested if (Config.bPerformResignWhenRepackaging) { // Start the resign process (load the mobileprovision and info.plist, find the cert, etc...) CodeSigner = new CodeSignatureBuilder(); CodeSigner.FileSystem = FileSystem; CodeSigner.PrepareForSigning(); // Merge in any user overrides that exist UpdateVersion(CodeSigner.Info); } // Empty the current staging directory FileOperations.DeleteDirectory(new DirectoryInfo(Config.PCStagingRootDir)); // we will zip files in the pre-staged payload dir string ZipSourceDir = Config.RepackageStagingDirectory; // Save the zip Program.Log("Saving IPA ..."); FilesBeingModifiedToPrintOut.Clear(); Zip.SaveProgress += UpdateSaveProgress; Zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)Config.RecompressionSetting; // Add all of the payload files, replacing existing files in the stub IPA if necessary (should only occur for icons) { string SourceDir = Path.GetFullPath(ZipSourceDir); string[] PayloadFiles = Directory.GetFiles(SourceDir, "*.*", SearchOption.AllDirectories); foreach (string Filename in PayloadFiles) { // Get the relative path to the file (this implementation only works because we know the files are all // deeper than the base dir, since they were generated from a search) string AbsoluteFilename = Path.GetFullPath(Filename); string RelativeFilename = AbsoluteFilename.Substring(SourceDir.Length + 1).Replace('\\', '/'); string ZipAbsolutePath = String.Format("Payload/{0}{1}.app/{1}", Program.GameName, Program.Architecture, RelativeFilename); byte[] FileContents = File.ReadAllBytes(AbsoluteFilename); if (FileContents.Length == 0) { // Zero-length files added by Ionic cause installation/upgrade to fail on device with error 0xE8000050 // We store a single byte in the files as a workaround for now FileContents = new byte[1]; FileContents[0] = 0; } FileSystem.WriteAllBytes(RelativeFilename, FileContents); if ((FileContents.Length >= 1024 * 1024) || (Config.bVerbose)) { FilesBeingModifiedToPrintOut.Add(ZipAbsolutePath); } } } // Re-sign the executable if there is a signing context if (CodeSigner != null) { if (Config.OverrideBundleName != null) { CodeSigner.Info.SetString("CFBundleDisplayName", Config.OverrideBundleName); string CFBundleIdentifier; if (CodeSigner.Info.GetString("CFBundleIdentifier", out CFBundleIdentifier)) { CodeSigner.Info.SetString("CFBundleIdentifier", CFBundleIdentifier + "_" + Config.OverrideBundleName); } } CodeSigner.PerformSigning(); } // Stick in the iTunesArtwork PNG if available string iTunesArtworkPath = Path.Combine(Config.BuildDirectory, "iTunesArtwork"); if (File.Exists(iTunesArtworkPath)) { Zip.UpdateFile(iTunesArtworkPath, ""); } // Save the Zip Program.Log("Compressing files into IPA (-compress={1}).{0}", Config.bVerbose ? "" : " Only large files will be listed next, but other files are also being packaged.", Config.RecompressionSetting); FileSystem.Close(); TimeSpan ZipLength = DateTime.Now - StartTime; FileInfo FinalZipInfo = new FileInfo(Zip.Name); Program.Log(String.Format("Finished repackaging into {2:0.00} MB IPA, written to '{0}' (took {1:0.00} s for all steps)", Zip.Name, ZipLength.TotalSeconds, FinalZipInfo.Length / (1024.0f * 1024.0f))); }