mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
hactoolnet: Always read both prod and dev key sets
This commit is contained in:
parent
8f011387a0
commit
c39895080b
3 changed files with 117 additions and 32 deletions
|
@ -65,6 +65,61 @@ namespace LibHac.Common.Keys
|
|||
|
||||
keySet.DeriveKeys(logger);
|
||||
|
||||
// Dev keys can be read from prod key files, so derive any missing keys if necessary.
|
||||
if (keySet.CurrentMode == KeySet.Mode.Prod)
|
||||
{
|
||||
keySet.SetMode(KeySet.Mode.Dev);
|
||||
keySet.DeriveKeys(logger);
|
||||
keySet.SetMode(KeySet.Mode.Prod);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads keys from key files into an existing <see cref="KeySet"/>. Missing keys will be
|
||||
/// derived from existing keys if possible. Any <see langword="null"/> file names will be skipped.
|
||||
/// </summary>
|
||||
/// <param name="keySet">The <see cref="KeySet"/> where the loaded keys will be placed.</param>
|
||||
/// <param name="prodKeysFilename">The path of the file containing common prod keys. Can be <see langword="null"/>.</param>
|
||||
/// <param name="devKeysFilename">The path of the file containing common dev keys. Can be <see langword="null"/>.</param>
|
||||
/// <param name="titleKeysFilename">The path of the file containing title keys. Can be <see langword="null"/>.</param>
|
||||
/// <param name="consoleKeysFilename">The path of the file containing device-unique keys. Can be <see langword="null"/>.</param>
|
||||
/// <param name="logger">An optional logger that key-parsing errors will be written to.</param>
|
||||
public static void ReadKeyFile(KeySet keySet, string prodKeysFilename = null, string devKeysFilename = null,
|
||||
string titleKeysFilename = null, string consoleKeysFilename = null, IProgressReport logger = null)
|
||||
{
|
||||
KeySet.Mode originalMode = keySet.CurrentMode;
|
||||
List<KeyInfo> keyInfos = DefaultKeySet.CreateKeyList();
|
||||
|
||||
if (prodKeysFilename != null)
|
||||
{
|
||||
keySet.SetMode(KeySet.Mode.Prod);
|
||||
using var storage = new FileStream(prodKeysFilename, FileMode.Open, FileAccess.Read);
|
||||
ReadMainKeys(keySet, storage, keyInfos, logger);
|
||||
}
|
||||
|
||||
if (devKeysFilename != null)
|
||||
{
|
||||
keySet.SetMode(KeySet.Mode.Dev);
|
||||
using var storage = new FileStream(devKeysFilename, FileMode.Open, FileAccess.Read);
|
||||
ReadMainKeys(keySet, storage, keyInfos, logger);
|
||||
}
|
||||
|
||||
keySet.SetMode(originalMode);
|
||||
|
||||
if (consoleKeysFilename != null)
|
||||
{
|
||||
using var storage = new FileStream(consoleKeysFilename, FileMode.Open, FileAccess.Read);
|
||||
ReadMainKeys(keySet, storage, keyInfos, logger);
|
||||
}
|
||||
|
||||
if (titleKeysFilename != null)
|
||||
{
|
||||
using var storage = new FileStream(titleKeysFilename, FileMode.Open, FileAccess.Read);
|
||||
ReadTitleKeys(keySet, storage, logger);
|
||||
}
|
||||
|
||||
keySet.DeriveKeys(logger);
|
||||
|
||||
// Dev keys can read from prod key files, so derive any missing keys if necessary.
|
||||
if (keySet.CurrentMode == KeySet.Mode.Prod)
|
||||
{
|
||||
|
@ -283,7 +338,12 @@ namespace LibHac.Common.Keys
|
|||
return ReaderStatus.Finished;
|
||||
}
|
||||
|
||||
buffer = buffer.Slice(0, buffer.Length - reader.BufferPos + charsRead);
|
||||
// ReadBlock will only read less than the buffer size if there's nothing left to read
|
||||
if (charsRead != reader.BufferPos)
|
||||
{
|
||||
buffer = buffer.Slice(0, buffer.Length - reader.BufferPos + charsRead);
|
||||
reader.Buffer = buffer;
|
||||
}
|
||||
|
||||
reader.NeedFillBuffer = false;
|
||||
reader.BufferPos = 0;
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace LibHac.Common.Keys
|
|||
{
|
||||
public static class ExternalKeyWriter
|
||||
{
|
||||
|
||||
public static void PrintKeys(KeySet keySet, StringBuilder sb, List<KeyInfo> keys, Type filter, bool isDev)
|
||||
{
|
||||
if (keys.Count == 0) return;
|
||||
|
@ -156,18 +155,18 @@ namespace LibHac.Common.Keys
|
|||
|
||||
public static string PrintCommonKeysWithDev(KeySet keySet)
|
||||
{
|
||||
KeySet.Mode originalMode = keySet.CurrentMode;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
keySet.SetMode(KeySet.Mode.Prod);
|
||||
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Seed | Type.Derived,
|
||||
false);
|
||||
|
||||
if (keySet.CurrentMode == KeySet.Mode.Prod)
|
||||
{
|
||||
sb.AppendLine();
|
||||
keySet.SetMode(KeySet.Mode.Dev);
|
||||
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Derived, true);
|
||||
keySet.SetMode(KeySet.Mode.Prod);
|
||||
}
|
||||
sb.AppendLine();
|
||||
keySet.SetMode(KeySet.Mode.Dev);
|
||||
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Derived, true);
|
||||
|
||||
keySet.SetMode(originalMode);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace hactoolnet
|
|||
Result.SetLogger(resultLogger);
|
||||
}
|
||||
|
||||
OpenKeyset(ctx);
|
||||
OpenKeySet(ctx);
|
||||
|
||||
if (ctx.Options.RunCustom)
|
||||
{
|
||||
|
@ -168,43 +168,65 @@ namespace hactoolnet
|
|||
}
|
||||
}
|
||||
|
||||
private static void OpenKeyset(Context ctx)
|
||||
private static void OpenKeySet(Context ctx)
|
||||
{
|
||||
string keyFileName = ctx.Options.UseDevKeys ? "dev.keys" : "prod.keys";
|
||||
|
||||
#if CORERT_NO_REFLECTION
|
||||
string home = HomeFolder.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
#else
|
||||
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
#endif
|
||||
string homeKeyFile = Path.Combine(home, ".switch", keyFileName);
|
||||
string homeTitleKeyFile = Path.Combine(home, ".switch", "title.keys");
|
||||
string homeConsoleKeyFile = Path.Combine(home, ".switch", "console.keys");
|
||||
string keyFile = ctx.Options.Keyfile;
|
||||
|
||||
string prodKeyFile = Path.Combine(home, ".switch", "prod.keys");
|
||||
string devKeyFile = Path.Combine(home, ".switch", "dev.keys");
|
||||
string titleKeyFile = ctx.Options.TitleKeyFile;
|
||||
string consoleKeyFile = ctx.Options.ConsoleKeyFile;
|
||||
|
||||
if (keyFile == null && File.Exists(homeKeyFile))
|
||||
{
|
||||
keyFile = homeKeyFile;
|
||||
}
|
||||
// Check if the files from the command line exist
|
||||
if (titleKeyFile != null && !File.Exists(titleKeyFile))
|
||||
titleKeyFile = null;
|
||||
|
||||
if (consoleKeyFile != null && !File.Exists(consoleKeyFile))
|
||||
consoleKeyFile = null;
|
||||
|
||||
if (!File.Exists(prodKeyFile))
|
||||
prodKeyFile = null;
|
||||
|
||||
if (!File.Exists(devKeyFile))
|
||||
devKeyFile = null;
|
||||
|
||||
// Check the home directory if no existing key files were specified
|
||||
if (consoleKeyFile == null && File.Exists(homeConsoleKeyFile))
|
||||
consoleKeyFile = homeConsoleKeyFile;
|
||||
|
||||
if (titleKeyFile == null && File.Exists(homeTitleKeyFile))
|
||||
{
|
||||
titleKeyFile = homeTitleKeyFile;
|
||||
}
|
||||
|
||||
if (consoleKeyFile == null && File.Exists(homeConsoleKeyFile))
|
||||
var keySet = KeySet.CreateDefaultKeySet();
|
||||
|
||||
// If the user specifies a key file then only load that file into the mode they specified,
|
||||
// otherwise load both prod.keys and dev.keys.
|
||||
// Todo: Should we add a way that both dev-only key files and mixed prod/dev key files
|
||||
// can both be loaded when specifying a key file in dev mode?
|
||||
if (ctx.Options.Keyfile != null && File.Exists(ctx.Options.Keyfile))
|
||||
{
|
||||
consoleKeyFile = homeConsoleKeyFile;
|
||||
keySet.SetMode(ctx.Options.KeyMode);
|
||||
ExternalKeyReader.ReadKeyFile(keySet, ctx.Options.Keyfile, titleKeyFile, consoleKeyFile, ctx.Logger);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExternalKeyReader.ReadKeyFile(keySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, ctx.Logger);
|
||||
}
|
||||
|
||||
ctx.KeySet = ExternalKeyReader.ReadKeyFile(keyFile, titleKeyFile, consoleKeyFile, ctx.Logger, ctx.Options.KeyMode);
|
||||
keySet.SetMode(ctx.Options.KeyMode);
|
||||
|
||||
if (ctx.Options.SdSeed != null)
|
||||
{
|
||||
ctx.KeySet.SetSdSeed(ctx.Options.SdSeed.ToBytes());
|
||||
keySet.SetSdSeed(ctx.Options.SdSeed.ToBytes());
|
||||
}
|
||||
|
||||
ctx.KeySet = keySet;
|
||||
}
|
||||
|
||||
private static void ProcessKeygen(Context ctx)
|
||||
|
@ -213,19 +235,23 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.OutDir != null)
|
||||
{
|
||||
string keyFileName = ctx.Options.UseDevKeys ? "dev.keys" : "prod.keys";
|
||||
KeySet.Mode originalMode = ctx.KeySet.CurrentMode;
|
||||
|
||||
string dir = ctx.Options.OutDir;
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
File.WriteAllText(Path.Combine(dir, keyFileName), ExternalKeyWriter.PrintCommonKeys(ctx.KeySet));
|
||||
ctx.KeySet.SetMode(KeySet.Mode.Prod);
|
||||
File.WriteAllText(Path.Combine(dir, "prod.keys"), ExternalKeyWriter.PrintCommonKeys(ctx.KeySet));
|
||||
|
||||
ctx.KeySet.SetMode(KeySet.Mode.Dev);
|
||||
File.WriteAllText(Path.Combine(dir, "dev.keys"), ExternalKeyWriter.PrintCommonKeys(ctx.KeySet));
|
||||
|
||||
ctx.KeySet.SetMode(originalMode);
|
||||
File.WriteAllText(Path.Combine(dir, "console.keys"), ExternalKeyWriter.PrintDeviceKeys(ctx.KeySet));
|
||||
File.WriteAllText(Path.Combine(dir, "title.keys"), ExternalKeyWriter.PrintTitleKeys(ctx.KeySet));
|
||||
|
||||
if (!ctx.Options.UseDevKeys)
|
||||
{
|
||||
File.WriteAllText(Path.Combine(dir, "prod+dev.keys"),
|
||||
ExternalKeyWriter.PrintCommonKeysWithDev(ctx.KeySet));
|
||||
}
|
||||
File.WriteAllText(Path.Combine(dir, "prod+dev.keys"),
|
||||
ExternalKeyWriter.PrintCommonKeysWithDev(ctx.KeySet));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue