diff --git a/Dalamud.Bootstrap/Bootstrapper.cs b/Dalamud.Bootstrap/Bootstrapper.cs index d90a29b70..b604fb606 100644 --- a/Dalamud.Bootstrap/Bootstrapper.cs +++ b/Dalamud.Bootstrap/Bootstrapper.cs @@ -94,11 +94,15 @@ namespace Dalamud.Bootstrap throw new BootstrapException($"Process id {process.Id} does not have any arguments to parse."); } - if (EncryptedArgument.Extract(arguments[0], out var encryptedPayload, out var _)) + var argument = arguments[0]; + + if (EncryptedArgument.TryParse(argument, out var encryptedArgument)) { var key = RecoverKey(process); - EncryptedArgument.Decry(encryptedPayload, key) + // } + + } /// diff --git a/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs b/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs index 2b4c7a479..d77948826 100644 --- a/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs +++ b/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs @@ -1,36 +1,40 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Runtime.InteropServices; -using System.Text; using System.Text.RegularExpressions; -using Dalamud.Bootstrap.Crypto; namespace Dalamud.Bootstrap.SqexArg { internal sealed class EncryptedArgument { - private static char[] ChecksumTable = new char[] - { - 'f', 'X', '1', 'p', 'G', 't', 'd', 'S', - '5', 'C', 'A', 'P', '4', '_', 'V', 'L' - }; + /// + /// A data that is encrypted and encoded in url-safe variant of base64. + /// + public string Data { get; } /// - /// Denotes that no checksum is encoded. + /// A checksum that is used to validate the encryption key. /// - private const char NoChecksumMarker = '!'; + public char Checksum { get; } - private IMemoryOwner m_encryptedData; + public EncryptedArgument(string data, char checksum) + { + Data = data; + Checksum = checksum; + } /// - /// Encrypts the argument with given key. + /// /// - /// - /// - public EncryptedArgument(string argument, uint key) + /// An argument that is encrypted and usually starts with //**sqex0003 and ends with **// + /// Returns true if successful, false otherwise. + public static bool TryParse(string argument, out EncryptedArgument output) { - + if (!Extract(argument, out var data, out var checksum)) + { + output = null!; + return false; + } + + output = new EncryptedArgument(data, checksum); + return true; } /// @@ -40,11 +44,11 @@ namespace Dalamud.Bootstrap.SqexArg /// An encrypted payload extracted. The value is undefined if the function fails. /// A checksum of the key extracted. The value is undefined if the function fails. /// Returns true on success, false otherwise. - public static bool Extract(string argument, out byte[] payload, out char checksum) + private static bool Extract(string argument, out string payload, out char checksum) { // must start with //**sqex0003, some characters, one checksum character and end with **// var regex = new Regex(@"^\/\/\*\*sqex0003(?.+)(?.)\*\*\/\/$"); - + var match = regex.Match(argument); if (!match.Success) { @@ -53,86 +57,13 @@ namespace Dalamud.Bootstrap.SqexArg return false; } - // Extract checksum + // Extract checksum = match.Groups["checksum"].Value[0]; - - // Extract payload - var payloadStr = match.Groups["payload"].Value; - payload = DecodeUrlSafeBase64(payloadStr); + payload = match.Groups["payload"].Value; return true; } - public override string ToString() - { - var checksum = GetChecksumFromKey(); - } - - private static char GetChecksumFromKey(uint key) - { - var index = (key & 0x000F_0000) >> 16; - - return ChecksumTable[index]; - } - - /// - /// - /// - /// Indicates that returned buffer must be larger than `minimumSize` bytes. - /// - /// A buffer aligned to next multiple of block size. - /// Dispose() must be called when it's not used anymore. - /// - private static IMemoryOwner CreateAlignedBuffer(int minimumSize) - { - // align to next multiple of block size. - var alignedSize = (minimumSize + Blowfish.BlockSize - 1) & (~(-Blowfish.BlockSize)); - - return MemoryPool.Shared.Rent(alignedSize); - } - - /// - /// Formats a key. - /// - /// A secret key. - /// A buffer where formatted key will be stored. This must be larger than 8 bytes. - private static void CreateKey(uint key, Span destination) - { - if (!Utf8Formatter.TryFormat(key, destination, out var _, new StandardFormat('x', 8))) - { - throw new InvalidOperationException("BUG: Could not create a key"); - } - } - - /// - /// Converts the url-safe variant of base64 string to bytes. - /// - /// A url-safe variant of base64 string. - private static byte[] DecodeUrlSafeBase64(string payload) - { - var base64Str = payload - .Replace('-', '+') - .Replace('_', '/'); - - try - { - return Convert.FromBase64String(base64Str); - } - catch (FormatException ex) - { - // This is expected to happen if the argument is ill-formed - throw new SqexArgException($"A payload {payload} does not look like a valid encrypted argument.", ex); - } - } - - private static string EncodeUrlSafeBase64(byte[] payload) - { - var payloadStr = Convert.ToBase64String(payload); - - return payloadStr - .Replace('+', '-') - .Replace('/', '_'); - - } + public override string ToString() => $"//**sqex0003{Data}{Checksum}**//"; } } diff --git a/Dalamud.Bootstrap/SqexArg/EncryptedArgumentExtensions.cs b/Dalamud.Bootstrap/SqexArg/EncryptedArgumentExtensions.cs new file mode 100644 index 000000000..1876752dc --- /dev/null +++ b/Dalamud.Bootstrap/SqexArg/EncryptedArgumentExtensions.cs @@ -0,0 +1,64 @@ +using System; +using System.Buffers; +using System.Buffers.Text; +using Dalamud.Bootstrap.Crypto; + +namespace Dalamud.Bootstrap.SqexArg +{ + internal static class EncryptedArgumentExtensions + { + public static void Decrypt(this EncryptedArgument argument, uint key) + { + Span keyBytes = stackalloc byte[8]; + CreateKey(key, keyBytes); + + var blowfish = new Blowfish(keyBytes); + + + } + + /// + /// Formats a key. + /// + /// A secret key. + /// A buffer where formatted key will be stored. This must be larger than 8 bytes. + private static void CreateKey(uint key, Span destination) + { + if (!Utf8Formatter.TryFormat(key, destination, out var _, new StandardFormat('x', 8))) + { + throw new InvalidOperationException("BUG: Could not create a key"); + } + } + + /// + /// Converts the url-safe variant of base64 string to bytes. + /// + /// A url-safe variant of base64 string. + private static byte[] DecodeUrlSafeBase64(string payload) + { + var base64Str = payload + .Replace('-', '+') + .Replace('_', '/'); + + try + { + return Convert.FromBase64String(base64Str); + } + catch (FormatException ex) + { + // This is expected to happen if the argument is ill-formed + throw new SqexArgException($"A payload {payload} does not look like a valid encrypted argument.", ex); + } + } + + private static string EncodeUrlSafeBase64(byte[] payload) + { + var payloadStr = Convert.ToBase64String(payload); + + return payloadStr + .Replace('+', '-') + .Replace('/', '_'); + + } + } +}