Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Tool for installing keys #233

Merged
merged 16 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions src/Ryujinx.HLE/FileSystem/ContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Path = System.IO.Path;

namespace Ryujinx.HLE.FileSystem
Expand Down Expand Up @@ -474,6 +475,74 @@ public void InstallFirmware(string firmwareSource)
FinishInstallation(temporaryDirectory, registeredDirectory);
}

public void InstallKeys(string keysSource, string installDirectory)
{
if (Directory.Exists(keysSource))
{
foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys"))
{
VerifyKeysFile(filePath);
File.Copy(filePath, Path.Combine(installDirectory, Path.GetFileName(filePath)), true);
}

return;
}

if (!File.Exists(keysSource))
{
throw new FileNotFoundException("Keys file does not exist.");
}

FileInfo info = new(keysSource);

using FileStream file = File.OpenRead(keysSource);

switch (info.Extension)
{
case ".zip":
using (ZipArchive archive = ZipFile.OpenRead(keysSource))
{
InstallKeysFromZip(archive, installDirectory);
}
break;
case ".keys":
VerifyKeysFile(keysSource);
File.Copy(keysSource, Path.Combine(installDirectory, info.Name), true);
break;
default:
throw new InvalidFirmwarePackageException("Input file is not a valid key package");
}
}

private void InstallKeysFromZip(ZipArchive archive, string installDirectory)
{
string temporaryDirectory = Path.Combine(installDirectory, "temp");
if (Directory.Exists(temporaryDirectory))
{
Directory.Delete(temporaryDirectory, true);
}
Directory.CreateDirectory(temporaryDirectory);
foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase))
{
string extractDestination = Path.Combine(temporaryDirectory, entry.Name);
entry.ExtractToFile(extractDestination, overwrite: true);
try
{
VerifyKeysFile(extractDestination);
File.Move(extractDestination, Path.Combine(installDirectory, entry.Name), true);
}
catch (Exception)
{
Directory.Delete(temporaryDirectory, true);
throw;
}
}
}
Directory.Delete(temporaryDirectory, true);
}

private void FinishInstallation(string temporaryDirectory, string registeredDirectory)
{
if (Directory.Exists(registeredDirectory))
Expand Down Expand Up @@ -947,5 +1016,70 @@ public SystemVersion GetCurrentFirmwareVersion()

return null;
}

public void VerifyKeysFile(string filePath)
{
// Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md
string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$";
string titlePattern = @"^[a-z0-9]{32} = [a-z0-9]{32}$";

if (File.Exists(filePath))
{
// Read all lines from the file
string fileName = Path.GetFileName(filePath);
string[] lines = File.ReadAllLines(filePath);

bool verified = false;
switch (fileName)
{
case "prod.keys":
verified = verifyKeys(lines, genericPattern);
break;
case "title.keys":
verified = verifyKeys(lines, titlePattern);
break;
case "console.keys":
verified = verifyKeys(lines, genericPattern);
break;
case "dev.keys":
verified = verifyKeys(lines, genericPattern);
break;
default:
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
}
if (!verified)
{
throw new FormatException($"Invalid \"{filePath}\" file format.");
}
} else
{
throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
}
}

private bool verifyKeys(string[] lines, string regex)
{
foreach (string line in lines)
{
if (!Regex.IsMatch(line, regex))
{
return false;
}
}
return true;
}

public bool AreKeysAlredyPresent(string pathToCheck)
{
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
foreach (var file in fileNames)
{
if (File.Exists(Path.Combine(pathToCheck, file)))
{
return true;
}
}
return false;
}
}
}
17 changes: 12 additions & 5 deletions src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,10 @@ public void ReloadKeySet()
{
KeySet ??= KeySet.CreateDefaultKeySet();

string keyFile = null;
string prodKeyFile = null;
string titleKeyFile = null;
string consoleKeyFile = null;
string devKeyFile = null;

if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile)
{
Expand All @@ -236,13 +237,14 @@ public void ReloadKeySet()

void LoadSetAtPath(string basePath)
{
string localKeyFile = Path.Combine(basePath, "prod.keys");
string localProdKeyFile = Path.Combine(basePath, "prod.keys");
string localTitleKeyFile = Path.Combine(basePath, "title.keys");
string localConsoleKeyFile = Path.Combine(basePath, "console.keys");
string localDevKeyFile = Path.Combine(basePath, "dev.keys");

if (File.Exists(localKeyFile))
if (File.Exists(localProdKeyFile))
{
keyFile = localKeyFile;
prodKeyFile = localProdKeyFile;
}

if (File.Exists(localTitleKeyFile))
Expand All @@ -254,9 +256,14 @@ void LoadSetAtPath(string basePath)
{
consoleKeyFile = localConsoleKeyFile;
}

if (File.Exists(localDevKeyFile))
{
devKeyFile = localDevKeyFile;
}
}

ExternalKeyReader.ReadKeyFile(KeySet, keyFile, titleKeyFile, consoleKeyFile, null);
ExternalKeyReader.ReadKeyFile(KeySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, null);
}

public void ImportTickets(IFileSystem fs)
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/ar_SA.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "تثبيت البرنامج الثابت",
"MenuBarFileToolsInstallFirmwareFromFile": "تثبيت برنامج ثابت من XCI أو ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "تثبيت برنامج ثابت من مجلد",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "إدارة أنواع الملفات",
"MenuBarToolsInstallFileTypes": "تثبيت أنواع الملفات",
"MenuBarToolsUninstallFileTypes": "إزالة أنواع الملفات",
Expand Down Expand Up @@ -506,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\nهل تريد المتابعة؟",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "تثبيت البرنامج الثابت...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "تم تثبيت إصدار النظام {0} بنجاح.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "لن تكون هناك ملفات الشخصية أخرى لفتحها إذا تم حذف الملف الشخصي المحدد",
"DialogUserProfileDeletionConfirmMessage": "هل تريد حذف الملف الشخصي المحدد",
"DialogUserProfileUnsavedChangesTitle": "تحذير - التغييرات غير محفوظة",
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Firmware installieren",
"MenuBarFileToolsInstallFirmwareFromFile": "Firmware von einer XCI- oder einer ZIP-Datei installieren",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Firmware aus einem Verzeichnis installieren",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Dateitypen verwalten",
"MenuBarToolsInstallFileTypes": "Dateitypen installieren",
"MenuBarToolsUninstallFileTypes": "Dateitypen deinstallieren",
Expand Down Expand Up @@ -506,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nMöchtest du fortfahren?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware wird installiert...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Systemversion {0} wurde erfolgreich installiert.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Es können keine anderen Profile geöffnet werden, wenn das ausgewählte Profil gelöscht wird.",
"DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?",
"DialogUserProfileUnsavedChangesTitle": "Warnung - Nicht gespeicherte Änderungen",
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/el_GR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Εγκατάσταση Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Εγκατάσταση Firmware από XCI ή ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Εγκατάσταση Firmware από τοποθεσία",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Διαχείριση τύπων αρχείων",
"MenuBarToolsInstallFileTypes": "Εγκαταστήσετε τύπους αρχείων.",
"MenuBarToolsUninstallFileTypes": "Απεγκαταστήσετε τύπους αρχείων",
Expand Down Expand Up @@ -506,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nΘέλετε να συνεχίσετε;",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Εγκατάσταση Firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Η έκδοση συστήματος {0} εγκαταστάθηκε με επιτυχία.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Δεν θα υπάρχουν άλλα προφίλ εάν διαγραφεί το επιλεγμένο",
"DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ",
"DialogUserProfileUnsavedChangesTitle": "Προσοχή - Μην Αποθηκευμένες Αλλαγές.",
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Install Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Manage file types",
"MenuBarToolsInstallFileTypes": "Install file types",
"MenuBarToolsUninstallFileTypes": "Uninstall file types",
Expand Down Expand Up @@ -518,6 +521,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted",
"DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile",
"DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes",
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/es_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Instalar firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Administrar tipos de archivo",
"MenuBarToolsInstallFileTypes": "Instalar tipos de archivo",
"MenuBarToolsUninstallFileTypes": "Desinstalar tipos de archivo",
Expand Down Expand Up @@ -506,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n¿Continuar?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versión de sistema {0} instalada con éxito.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Si eliminas el perfil seleccionado no quedará ningún otro perfil",
"DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?",
"DialogUserProfileUnsavedChangesTitle": "Advertencia - Cambios sin guardar",
Expand Down
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/fr_FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Installer un firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Installer un firmware depuis un fichier XCI ou ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installer un firmware depuis un dossier",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Gérer les types de fichiers",
"MenuBarToolsInstallFileTypes": "Installer les types de fichiers",
"MenuBarToolsUninstallFileTypes": "Désinstaller les types de fichiers",
Expand Down Expand Up @@ -506,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé",
"DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?",
"DialogUserProfileUnsavedChangesTitle": "Avertissement - Modifications non enregistrées",
Expand Down
Loading