Load title keys

This commit is contained in:
Alex Barney 2018-06-27 20:25:25 -05:00
parent 723ffe5550
commit d336c2e58d
5 changed files with 137 additions and 2 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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
View 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; }
}
}

View file

@ -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();
}
}
} }