From aa85c0dc8cfb7c04d20f969c32c684e3eec38829 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Fri, 31 Jan 2020 15:38:56 -0700 Subject: [PATCH] We have a CLI --- Wabbajack.CLI/OptionsDefinition.cs | 13 +++++++++++++ Wabbajack.CLI/Program.cs | 18 ++++++++++++++++++ Wabbajack.CLI/Verbs/Decrypt.cs | 23 +++++++++++++++++++++++ Wabbajack.CLI/Verbs/Encrypt.cs | 22 ++++++++++++++++++++++ Wabbajack.CLI/Wabbajack.CLI.csproj | 17 +++++++++++++++++ Wabbajack.Common/Utils.cs | 18 ++++++++++++++---- Wabbajack.sln | 10 ++++++++++ 7 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 Wabbajack.CLI/OptionsDefinition.cs create mode 100644 Wabbajack.CLI/Program.cs create mode 100644 Wabbajack.CLI/Verbs/Decrypt.cs create mode 100644 Wabbajack.CLI/Verbs/Encrypt.cs create mode 100644 Wabbajack.CLI/Wabbajack.CLI.csproj diff --git a/Wabbajack.CLI/OptionsDefinition.cs b/Wabbajack.CLI/OptionsDefinition.cs new file mode 100644 index 00000000..131927bc --- /dev/null +++ b/Wabbajack.CLI/OptionsDefinition.cs @@ -0,0 +1,13 @@ +using System; +using Wabbajack.CLI.Verbs; + +namespace Wabbajack.CLI +{ + public class OptionsDefinition + { + public static Type[] AllOptions = new[] + { + typeof(OptionsDefinition), typeof(Encrypt), typeof(Decrypt) + }; + } +} diff --git a/Wabbajack.CLI/Program.cs b/Wabbajack.CLI/Program.cs new file mode 100644 index 00000000..97f0c1d8 --- /dev/null +++ b/Wabbajack.CLI/Program.cs @@ -0,0 +1,18 @@ +using System; +using CommandLine; +using Wabbajack.CLI.Verbs; + +namespace Wabbajack.CLI +{ + class Program + { + static int Main(string[] args) + { + return CommandLine.Parser.Default.ParseArguments(args, OptionsDefinition.AllOptions) + .MapResult( + (Encrypt opts) => Encrypt.Run(opts), + (Decrypt opts) => Decrypt.Run(opts), + errs => 1); + } + } +} diff --git a/Wabbajack.CLI/Verbs/Decrypt.cs b/Wabbajack.CLI/Verbs/Decrypt.cs new file mode 100644 index 00000000..9796fad0 --- /dev/null +++ b/Wabbajack.CLI/Verbs/Decrypt.cs @@ -0,0 +1,23 @@ +using Alphaleonis.Win32.Filesystem; +using CommandLine; +using Wabbajack.Common; + +namespace Wabbajack.CLI.Verbs +{ + [Verb("decrypt", HelpText = @"Decrypt data from AppData\Local\Wabbajack and store it locally", Hidden = true)] + public class Decrypt + { + [Option('n', "name", Required = true, HelpText = @"Credential to encrypt and store in AppData\Local\Wabbajack")] + public string Name { get; set; } + + + [Option('o', "output", Required = true, HelpText = @"Output file for the decrypted data")] + public string Output { get; set; } + + public static int Run(Decrypt opts) + { + File.WriteAllBytes(opts.Output, Utils.FromEncryptedData(opts.Name)); + return 0; + } + } +} diff --git a/Wabbajack.CLI/Verbs/Encrypt.cs b/Wabbajack.CLI/Verbs/Encrypt.cs new file mode 100644 index 00000000..a9b8a7b9 --- /dev/null +++ b/Wabbajack.CLI/Verbs/Encrypt.cs @@ -0,0 +1,22 @@ +using Alphaleonis.Win32.Filesystem; +using CommandLine; +using Wabbajack.Common; + +namespace Wabbajack.CLI.Verbs +{ + [Verb("encrypt", HelpText = @"Encrypt local data and store it in AppData\Local\Wabbajack", Hidden = true)] + public class Encrypt + { + [Option('n', "name", Required = true, HelpText = @"Credential to encrypt and store in AppData\Local\Wabbajack")] + public string Name { get; set; } + + [Option('i', "input", Required = true, HelpText = @"Source data file name")] + public string Input { get; set; } + + public static int Run(Encrypt opts) + { + File.ReadAllBytes(opts.Input).ToEcryptedData(opts.Name); + return 0; + } + } +} diff --git a/Wabbajack.CLI/Wabbajack.CLI.csproj b/Wabbajack.CLI/Wabbajack.CLI.csproj new file mode 100644 index 00000000..17926d81 --- /dev/null +++ b/Wabbajack.CLI/Wabbajack.CLI.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index 6235d73a..7c1c0c02 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -1082,6 +1082,18 @@ namespace Wabbajack.Common public static void ToEcryptedJson(this T data, string key) { var bytes = Encoding.UTF8.GetBytes(data.ToJSON()); + bytes.ToEcryptedData(key); + } + + public static T FromEncryptedJson(string key) + { + var decoded = FromEncryptedData(key); + return Encoding.UTF8.GetString(decoded).FromJSONString(); + } + + + public static void ToEcryptedData(this byte[] bytes, string key) + { var encoded = ProtectedData.Protect(bytes, Encoding.UTF8.GetBytes(key), DataProtectionScope.LocalMachine); if (!Directory.Exists(Consts.LocalAppDataPath)) @@ -1090,13 +1102,11 @@ namespace Wabbajack.Common var path = Path.Combine(Consts.LocalAppDataPath, key); File.WriteAllBytes(path, encoded); } - - public static T FromEncryptedJson(string key) + public static byte[] FromEncryptedData(string key) { var path = Path.Combine(Consts.LocalAppDataPath, key); var bytes = File.ReadAllBytes(path); - var decoded = ProtectedData.Unprotect(bytes, Encoding.UTF8.GetBytes(key), DataProtectionScope.LocalMachine); - return Encoding.UTF8.GetString(decoded).FromJSONString(); + return ProtectedData.Unprotect(bytes, Encoding.UTF8.GetBytes(key), DataProtectionScope.LocalMachine); } public static bool HaveEncryptedJson(string key) diff --git a/Wabbajack.sln b/Wabbajack.sln index 758ac1ff..698b3135 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.VirtualFileSystem EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.Test", "Wabbajack.Test\Wabbajack.Test.csproj", "{81F87B8B-D5CE-4807-9005-38DE95BD7840}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.CLI", "Wabbajack.CLI\Wabbajack.CLI.csproj", "{685D8BB1-D178-4D2C-85C7-C54A36FB7454}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -132,6 +134,14 @@ Global {81F87B8B-D5CE-4807-9005-38DE95BD7840}.Release|Any CPU.Build.0 = Release|Any CPU {81F87B8B-D5CE-4807-9005-38DE95BD7840}.Release|x64.ActiveCfg = Release|x64 {81F87B8B-D5CE-4807-9005-38DE95BD7840}.Release|x64.Build.0 = Release|x64 + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Debug|Any CPU.Build.0 = Debug|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Debug|x64.ActiveCfg = Debug|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Debug|x64.Build.0 = Debug|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Release|Any CPU.ActiveCfg = Release|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Release|Any CPU.Build.0 = Release|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Release|x64.ActiveCfg = Release|Any CPU + {685D8BB1-D178-4D2C-85C7-C54A36FB7454}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE