This provides (my own) implementation of ToBase64String and FromBase64String (since the .NET implementations suck), and a ToBase32String (since .NET hasn't one)./// <summary>/// Provides extensions to convert certain objects to certain other objects./// </summary>public static class StringHelpers{    /// <summary>    /// Converts a byte-array to an RFC4648 (https://tools.ietf.org/html/rfc4648) Base64 string.    /// </summary>    /// <param name=input>The input byte-array.</param>    /// <param name=options>Any of <see cref=Base64FormattingOptions/> enumeration values.</param>    /// <returns>The input byte-array encoded into a Base64 string, following the provided options.</returns>    public static string ToBase64String(byte[] input, Base64FormattingOptions options = Base64FormattingOptions.RequirePaddingCharacter)    {        string alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=;        if ((options & Base64FormattingOptions.UrlFilenameSafeAlphabet) == Base64FormattingOptions.UrlFilenameSafeAlphabet)            alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=;        else if ((options & Base64FormattingOptions.UnixCryptAlphabet) == Base64FormattingOptions.UnixCryptAlphabet)            alphabet = ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=;        string workingResult = ;        int originalLength = input.Length;        int newLength = originalLength;        if (input.Length % 3 != 0)            newLength += 3 - (originalLength % 3);        byte[] workingSet = new byte[newLength];        for (int i = 0; i < originalLength; i++)        {            workingSet[i] = input[i];        }        for (int g = 0; g < newLength / 3; g++)        {            workingResult += alphabet[((workingSet[(g * 3)] & 0xFC) >> 2)];            workingResult += alphabet[((workingSet[(g * 3)] & 0x03) << 4) | ((workingSet[(g * 3) + 1] & 0xF0) >> 4)];            workingResult += alphabet[((workingSet[(g * 3) + 1] & 0x0F) << 2) | ((workingSet[(g * 3) + 2] & 0xC0) >> 6)];            workingResult += alphabet[((workingSet[(g * 3) + 2] & 0x3F))];        }        if ((options & Base64FormattingOptions.RequirePaddingCharacter) == Base64FormattingOptions.RequirePaddingCharacter)        {            if (originalLength != newLength)            {                for (int p = 0; p < newLength - originalLength; p++)                    workingResult += alphabet[64];            }        }        int lineBreaks = 0;        if ((options & Base64FormattingOptions.BreakLinesAt64Characters) == Base64FormattingOptions.BreakLinesAt64Characters)            lineBreaks = 64;        else if ((options & Base64FormattingOptions.BreakLinesAt76Characters) == Base64FormattingOptions.BreakLinesAt76Characters)            lineBreaks = 76;        string result = ;        if (lineBreaks > 0)        {            for (int l = 0; l < workingResult.Length / lineBreaks; l++)                result += workingResult.Substring(l * lineBreaks, lineBreaks) + \r\n;        }        else            result = workingResult;        return result;    }    /// <summary>    /// Converts a byte-array to an RFC4648 (https://tools.ietf.org/html/rfc4648) Base32 string.    /// </summary>    /// <param name=input>The input byte-array.</param>    /// <param name=options>Any of <see cref=Base32FormattingOptions/> enumeration values.</param>    /// <returns>The input byte-array encoded into a Base32 string, following the provided options.</returns>    public static string ToBase32String(this byte[] input, Base32FormattingOptions options = Base32FormattingOptions.RequirePaddingCharacter)    {        string alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=;        if ((options & Base32FormattingOptions.CrockfordAlphabet) == Base32FormattingOptions.CrockfordAlphabet)            alphabet = 0123456789ABCDEFGHJKMNPQRSTVWXYZ=;        else if ((options & Base32FormattingOptions.Hex32Alphabet) == Base32FormattingOptions.Hex32Alphabet)            alphabet = 0123456789ABCDEFGHIJKLMNOPQRSTUV=;        else if ((options & Base32FormattingOptions.VowelSafeAlphabet) == Base32FormattingOptions.VowelSafeAlphabet)            alphabet = 0123456789bcdfhjkmnpqrtvxyDFGHJL=;        string workingResult = ;        int originalLength = input.Length;        int newLength = originalLength;        if (input.Length % 5 != 0)            newLength += originalLength % 5;        byte[] workingSet = new byte[newLength];        for (int i = 0; i < originalLength; i++)        {            workingSet[i] = input[i];        }        for (int g = 0; g < newLength / 5; g++)        {            workingResult += alphabet[((workingSet[(g * 5)] & 0xF4) >> 3)];            workingResult += alphabet[((workingSet[(g * 5)] & 0x03) << 2) | ((workingSet[(g * 5) + 1] & 0xC0) >> 6)];            workingResult += alphabet[((workingSet[(g * 5) + 1] & 0x3E) >> 1)];            workingResult += alphabet[((workingSet[(g * 5) + 1] & 0x01) << 4) | ((workingSet[(g * 5) + 2] & 0xF0) >> 4)];            workingResult += alphabet[((workingSet[(g * 5) + 2] & 0x0F) << 1) | ((workingSet[(g * 5) + 3] & 0x80) >> 7)];            workingResult += alphabet[((workingSet[(g * 5) + 3] & 0x7C) >> 2)];            workingResult += alphabet[((workingSet[(g * 5) + 3] & 0x03) << 3) | ((workingSet[(g * 5) + 4] & 0xE0) >> 5)];            workingResult += alphabet[((workingSet[(g * 5) + 4] & 0x1F))];        }        if ((options & Base32FormattingOptions.RequirePaddingCharacter) == Base32FormattingOptions.RequirePaddingCharacter)        {            if (originalLength != newLength)            {                for (int p = 0; p < newLength - originalLength; p++)                    workingResult += alphabet[32];            }        }        string result = ;        result = workingResult;        return result;    }    /// <summary>    /// Converts an RFC4648 (https://tools.ietf.org/html/rfc4648) Base64 string to a byte-array.    /// </summary>    /// <param name=input>The input string.</param>    /// <param name=options>Any of <see cref=Base64FormattingOptions/> enumeration values.</param>    /// <returns>The input Base64 string decoded into a byte-array string, following the provided options.</returns>    public static byte[] FromBase64String(string input, Base64FormattingOptions options = Base64FormattingOptions.RequirePaddingCharacter)    {        string alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=;        if ((options & Base64FormattingOptions.UrlFilenameSafeAlphabet) == Base64FormattingOptions.UrlFilenameSafeAlphabet)            alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=;        else if ((options & Base64FormattingOptions.UnixCryptAlphabet) == Base64FormattingOptions.UnixCryptAlphabet)            alphabet = ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=;        string workingSet = input.Replace(\r\n, );        int originalLength = input.Length;        int newLength = originalLength;        if (newLength % 4 != 0)            if ((options & Base64FormattingOptions.RequirePaddingCharacter) == Base64FormattingOptions.RequirePaddingCharacter)                throw new ArgumentException(The input string did not contain a required padding character.);        newLength = newLength / 4 * 3;        if (input[originalLength - 1] == alphabet[64])        {            if (input[originalLength - 2] == alphabet[64])                newLength -= 2;            else                newLength -= 1;        }        byte[] workingResult = new byte[newLength];        for (int g = 0; g < newLength / 3; g++)        {            workingResult[g * 3] = (byte)(((alphabet.IndexOf(workingSet[g * 4])) << 2) | ((alphabet.IndexOf(workingSet[g * 4 + 1])) >> 4));            workingResult[g * 3 + 1] = (byte)(((alphabet.IndexOf(workingSet[g * 4 + 1])) << 4) | ((alphabet.IndexOf(workingSet[g * 4 + 2])) >> 2));            workingResult[g * 3 + 2] = (byte)(((alphabet.IndexOf(workingSet[g * 4 + 2])) << 6) | ((alphabet.IndexOf(workingSet[g * 4 + 3]))));        }        byte[] result = workingResult;        return result;    }}Related enumerations:/// <summary>/// A series of values that may be used in any combination to determine how a Base64 string will be formatted./// </summary>[Flags]public enum Base64FormattingOptions{    /// <summary>    /// Do not use any special options.    /// </summary>    None = 0x00,    /// <summary>    /// Include the padding character at the end of the string, if neccessary.    /// </summary>    RequirePaddingCharacter = 0x01,    /// <summary>    /// Insert line breaks after every 64 characters in the string representation. Superceeds 76-character breaks.    /// </summary>    BreakLinesAt64Characters = 0x02,    /// <summary>    /// Insert line breaks after every 76 characters in the string representation.    /// </summary>    BreakLinesAt76Characters = 0x04,    /// <summary>    /// Utilize an alphabet with safe characters allowed in filenames and URLs. Superceeds all other alphabets.    /// </summary>    UrlFilenameSafeAlphabet = 0x10,    /// <summary>    /// Utilizes an alphabet compatible with Unix Crypt PASSWD stores.    /// </summary>    UnixCryptAlphabet = 0x20,    // Composite options    /// <summary>    /// Composite flag for use encoding to original Privacy-Enhanced Mail (RFC 1421) Base64.    /// </summary>    Rfc1421PemEncoding = 0x03,    /// <summary>    /// Composite flag for use encoding to MIME (RFC 2045) Base64.    /// </summary>    Rfc2045MimeEncoding = 0x05,    /// <summary>    /// Encodes to RFC 3548 (obsoleted by RFC 4648) standard encoding, with 64-character lines.    /// </summary>    Rfc3548Standard64Encoding = 0x03,    /// <summary>    /// Encodes to RFC 3548 (obsoleted by RFC 4648) standard encoding, with 76-character lines.    /// </summary>    Rfc3548Standard76Encoding = 0x05,    /// <summary>    /// Encodes to RFC 4648 URL/Filename Safe encoding, with no line breaks.    /// </summary>    Rfc4648UrlFilenameEncoding = 0x11,    /// <summary>    /// Encodes to RFC 4648 URL/Filename Safe encoding, with 64-character lines.    /// </summary>    Rfc4648UrlFilename64Encoding = 0x13,    /// <summary>    /// Encodes to RFC 4648 URL/Filename Safe encoding, with 76-character lines.    /// </summary>    Rfc4648UrlFilename76Encoding = 0x15,}/// <summary>/// A series of values that may be used in any combination to determine how a Base32 string will be formatted./// </summary>[Flags]public enum Base32FormattingOptions{    /// <summary>    /// Do not use any special options.    /// </summary>    None = 0x00,    /// <summary>    /// Include the padding character at the end of the string, if neccessary.    /// </summary>    RequirePaddingCharacter = 0x01,    /// <summary>    /// Utilizes the Crockford Base32 alphabet.    /// </summary>    CrockfordAlphabet = 0x10,    /// <summary>    /// Utilizes an alphabet that is a direct extension of Base16 Hexadecimal.    /// </summary>    Hex32Alphabet = 0x20,    /// <summary>    /// Utilizes a proprietary alphabet that excludes vowels and other non-distinguished characters to prevent the chances of obscene words being generated. Alphabet is 0123456789bcdfhjkmnpqrtvxyDFGHJL with an equal sign (=) for optional padding.    /// </summary>    VowelSafeAlphabet = 0x40,}Any comments/feedback welcome.Also, do note, anyone (who wants to) is free to use this.
Replacement string Base64 (and a Base32) conversion
c#;strings;.net;converting;formatting
Options on a single byteYou're using the values of Base64FormattingOptions to store all options on a single byte.I'm wondering why you want to do that.It raises some questions when setting conflicting values.For example, if I set both UrlFilenameSafeAlphabet and UnixCryptAlphabet (= 0x10 | 0x20 = 0x30), which one will be actually used?Sure, looking at the implementation I know which one,but I shouldn't do that,as that would violates information hiding.You could say the one with the smaller enum value takes precedent,but then again, I shouldn't have to know about the enum values either,and I shouldn't have to make guesses.It would be better to use an enumeration for the allowed alphabet types.That way the compiler will guarantee that one specific value is used,and no further questions and ambiguity about it.I guess you liked the idea of simply OR-ing together the different kinds of options you want.It will get more tedious when you refactor using a more complex config object.To remedy that, the builder pattern with a fluent interface can be useful here.Repeated offset valuesg * 3 and g * X appear repeated many times.I suggest putting the value in an offset variable.Variable l (lowercase L)I suggest to never use lowercase L as a variable name.Single-letter variables are generally frowned upon,but this is the worst: on some displays with certain fonts it's indistinguishable from 1 (one) or | (pipe).BracesYou know what they say about putting braces on even single-line if/for/while statements...NewlineInstead of hardcoding \r\n,it might be a good idea to put it in a constant.Pointless intermediary variableThis looks like leftover from something copy-pasted:    string result = ;    result = workingResult;    return result;