diff --git a/src/Discord.Net.Core/Utils/TokenUtils.cs b/src/Discord.Net.Core/Utils/TokenUtils.cs index 68aad5d96..c820ef069 100644 --- a/src/Discord.Net.Core/Utils/TokenUtils.cs +++ b/src/Discord.Net.Core/Utils/TokenUtils.cs @@ -17,6 +17,49 @@ namespace Discord /// internal const int MinBotTokenLength = 58; + internal const char Base64Padding = '='; + + /// + /// Pads a base64-encoded string with 0, 1, or 2 '=' characters, + /// if the string is not a valid multiple of 4. + /// Does not ensure that the provided string contains only valid base64 characters. + /// + /// + /// A string that would require 3 padding characters is considered to be already corrupt. + /// Some older bot tokens may require padding, as the format provided by Discord + /// does not include this padding in the token. + /// + /// The base64 encoded string to pad with characters. + /// A string containing the base64 padding. + /// + /// Thrown if would require an invalid number of padding characters. + /// + /// + /// Thrown if is null, empty, or whitespace. + /// + /// + /// Thrown if the given input string already contains padding characters. + /// + internal static string PadBase64String(string encodedBase64) + { + if (string.IsNullOrWhiteSpace(encodedBase64)) + throw new ArgumentNullException(paramName: encodedBase64, + message: "The supplied base64-encoded string was null or whitespace."); + + if (encodedBase64.IndexOf(Base64Padding) != -1) + throw new ArgumentException(paramName: encodedBase64, + message: "The supplied base64-encoded string already contains padding characters."); + + // based from https://stackoverflow.com/a/1228744 + var padding = (4 - (encodedBase64.Length % 4)) % 4; + if (padding == 3) + // can never have 3 characters of padding + throw new FormatException("The provided base64 string is corrupt, as it requires an invalid amount of padding."); + else if (padding == 0) + return encodedBase64; + return encodedBase64.PadRight(encodedBase64.Length + padding, Base64Padding); + } + /// /// Decodes a base 64 encoded string into a ulong value. /// @@ -29,6 +72,8 @@ namespace Discord try { + // re-add base64 padding if missing + encoded = PadBase64String(encoded); // decode the base64 string var bytes = Convert.FromBase64String(encoded); var idStr = Encoding.UTF8.GetString(bytes); @@ -46,7 +91,7 @@ namespace Discord } catch (ArgumentException) { - // ignore exception, can be thrown by BitConverter + // ignore exception, can be thrown by BitConverter, or by PadBase64String } return null; }