public Result UnregisterAllExternalKey() { ExternalKeys.Clear(); return(Result.Success); }
public Result RegisterExternalKey(ref RightsId rightsId, ref AccessKey externalKey) { return(ExternalKeys.Add(rightsId, externalKey)); }
public Result UnregisterExternalKey(ref RightsId rightsId) { ExternalKeys.Remove(rightsId); return(Result.Success); }
//Open update only private void Open_NSP_Update(object sender, EventArgs e) { var Dialog = openFileDialog1.ShowDialog(); if (Dialog != DialogResult.Cancel) { Console.WriteLine("LOADING."); label8.Visible = true; this.Update(); treeView1.Nodes.Clear(); string FileToOpen = null; if (Program.FileArg != null) { FileToOpen = Program.FileArg; } else { FileToOpen = openFileDialog1.FileName; } Program.FileArg = null; Stream Input = null; try { string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In); var ProdKeys = ExpEnv(@"%USERPROFILE%\.switch\prod.keys"); var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys"); Console.WriteLine(FileToOpen); var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys); var Ext = (new FileInfo(FileToOpen).Extension); if (Ext == ".nsp") { var InputPFS = File.OpenRead(FileToOpen); var Pfs = new Pfs(InputPFS.AsStorage()); var CnmtNca = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false); var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true)); var Cnmt = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream()); var Program = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program); var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control); if (CtrlEntry != null) { Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false); } Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream(); } else { Input = File.OpenRead(FileToOpen); } try { Nca = new Nca(Keys, Input.AsStorage(), true); if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId))) { MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file."); } else { var isUpdateNca = false; if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr)) { isUpdateNca = true; } if (isUpdateNca) { var InputPFS = File.OpenRead(FileToOpen); var Pfs = new Pfs(InputPFS.AsStorage()); var CnmtNca = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false); var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true)); var Cnmt = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream()); var Program = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program); var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control); if (CtrlEntry != null) { Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false); } Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream(); var Input2 = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream(); Patch = new Nca(Keys, Input2.AsStorage(), true); Nca.SetBaseNca(Patch); } new Thread (() => { Thread.CurrentThread.IsBackground = true; var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}"); label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; })); }).Start(); Rom = new Romfs( Nca.OpenSection(Nca.Sections.FirstOrDefault (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr) .SectionNum, false, IntegrityCheckLevel.None, true) ); IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir); Console.WriteLine("DONE."); fileToolStripMenuItem.Text = "File / Explore"; label8.Visible = false; this.Update(); } } catch { MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?"); } } catch (ArgumentNullException) { MessageBox.Show("Error: key files are missing!"); } } }
private void Open() { treeView1.Nodes.Clear(); string FileToOpen = null; if (Program.FileArg != null) { FileToOpen = Program.FileArg; } else { FileToOpen = openFileDialog1.FileName; } Program.FileArg = null; Stream Input = null; try { string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In); var ProdKeys = ExpEnv(@"%USERPROFILE%\.switch\prod.keys"); var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys"); var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys); var Ext = (new FileInfo(FileToOpen).Extension); if (Ext == ".nsp") { var InputPFS = File.OpenRead(FileToOpen); var Pfs = new Pfs(InputPFS); var CnmtNca = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false); var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None)); var Cnmt = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0])); var Program = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program); var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control); if (CtrlEntry != null) { Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false); } Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca"); } else if (Ext == ".xci") { var InputPFS = File.OpenRead(FileToOpen); var Xci = new Xci(Keys, InputPFS); var CnmtNca = new Nca(Keys, Xci.SecurePartition.OpenFile(Xci.SecurePartition.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false); var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None)); var Cnmt = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0])); var Program = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program); var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control); if (CtrlEntry != null) { Control = new Nca(Keys, Xci.SecurePartition.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false); } Input = Xci.SecurePartition.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca"); } else if (FileToOpen.Split('.')[1] == "cnmt" && Ext == ".nca") { var TargetFile = File.OpenRead(FileToOpen); var CnmtNca = new Nca(Keys, TargetFile, false); var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None)); var Cnmt = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0])); var Program = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program); var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control); if (CtrlEntry != null) { Control = new Nca(Keys, File.OpenRead($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false); } Input = File.OpenRead($"{Program.NcaId.ToHexString().ToLower()}.nca"); } else { Input = File.OpenRead(FileToOpen); } try { Nca = new Nca(Keys, Input, true); if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId))) { MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file."); } else { bool isUpdateNca = false; if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr)) { isUpdateNca = true; } if (isUpdateNca) { openFileDialog1.Title = "Select base Nca"; openFileDialog1.ShowDialog(); var Input2 = File.OpenRead(openFileDialog1.FileName); Patch = new Nca(Keys, Input2, true); Nca.SetBaseNca(Patch); } new Thread ( () => { Thread.CurrentThread.IsBackground = true; var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}"); label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; })); } ) .Start(); Rom = new Romfs ( Nca.OpenSection ( Nca.Sections.FirstOrDefault (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr) .SectionNum, false, IntegrityCheckLevel.None ) ); IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir); } } catch { MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?"); } } catch (ArgumentNullException) { MessageBox.Show("Error: key files are missing!"); } }
public static bool initialize(out List <string> messages) { messages = new List <string>(); string prod_keys = path_prefix + Common.PROD_KEYS; string title_keys = path_prefix + Common.TITLE_KEYS; string console_keys = path_prefix + Common.CONSOLE_KEYS; if (!File.Exists(prod_keys)) { messages.Add("File not found. Check if '" + Common.PROD_KEYS + "' exist and try again."); return(false); } if (Common.Settings.Default.DebugLog) { try { log = File.AppendText(path_prefix + Common.LOG_FILE); log.AutoFlush = true; } catch { } } log?.WriteLine("--------------------------------------------------------------"); log?.WriteLine("Application starts at {0}\n", String.Format("{0:F}", DateTime.Now)); try { log?.WriteLine("Reading keys"); log?.WriteLine(" - {0} ({1}exists)", prod_keys, File.Exists(prod_keys) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", title_keys, File.Exists(title_keys) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", console_keys, File.Exists(console_keys) ? "" : "not "); keyset = ExternalKeys.ReadKeyFile(prod_keys, title_keys, console_keys); log?.WriteLine("Found {0} title keys", keyset?.TitleKeys?.Count); titleNames = keyset.TitleNames.ToDictionary(p => BitConverter.ToString(p.Key.Take(8).ToArray()).Replace("-", "").ToUpper(), p => p.Value); titleVersions = keyset.TitleVersions.ToDictionary(p => BitConverter.ToString(p.Key.Take(8).ToArray()).Replace("-", "").ToUpper(), p => p.Value); } catch { } try { if (!(bool)keyset?.HeaderKey?.Any(b => b != 0) || !(bool)keyset?.AesKekGenerationSource?.Any(b => b != 0) || !(bool)keyset?.AesKeyGenerationSource?.Any(b => b != 0) || !(bool)keyset?.KeyAreaKeyApplicationSource?.Any(b => b != 0) || !((bool)keyset?.MasterKeys?[0]?.Any(b => b != 0) || (bool)keyset?.KeyAreaKeys?[0]?[0]?.Any(b => b != 0))) { log?.WriteLine("Keyfile missing required keys"); log?.WriteLine(" - {0} ({1}exists)", "header_key", (bool)keyset?.HeaderKey?.Any(b => b != 0) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", "aes_kek_generation_source", (bool)keyset?.AesKekGenerationSource?.Any(b => b != 0) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", "aes_key_generation_source", (bool)keyset?.AesKeyGenerationSource?.Any(b => b != 0) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", "key_area_key_application_source", (bool)keyset?.KeyAreaKeyApplicationSource?.Any(b => b != 0) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", "master_key_00", (bool)keyset?.MasterKeys[0]?.Any(b => b != 0) ? "" : "not "); log?.WriteLine(" - {0} ({1}exists)", "key_area_key_application_00", (bool)keyset?.KeyAreaKeys[0][0]?.Any(b => b != 0) ? "" : "not "); messages.Add("Keyfile missing required keys. Check if these keys exist and try again.\n" + "header_key, aes_kek_generation_source, aes_key_generation_source, key_area_key_application_source, master_key_00 or key_area_key_application_00."); return(false); } } catch { messages.Add("Keyfile missing required keys. Check if these keys exist and try again.\n" + "header_key, aes_kek_generation_source, aes_key_generation_source, key_area_key_application_source, master_key_00 or key_area_key_application_00."); return(false); } string hac_versionlist = path_prefix + Common.HAC_VERSIONLIST; try { log?.WriteLine("Reading version list"); var versionlist = JsonConvert.DeserializeObject <Common.VersionList>(File.ReadAllText(hac_versionlist)); foreach (var title in versionlist.titles) { string titleID = title.id; if (titleID.EndsWith("800")) { titleID = titleID.Substring(0, Math.Min(titleID.Length, 13)) + "000"; } versionList.TryGetValue(titleID.ToUpper(), out uint version); versionList[titleID.ToUpper()] = Math.Max(version, title.version); } log?.WriteLine("Found {0} titles, last modified at {1}", versionList.Count, versionlist.last_modified); } catch { } log?.WriteLine("Initialization success"); return(true); }
static void Main(string[] args) { Console.WriteLine("Nintendo Switch NSP Verifier v1.00"); Console.WriteLine("Copyright 2018 CaitSith2"); Console.WriteLine(""); _path = args.Length >= 1 ? string.Join(" ", args) : Environment.CurrentDirectory; if (new[] { "--help", "-h" }.Any(x => x.Equals(_path, StringComparison.InvariantCultureIgnoreCase))) { Console.WriteLine("Usage: NSPVerify [path to NSP directory]"); Console.WriteLine(""); Console.WriteLine("If the tool is run without specifying a path, it will look for NSPs in the current directory and ALL sub-directories of current directory"); return; } if (!Directory.Exists(_path)) { Console.WriteLine("ERROR: Specified directory does not exist. specify --help for usage information."); return; } var fs = new FileSystem(_path); var keys = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys"); if (File.Exists("keys.txt")) { keys = "keys.txt"; } if (!File.Exists(keys)) { Console.WriteLine($"Cannot verify NSPs without keys.txt. Either put it in the same directory as this tool,"); Console.WriteLine($"or place it in \"{Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch")}\" named as prod.keys"); PressAnyKey(); return; } var keyset = ExternalKeys.ReadKeyFile(keys); var badlist = new List <string>(); var exceptionlist = new List <string>(); var files = fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories).ToList(); files.AddRange(fs.GetFileSystemEntries("", "*.nsx", SearchOption.AllDirectories)); if (files.Count == 0) { Console.WriteLine("Error: No NSP/NSX files in specified directory"); PressAnyKey(); return; } foreach (var file in files) { var filename = Path.GetFileName(file); var relativefilename = Util.GetRelativePath(file, Path.GetFullPath(_path)); Console.Write($"Checking {filename}: "); try { bool ok = true; using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read)) { var nspdata = new Pfs(nspfile); var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca")); if (cnmtfile == null) { Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present"); badlist.Add(relativefilename); continue; } var cnmtdata = nspdata.OpenFile(cnmtfile); Cnmt cnmt; using (var sr = new BinaryReader(cnmtdata)) { var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length)); if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString())) { //Put failure here Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted"); badlist.Add(relativefilename); cnmtdata.Dispose(); continue; } cnmtdata.Position = 0; var cnmtnca = new Nca(keyset, cnmtdata, false); var section = cnmtnca.OpenSection(0, false); var sectionpfs = new Pfs(section); cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0])); } foreach (var entry in cnmt.ContentEntries) { var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca")); if (entryfile == null) { if (entry.Type != CnmtContentType.UpdatePatch) { //Put failure here Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing."); badlist.Add(relativefilename); break; } continue; } using (var entrynca = nspdata.OpenFile(entryfile)) { var hash = SHA256.Create(); using (var sr = new BinaryReader(entrynca)) { while (entrynca.Length != entrynca.Position) { var entryncadata = sr.ReadBytes(0x100000); hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0); Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%"); } hash.TransformFinalBlock(new byte[0], 0, 0); } if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString())) { Console.Write($"\rChecking {filename}: {100:0.0}%"); continue; } //Put failure here Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted"); badlist.Add(relativefilename); ok = false; break; } } if (ok) { Console.WriteLine($"\rChecking {filename}: OK "); } //Put Success here } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); exceptionlist.Add($"{relativefilename}{Environment.NewLine}Exception: \"{ex.GetType()}\" {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}"); } } badlist.Insert(0, badlist.Count == 0 ? "None of the files are corrupted. :)" : "The following NSP/NSX files are corrupted:"); exceptionlist.Insert(0, exceptionlist.Count == 0 ? "No exceptions to log. :)" : "Exceptions caused while parsing the following NSP/NSX files:"); try { File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist)); File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist)); } catch (Exception ex) { Console.WriteLine($"Could not write the output files \"Corrupted NSPs.txt\" and \"Exception Log.txt\" due to the following exception."); Console.WriteLine($"Exception: \"{ex.GetType()}\" {ex.Message}"); Console.WriteLine($"Stack Trace: {ex.StackTrace}{Environment.NewLine}"); Console.WriteLine(string.Join(Environment.NewLine, badlist)); Console.WriteLine(); Console.WriteLine(string.Join(Environment.NewLine, exceptionlist)); Console.WriteLine(); } Console.WriteLine("Done."); PressAnyKey(); }
private void OnNandFound() { Nand nand = NANDService.NAND; Stream NANDSource = NANDService.NANDSource; NANDSource.Seek(0x804000, SeekOrigin.Begin); // BCPKG2-1-Normal-Main offset + length of BootConfig FileStream pkg2stream = HACGUIKeyset.TempPkg2FileInfo.Create(); NANDSource.CopyToNew(pkg2stream, 0x7FC000); // rest of BCPPKG2-Normal-Main partition pkg2stream.Seek(0, SeekOrigin.Begin); byte[] pkg2raw = new byte[pkg2stream.Length]; pkg2stream.Read(pkg2raw, 0, pkg2raw.Length); Package2 pkg2 = new Package2(HACGUIKeyset.Keyset, new MemoryStream(pkg2raw)); HACGUIKeyset.RootTempPkg2FolderInfo.Create(); FileStream kernelstream = HACGUIKeyset.TempKernelFileInfo.Create(); FileStream INI1stream = HACGUIKeyset.TempINI1FileInfo.Create(); pkg2.OpenKernel().CopyTo(kernelstream); pkg2.OpenIni1().CopyTo(INI1stream); kernelstream.Close(); INI1stream.Close(); Ini1 INI1 = new Ini1(pkg2.OpenIni1()); List <HashSearchEntry> hashes = new List <HashSearchEntry>(); Dictionary <byte[], byte[]> keys = new Dictionary <byte[], byte[]>(); HACGUIKeyset.RootTempINI1Folder.Create(); foreach (Kip kip in INI1.Kips) { Stream rodatastream, datastream; switch (kip.Header.Name) { case "FS": hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeyApplicationSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeyOceanSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.KeyAreaKeySystemSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.HeaderKekSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.SaveMacKekSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.SaveMacKeySourceHash, 0x10)); rodatastream = new MemoryStream(kip.DecompressSection(1)); keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10); Array.Copy(keys[NintendoKeys.KeyAreaKeyApplicationSourceHash], HACGUIKeyset.Keyset.KeyAreaKeyApplicationSource, 0x10); Array.Copy(keys[NintendoKeys.KeyAreaKeyOceanSourceHash], HACGUIKeyset.Keyset.KeyAreaKeyOceanSource, 0x10); Array.Copy(keys[NintendoKeys.KeyAreaKeySystemSourceHash], HACGUIKeyset.Keyset.KeyAreaKeySystemSource, 0x10); Array.Copy(keys[NintendoKeys.HeaderKekSourceHash], HACGUIKeyset.Keyset.HeaderKekSource, 0x10); Array.Copy(keys[NintendoKeys.SaveMacKekSourceHash], HACGUIKeyset.Keyset.SaveMacKekSource, 0x10); Array.Copy(keys[NintendoKeys.SaveMacKeySourceHash], HACGUIKeyset.Keyset.SaveMacKeySource, 0x10); hashes.Clear(); rodatastream.Seek(0, SeekOrigin.Begin); bool sdWarn = false; hashes.Add(new HashSearchEntry(NintendoKeys.SDCardKekSourceHash, 0x10)); try { keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10); Array.Copy(keys[NintendoKeys.SDCardKekSourceHash], HACGUIKeyset.Keyset.SdCardKekSource, 0x10); } catch (EndOfStreamException) { MessageBox.Show("Failed to find SD card kek source! The NAND is probably from 1.0.0."); sdWarn = true; } if (!sdWarn) // don't try to find the rest of the keys if the other one couldn't be found { hashes.Clear(); rodatastream.Seek(0, SeekOrigin.Begin); hashes.Add(new HashSearchEntry(NintendoKeys.SDCardSaveKeySourceHash, 0x20)); hashes.Add(new HashSearchEntry(NintendoKeys.SDCardNcaKeySourceHash, 0x20)); keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x20); Array.Copy(keys[NintendoKeys.SDCardSaveKeySourceHash], HACGUIKeyset.Keyset.SdCardKeySources[0], 0x20); Array.Copy(keys[NintendoKeys.SDCardNcaKeySourceHash], HACGUIKeyset.Keyset.SdCardKeySources[1], 0x20); } hashes.Clear(); rodatastream.Close(); hashes.Add(new HashSearchEntry(NintendoKeys.HeaderKeySourceHash, 0x20)); datastream = new MemoryStream(kip.DecompressSection(2)); keys = datastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x20); Array.Copy(keys[NintendoKeys.HeaderKeySourceHash], HACGUIKeyset.Keyset.HeaderKeySource, 0x20); datastream.Close(); hashes.Clear(); break; case "spl": hashes.Add(new HashSearchEntry(NintendoKeys.AesKeyGenerationSourceHash, 0x10)); rodatastream = new MemoryStream(kip.DecompressSection(1)); keys = rodatastream.FindKeyViaHash(hashes, new SHA256Managed(), 0x10); Array.Copy(keys[NintendoKeys.AesKeyGenerationSourceHash], HACGUIKeyset.Keyset.AesKeyGenerationSource, 0x10); rodatastream.Close(); hashes.Clear(); break; } FileStream kipstream = HACGUIKeyset.RootTempINI1Folder.GetFile(kip.Header.Name + ".kip").Create(); kip.OpenRawFile().CopyTo(kipstream); kipstream.Close(); } pkg2stream.Close(); INI1stream.Close(); HACGUIKeyset.Keyset.DeriveKeys(); SwitchFs fs = new SwitchFs(HACGUIKeyset.Keyset, NANDService.NAND.OpenSystemPartition()); foreach (KeyValuePair <string, Nca> kv in fs.Ncas) { Nca nca = kv.Value; switch (nca.Header.TitleId) { case 0x0100000000000033: // es switch (nca.Header.ContentType) { case ContentType.Program: NcaSection exefsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0); Stream pfsStream = nca.OpenSection(exefsSection.SectionNum, false, false); Pfs pfs = new Pfs(pfsStream); Nso nso = new Nso(pfs.OpenFile("main")); NsoSection section = nso.Sections[1]; Stream data = new MemoryStream(section.DecompressSection()); hashes.Clear(); hashes.Add(new HashSearchEntry(NintendoKeys.EticketRsaKekSourceHash, 0x10)); hashes.Add(new HashSearchEntry(NintendoKeys.EticketRsaKekekSourceHash, 0x10)); keys = data.FindKeyViaHash(hashes, new SHA256Managed(), 0x10, data.Length); byte[] EticketRsaKekSource = new byte[0x10]; byte[] EticketRsaKekekSource = new byte[0x10]; Array.Copy(keys[NintendoKeys.EticketRsaKekSourceHash], EticketRsaKekSource, 0x10); Array.Copy(keys[NintendoKeys.EticketRsaKekekSourceHash], EticketRsaKekekSource, 0x10); byte[] RsaOaepKekGenerationSource; XOR(NintendoKeys.KekMasks[0], NintendoKeys.KekSeeds[3], out RsaOaepKekGenerationSource); byte[] key1 = new byte[0x10]; Crypto.DecryptEcb(HACGUIKeyset.Keyset.MasterKeys[0], RsaOaepKekGenerationSource, key1, 0x10); byte[] key2 = new byte[0x10]; Crypto.DecryptEcb(key1, EticketRsaKekekSource, key2, 0x10); byte[] key3 = new byte[0x10]; Crypto.DecryptEcb(key2, EticketRsaKekSource, HACGUIKeyset.Keyset.EticketRsaKek, 0x10); break; } break; } } Stream prodinfo = nand.OpenProdInfo(); Stream prodinfoFile = HACGUIKeyset.TempPRODINFOFileInfo.Create(); prodinfo.CopyTo(prodinfoFile); prodinfo.Close(); prodinfoFile.Seek(0, SeekOrigin.Begin); Calibration cal0 = new Calibration(prodinfoFile); HACGUIKeyset.Keyset.EticketExtKeyRsa = Crypto.DecryptRsaKey(cal0.EticketExtKeyRsa, HACGUIKeyset.Keyset.EticketRsaKek); prodinfoFile.Close(); List <Ticket> tickets = new List <Ticket>(); NandPartition system = nand.OpenSystemPartition(); Stream e1Stream = system.OpenFile("save\\80000000000000E1", FileMode.Open, FileAccess.Read); tickets.AddRange(ReadTickets(HACGUIKeyset.Keyset, e1Stream)); Stream e2Stream = system.OpenFile("save\\80000000000000E2", FileMode.Open, FileAccess.Read); tickets.AddRange(ReadTickets(HACGUIKeyset.Keyset, e2Stream)); Stream nsAppmanStream = system.OpenFile("save\\8000000000000043", FileMode.Open, FileAccess.Read); Savefile save = new Savefile(HACGUIKeyset.Keyset, nsAppmanStream, false); Stream privateStream = save.OpenFile("/private"); byte[] sdSeed = new byte[0x10]; privateStream.Read(sdSeed, 0, 0x10); // Seek doesn't work so i just read twice privateStream.Read(sdSeed, 0, 0x10); HACGUIKeyset.Keyset.SetSdSeed(sdSeed); foreach (Ticket ticket in tickets) { HACGUIKeyset.Keyset.TitleKeys[ticket.RightsId] = new byte[0x10]; Array.Copy(ticket.TitleKeyBlock, HACGUIKeyset.Keyset.TitleKeys[ticket.RightsId], 0x10); } NANDService.Stop(); HACGUIKeyset.ProductionKeysFileInfo.Create().WriteString(HACGUIKeyset.PrintCommonKeys(HACGUIKeyset.Keyset, true)); HACGUIKeyset.ExtraKeysFileInfo.Create().WriteString(HACGUIKeyset.PrintCommonWithoutFriendlyKeys(HACGUIKeyset.Keyset)); HACGUIKeyset.ConsoleKeysFileInfo.Create().WriteString(ExternalKeys.PrintUniqueKeys(HACGUIKeyset.Keyset)); HACGUIKeyset.GetConsoleKeysFileInfoByName(PickConsole.ConsoleName).Create().WriteString(ExternalKeys.PrintUniqueKeys(HACGUIKeyset.Keyset)); HACGUIKeyset.TitleKeysFileInfo.Create().WriteString(ExternalKeys.PrintTitleKeys(HACGUIKeyset.Keyset)); }
private static void ProcessKeygen(Context ctx) { Console.WriteLine(ExternalKeys.PrintCommonKeys(ctx.Keyset)); }
public MainPage() { InitializeComponent(); Loaded += (_, __) => { void rcmRefresh(bool b) { foreach (MenuItem item in RCMContextMenu.Items.Cast <MenuItem>().Where(i => i.Tag as string == "RequiresRCM")) { item.IsEnabled = b; } }; rcmRefresh(InjectService.LibusbKInstalled); void nandRefresh(bool b) { foreach (MenuItem item in NANDContextMenu.Items.Cast <MenuItem>().Where(i => i.Tag as string == "RequiresNAND")) { item.IsEnabled = b; } }; nandRefresh(false); InjectService.DeviceInserted += () => { if (InjectService.LibusbKInstalled) { Dispatcher.Invoke(() => rcmRefresh(true)); } }; InjectService.DeviceRemoved += () => { Dispatcher.Invoke(() => rcmRefresh(false)); }; NANDService.OnNANDPluggedIn += () => { Dispatcher.Invoke(() => nandRefresh(true)); }; NANDService.OnNANDRemoved += () => { Dispatcher.Invoke(() => nandRefresh(false)); }; SDService.OnSDPluggedIn += (drive) => { DirectoryInfo root = drive.RootDirectory; DirectoryInfo switchDir = root.GetDirectory("switch"); if (switchDir.Exists) { FileInfo prodKeysInfo = switchDir.GetFile("prod.keys"); if (prodKeysInfo.Exists) { try { ExternalKeys.ReadKeyFile(HACGUIKeyset.Keyset, prodKeysInfo.FullName); new SaveKeysetTask(null).CreateTask().RunSynchronously(); } catch (Exception e) { MessageBox.Show($"An error occured when attempting to import keys from SD card. It could be corrupted.\nError: {e.Message}"); } } } }; // init this first as other pages may request tasks on init TaskManagerView = new TaskManagerPage(); TaskManagerFrame.Content = TaskManagerView; StatusService.Bar = StatusBar; StatusService.CurrentTaskBlock = CurrentTaskBlock; CurrentTaskBlock.Background = StatusBar.Background; TaskManagerView.Queue.Submit(new RunTask("Opening/Deriving keys...", new Task(() => HACGUIKeyset.Keyset.LoadAll()))); DeviceService.Start(); TitleManagerView = new MainTitleManagerPage(); TitleManagerFrame.Content = TitleManagerView; SaveManagerView = new SaveManagerPage(0); SaveManagerFrame.Content = SaveManagerView; StatusService.Start(); if (Native.IsAdministrator) { AdminButton.IsEnabled = false; } }; }
private static void Main(string[] args) { var keyFile = Environment.ExpandEnvironmentVariables("%USERPROFILE%/.switch/prod.keys"); var keysInUserDir = true; var getDeltasOnly = false; #region Pre-execution checks if (!File.Exists(keyFile)) { if (!File.Exists("prod.keys")) { Console.Error.WriteLine("Error: prod.keys is missing!"); return; } else { keysInUserDir = false; } } if (!File.Exists("edge.token")) { Console.Error.WriteLine("Error: Please add an edge token to a file named \"edge.token\"."); return; } if (!File.Exists("device.id")) { Console.Error.WriteLine("Error: Please add your device ID in hexadecimal text form to a file named \"device.id\"."); return; } if (!File.Exists("nx_tls_client_cert.pfx")) { Console.Error.WriteLine("Error: Please add your Switch certificate to a file named \"nx_tls_client_cert.pfx\"."); return; } #endregion var deviceID = Convert.ToInt64(File.ReadAllText("device.id"), 16); var keys = ExternalKeys.ReadKeyFile(keysInUserDir ? keyFile : "prod.keys"); var sysID = "0100000000000816"; // To-do: Clean up if (args[0] == "-s" || args[0] == sysID) { var JSON = (string)GET(deviceID, SunUrl, true); var Version = args.Length > 1 ? args[1] : (string)JObject.Parse(JSON)["system_update_metas"][0]["title_version"]; HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID)); var contentID = HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID)); using (var meta = (HttpWebResponse)GET(deviceID, nContentURL('s', contentID), false)) using (var rd = new BinaryReader(meta.GetResponseStream())) using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength))) { Directory.CreateDirectory(sysID); strm.WriteAllBytes($"{sysID}/{contentID}.cnmt.nca"); using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false)) { var pfs = new Pfs(nca); var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream()); foreach (var entry in cnmt.MetaEntries) { var tid = $"{entry.TitleId:x16}"; HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID)); var cID = HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID)); using (var met2 = (HttpWebResponse)GET(deviceID, nContentURL('a', cID), false)) using (var rdr = new BinaryReader(met2.GetResponseStream())) using (var strm2 = new MemoryStorage(rdr.ReadBytes((int)meta.ContentLength))) { Directory.CreateDirectory($"{sysID}/{tid}"); strm2.WriteAllBytes($"{sysID}/{tid}/{cID}.cnmt.nca"); using (var nca2 = new Nca(keys, strm2, false).OpenSection(0, false, IntegrityCheckLevel.None, false)) { var pfs2 = new Pfs(nca2); var cnmt2 = new Cnmt(pfs2.OpenFile(pfs2.Files[0]).AsStream()); foreach (var entry2 in cnmt2.ContentEntries) { string NCAID = entry2.NcaId.ToHexString().ToLower(); using (var Req = (HttpWebResponse)GET(deviceID, nContentURL('c', NCAID), false)) using (var Output = File.OpenWrite($"{sysID}/{tid}/{NCAID}.nca")) Req.GetResponseStream().CopyTo(Output); } } } } } } return; } string id = null, idFirstReq = null, idSecondReq = null; List <string> tidTargets = new List <string>(), verTargets = new List <string>(), entryTargets = new List <string>(); var numOfListings = 0; if (args.Length == 2) { if (args[1] == "-d") { getDeltasOnly = true; } else if (args[0] == "-t") { var rightsID = args[1]; using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false)) using (var strm = tikReq.GetResponseStream()) using (var rd = new BinaryReader(strm)) { File.WriteAllBytes($"{rightsID}.tik", rd.ReadBytes(0x2C0)); File.WriteAllBytes($"{rightsID}.cert", rd.ReadBytes(0x700)); } return; } } GET(deviceID, Aqua(deviceID), false); if (args.Length == 3) { numOfListings = 2; if (args[0].Substring(13, 3) != "000" && args[0].Substring(13, 3) != "800") { tidTargets.Add(null); tidTargets.Add(args[0]); } else { tidTargets.Add(null); tidTargets.Add($"{args[0].Substring(0, 13)}800"); } verTargets.Add(null); verTargets.Add(args[2]); } else { var Streq = (string)GET(deviceID, Superfly(GetBaseTID(args[0])), true); if (args[0].Substring(13, 3) == "000") { foreach (JToken Listing in JArray.Parse(Streq)) { if ((string)Listing["title_type"] != "AddOnContent") { numOfListings++; tidTargets.Add(Listing["title_id"].ToString()); verTargets.Add(Listing["version"].ToString()); } } } else { foreach (JToken Listing in JArray.Parse(Streq)) { if ((string)Listing["title_id"] == args[0]) { numOfListings++; tidTargets.Add(Listing["title_id"].ToString()); verTargets.Add(Listing["version"].ToString()); } } } } if (args.Length == 1) { id = HEAD(deviceID, MetaURL('a', tidTargets[0], verTargets[0], deviceID)); } if (args.Length == 1 && id != null) { GET(deviceID, ContentURL('a', id), true); } if (numOfListings >= 2) { idFirstReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID)); } if (args.Length == 1 && numOfListings >= 2) { GET(deviceID, ContentURL('a', idFirstReq), true); } if (numOfListings >= 2) { idSecondReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID)); } if (numOfListings >= 2) { GET(deviceID, ContentURL('a', idSecondReq), true); } if (args.Length == 1) { using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', id), false)) using (var rd = new BinaryReader(meta.GetResponseStream())) using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength))) { Directory.CreateDirectory(tidTargets[0]); strm.WriteAllBytes($"{tidTargets[0]}/{id}.cnmt.nca"); using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false)) { var pfs = new Pfs(nca); var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream()); foreach (var entry in cnmt.ContentEntries) { string NCAID = entry.NcaId.ToHexString().ToLower(); using (var Req = (HttpWebResponse)GET(deviceID, ContentURL('c', NCAID), false)) using (var Output = File.OpenWrite($"{tidTargets[0]}/{NCAID}.nca")) Req.GetResponseStream().CopyTo(Output); } } } } if (numOfListings >= 2) { using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', idSecondReq), false)) using (var read = new BinaryReader(meta.GetResponseStream())) using (var metastrm = new MemoryStorage(read.ReadBytes((int)meta.ContentLength))) { Directory.CreateDirectory(tidTargets[1]); metastrm.WriteAllBytes($"{tidTargets[1]}/{idSecondReq}.cnmt.nca"); using (var nca = new Nca(keys, metastrm, false).OpenSection(0, false, IntegrityCheckLevel.None, false)) { var pfs = new Pfs(nca); var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream()); foreach (var entry in getDeltasOnly ? cnmt.ContentEntries.Where(e => e.Type == CnmtContentType.DeltaFragment) : cnmt.ContentEntries) { var ncaID = entry.NcaId.ToHexString().ToLower(); using (var request = (HttpWebResponse)GET(deviceID, ContentURL('c', ncaID), false)) using (var output = File.OpenWrite($"{tidTargets[1]}/{ncaID}.nca")) request.GetResponseStream().CopyTo(output); if (entry.Type == CnmtContentType.Program) { var rightsID = new Nca(keys, new StreamStorage (File.OpenRead($"{tidTargets[1]}/{ncaID}.nca"), false), false) .Header.RightsId.ToHexString().ToLower(); using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false)) using (var strm = tikReq.GetResponseStream()) using (var rd = new BinaryReader(strm)) { File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.tik", rd.ReadBytes(0x2C0)); File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.cert", rd.ReadBytes(0x700)); } } } } } } }
private void Open() { treeView1.Nodes.Clear(); string FileToOpen = null; if (Program.FileArg != null) { FileToOpen = Program.FileArg; } else { FileToOpen = openFileDialog1.FileName; } Program.FileArg = null; Stream Input = null; try { string ExpEnv(string In) { return(Environment.ExpandEnvironmentVariables(In)); } var ProdKeys = ExpEnv(@"%USERPROFILE%\.switch\prod.keys"); var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys"); var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys); var Ext = (new FileInfo(FileToOpen).Extension); if (Ext == ".nsp") { var InputPFS = File.OpenRead(FileToOpen); var Pfs = new Pfs(InputPFS); Input = Pfs.OpenFile ( Pfs.Files.OrderByDescending(s => s.Size) .FirstOrDefault() ); } else if (Ext == ".xci") { var InputPFS = File.OpenRead(FileToOpen); var Xci = new Xci(Keys, InputPFS); Input = Xci.SecurePartition.OpenFile ( Xci.SecurePartition.Files .OrderByDescending(s => s.Size) .FirstOrDefault() ); } else { Input = File.OpenRead(FileToOpen); } try { Nca = new Nca(Keys, Input, true); if (Nca.HasRightsId) { if (!Keys.TitleKeys.Keys.Contains(Nca.Header.RightsId)) { MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString()} is not present in your key file."); } } bool IsUpdateNca = false; foreach (var Section in Nca.Sections) { if (Section?.Type == SectionType.Bktr) { IsUpdateNca = true; } } if (IsUpdateNca) { openFileDialog1.Title = "Select base Nca"; openFileDialog1.ShowDialog(); var Input2 = File.OpenRead(openFileDialog1.FileName); Patch = new Nca(Keys, Input2, true); Nca.SetBaseNca(Patch); } new Thread ( () => { Thread.CurrentThread.IsBackground = true; var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}"); label2.Invoke ( new Action ( () => { label2.Text = Info[0]; } ) ); label3.Invoke ( new Action ( () => { label3.Text = Info[1]; } ) ); } ) .Start(); Rom = new Romfs ( Nca.OpenSection ( Nca.Sections.FirstOrDefault (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr) .SectionNum, false, false ) ); IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir); } catch (Exception) { MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?"); } } catch (Exception) { MessageBox.Show("Error: key files are missing!"); } }
static void Main(string[] args) { var path = args.Length >= 1 ? args[0] : Environment.CurrentDirectory; var fs = new FileSystem(path); if (!File.Exists("keys.txt")) { Console.WriteLine("Cannot verify NSPs without keys.txt"); Console.WriteLine(); Console.WriteLine("Press any key to continue"); Console.ReadKey(); return; } var keyset = ExternalKeys.ReadKeyFile("keys.txt"); var badlist = new List <string>(); var exceptionlist = new List <string>(); foreach (var file in fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories)) { var filename = Path.GetFileName(file); var progress = $"Checking {filename}: "; Console.Write(progress); try { bool ok = true; using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read)) { var nspdata = new Pfs(nspfile); var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca")); if (cnmtfile == null) { Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present"); badlist.Add(filename); continue; } var cnmtdata = nspdata.OpenFile(cnmtfile); Cnmt cnmt; using (var sr = new BinaryReader(cnmtdata)) { var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length)); if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString())) { //Put failure here Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted"); badlist.Add(filename); cnmtdata.Dispose(); continue; } cnmtdata.Position = 0; var cnmtnca = new Nca(keyset, cnmtdata, false); var section = cnmtnca.OpenSection(0, false); var sectionpfs = new Pfs(section); cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0])); } foreach (var entry in cnmt.ContentEntries) { var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca")); if (entryfile == null) { if (entry.Type != CnmtContentType.UpdatePatch) { //Put failure here Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing."); badlist.Add(filename); break; } continue; } using (var entrynca = nspdata.OpenFile(entryfile)) { var hash = SHA256.Create(); using (var sr = new BinaryReader(entrynca)) { while (entrynca.Length != entrynca.Position) { var entryncadata = sr.ReadBytes(0x100000); hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0); Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%"); } hash.TransformFinalBlock(new byte[0], 0, 0); } if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString())) { Console.Write($"\rChecking {filename}: {100:0.0}%"); continue; } //Put failure here Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted"); badlist.Add(filename); ok = false; break; } } if (ok) { Console.WriteLine($"\rChecking {filename}: OK "); } //Put Success here } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); exceptionlist.Add($"{filename}{Environment.NewLine}Exception: {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}"); } } File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist)); File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist)); Console.WriteLine(); Console.WriteLine("Press any key to continue"); Console.ReadKey(); }
public void CopyKeyset() { ExternalKeys.ReadKeyFile(HACGUIKeyset.Keyset, KeysetFile.FullName); HACGUIKeyset.Keyset.DeriveKeys(); // derive from keyblobs }