mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Load title keys
This commit is contained in:
parent
723ffe5550
commit
d336c2e58d
5 changed files with 137 additions and 2 deletions
|
@ -8,6 +8,12 @@ namespace hactoolnet
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
ReadNca();
|
||||||
|
//ListSdfs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ListSdfs(string[] args)
|
||||||
{
|
{
|
||||||
var sdfs = LoadSdFs(args);
|
var sdfs = LoadSdFs(args);
|
||||||
|
|
||||||
|
@ -18,7 +24,22 @@ namespace hactoolnet
|
||||||
ListTitles(sdfs);
|
ListTitles(sdfs);
|
||||||
|
|
||||||
//DecryptNax0(sdfs, "C0628FB07A89E9050BDA258F74868E8D");
|
//DecryptNax0(sdfs, "C0628FB07A89E9050BDA258F74868E8D");
|
||||||
DecryptTitle(sdfs, 0x0100000000010800);
|
DecryptTitle(sdfs, 0x010025400AECE000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadNca()
|
||||||
|
{
|
||||||
|
var keyset = ExternalKeys.ReadKeyFile("keys.txt", "titlekeys.txt");
|
||||||
|
using (var file = new FileStream("acc9da939a8e0b339aa3be3d409d9ada.nca", FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
var nca = new Nca(keyset, file, false);
|
||||||
|
var romfs = nca.OpenSection(0);
|
||||||
|
|
||||||
|
using (var output = new FileStream("romfs_net", FileMode.Create))
|
||||||
|
{
|
||||||
|
romfs.CopyTo(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DecryptNax0(SdFs sdFs, string name)
|
static void DecryptNax0(SdFs sdFs, string name)
|
||||||
|
|
|
@ -41,6 +41,8 @@ namespace libhac
|
||||||
public byte[] acid_fixed_key_modulus { get; set; } = new byte[0x100];
|
public byte[] acid_fixed_key_modulus { get; set; } = new byte[0x100];
|
||||||
public byte[] package2_fixed_key_modulus { get; set; } = new byte[0x100];
|
public byte[] package2_fixed_key_modulus { get; set; } = new byte[0x100];
|
||||||
|
|
||||||
|
public Dictionary<byte[], byte[]> TitleKeys { get; } = new Dictionary<byte[], byte[]>(new ByteArray128BitComparer());
|
||||||
|
|
||||||
public void SetSdSeed(byte[] sdseed)
|
public void SetSdSeed(byte[] sdseed)
|
||||||
{
|
{
|
||||||
for (int k = 0; k < sd_card_key_sources.Length; k++)
|
for (int k = 0; k < sd_card_key_sources.Length; k++)
|
||||||
|
@ -76,12 +78,46 @@ namespace libhac
|
||||||
|
|
||||||
public static class ExternalKeys
|
public static class ExternalKeys
|
||||||
{
|
{
|
||||||
|
private const int TitleKeySize = 0x10;
|
||||||
private static readonly Dictionary<string, KeyValue> KeyDict = CreateKeyDict();
|
private static readonly Dictionary<string, KeyValue> KeyDict = CreateKeyDict();
|
||||||
|
|
||||||
|
public static Keyset ReadKeyFile(string filename, string titleKeysFilename, IProgressReport progress = null)
|
||||||
|
{
|
||||||
|
var keyset = ReadKeyFile(filename, progress);
|
||||||
|
using (var reader = new StreamReader(new FileStream(titleKeysFilename, FileMode.Open, FileAccess.Read)))
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
var a = line.Split(',');
|
||||||
|
if (a.Length != 2) continue;
|
||||||
|
|
||||||
|
var rightsId = a[0].Trim().ToBytes();
|
||||||
|
var titleKey = a[1].Trim().ToBytes();
|
||||||
|
|
||||||
|
if (rightsId.Length != TitleKeySize)
|
||||||
|
{
|
||||||
|
progress?.LogMessage($"Rights ID {rightsId.ToHexString()} had incorrect size {rightsId.Length}. (Expected {TitleKeySize})");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (titleKey.Length != TitleKeySize)
|
||||||
|
{
|
||||||
|
progress?.LogMessage($"Title key {titleKey.ToHexString()} had incorrect size {titleKey.Length}. (Expected {TitleKeySize})");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyset.TitleKeys.Add(rightsId, titleKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyset;
|
||||||
|
}
|
||||||
|
|
||||||
public static Keyset ReadKeyFile(string filename, IProgressReport progress = null)
|
public static Keyset ReadKeyFile(string filename, IProgressReport progress = null)
|
||||||
{
|
{
|
||||||
var keyset = new Keyset();
|
var keyset = new Keyset();
|
||||||
using (var reader = new StreamReader(new FileStream(filename, FileMode.Open)))
|
using (var reader = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||||
{
|
{
|
||||||
string line;
|
string line;
|
||||||
while ((line = reader.ReadLine()) != null)
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
|
|
@ -57,6 +57,8 @@ namespace libhac
|
||||||
size = sect.Pfs0.Pfs0Size;
|
size = sect.Pfs0.Pfs0Size;
|
||||||
break;
|
break;
|
||||||
case SectionFsType.Romfs:
|
case SectionFsType.Romfs:
|
||||||
|
offset = sect.Offset + (long)sect.Header.Romfs.IvfcHeader.LevelHeaders[Romfs.IvfcMaxLevel - 1].LogicalOffset;
|
||||||
|
size = (long)sect.Header.Romfs.IvfcHeader.LevelHeaders[Romfs.IvfcMaxLevel - 1].HashDataSize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
34
libhac/Romfs.cs
Normal file
34
libhac/Romfs.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace libhac
|
||||||
|
{
|
||||||
|
public class Romfs
|
||||||
|
{
|
||||||
|
public static readonly int IvfcMaxLevel = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RomfsHeader
|
||||||
|
{
|
||||||
|
public ulong HeaderSize;
|
||||||
|
public ulong DirHashTableOffset;
|
||||||
|
public ulong DirHashTableSize;
|
||||||
|
public ulong DirMetaTableOffset;
|
||||||
|
public ulong DirMetaTableSize;
|
||||||
|
public ulong FileHashTableOffset;
|
||||||
|
public ulong FileHashTableSize;
|
||||||
|
public ulong FileMetaTableOffset;
|
||||||
|
public ulong FileMetaTableSize;
|
||||||
|
public ulong DataOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IvfcLevel
|
||||||
|
{
|
||||||
|
public ulong DataOffset { get; set; }
|
||||||
|
public ulong DataSize { get; set; }
|
||||||
|
public ulong HashOffset { get; set; }
|
||||||
|
public ulong HashBlockSize { get; set; }
|
||||||
|
public ulong HashBlockCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace libhac
|
namespace libhac
|
||||||
|
@ -255,4 +257,44 @@ namespace libhac
|
||||||
return readable.ToString("0.### ") + suffix;
|
return readable.ToString("0.### ") + suffix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ByteArray128BitComparer : EqualityComparer<byte[]>
|
||||||
|
{
|
||||||
|
public override bool Equals(byte[] first, byte[] second)
|
||||||
|
{
|
||||||
|
if (first == null || second == null)
|
||||||
|
{
|
||||||
|
// null == null returns true.
|
||||||
|
// non-null == null returns false.
|
||||||
|
return first == second;
|
||||||
|
}
|
||||||
|
if (ReferenceEquals(first, second))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (first.Length != second.Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Linq extension method is based on IEnumerable, must evaluate every item.
|
||||||
|
return first.SequenceEqual(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode(byte[] obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
}
|
||||||
|
if (obj.Length != 16)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Length must be 16 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
var hi = BitConverter.ToUInt64(obj, 0);
|
||||||
|
var lo = BitConverter.ToUInt64(obj, 8);
|
||||||
|
|
||||||
|
return (hi.GetHashCode() * 397) ^ lo.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue