Code for decoding/encoding a modified base64 URL (in ASP.NET Framework)

C#UrlBase64EncodeDecode

C# Problem Overview


I want to base64 encode data to put it in a URL and then decode it within my HttpHandler.

I have found that Base64 Encoding allows for a '/' character which will mess up my UriTemplate matching. Then I found that there is a concept of a "modified Base64 for URL" from wikipedia:

A modified Base64 for URL variant exists, where no padding '=' will be used, and the '+' and '/' characters of standard Base64 are respectively replaced by '-' and '_', so that using URL encoders/decoders is no longer necessary and has no impact on the length of the encoded value, leaving the same encoded form intact for use in relational databases, web forms, and object identifiers in general.

Using .NET I want to modify my current code from doing basic base64 encoding and decoding to using the "modified base64 for URL" method. Has anyone done this?

To decode, I know it starts out with something like:

string base64EncodedText = base64UrlEncodedText.Replace('-', '+').Replace('_', '/');

// Append '=' char(s) if necessary - how best to do this?

// My normal base64 decoding now uses encodedText

But, I need to potentially add one or two '=' chars to the end which looks a little more complex.

My encoding logic should be a little simpler:

// Perform normal base64 encoding
byte[] encodedBytes = Encoding.UTF8.GetBytes(unencodedText);
string base64EncodedText = Convert.ToBase64String(encodedBytes);

// Apply URL variant
string base64UrlEncodedText = base64EncodedText.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');

I have seen the Guid to Base64 for URL StackOverflow entry, but that has a known length and therefore they can hardcode the number of equal signs needed at the end.

C# Solutions


Solution 1 - C#

Also check class HttpServerUtility with UrlTokenEncode and UrlTokenDecode methods that is handling URL safe Base64 encoding and decoding.

Note 1: The result is not a valid Base64 string. Some unsafe characters for URL are replaced.

Note 2: The result differs from the base64url algorithm in RFC4648, it replaces the '=' padding with '0', '1' or '2' depending on how many equal signs it replaced to make the value safe for a query parameter.

///<summary>
/// Base 64 Encoding with URL and Filename Safe Alphabet using UTF-8 character set.
///</summary>
///<param name="str">The origianl string</param>
///<returns>The Base64 encoded string</returns>
public static string Base64ForUrlEncode(string str)
{
    byte[] encbuff = Encoding.UTF8.GetBytes(str);
    return HttpServerUtility.UrlTokenEncode(encbuff);
}
///<summary>
/// Decode Base64 encoded string with URL and Filename Safe Alphabet using UTF-8.
///</summary>
///<param name="str">Base64 code</param>
///<returns>The decoded string.</returns>
public static string Base64ForUrlDecode(string str)
{
    byte[] decbuff = HttpServerUtility.UrlTokenDecode(str);
    return Encoding.UTF8.GetString(decbuff);
}

Solution 2 - C#

This ought to pad it out correctly:-

 base64 = base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=');

Solution 3 - C#

Not enough points to comment, but in case it helps, the code snippet that Sushil found in the link provided (JSON Web Signature ietf draft) works for when encoding Base 64 as a parameter in URL.

Copied snippet below for those that are lazy:

    static string Base64UrlEncode(byte[] arg)
    {
        string s = Convert.ToBase64String(arg); // Regular base64 encoder
        s = s.Split('=')[0]; // Remove any trailing '='s
        s = s.Replace('+', '-'); // 62nd char of encoding
        s = s.Replace('/', '_'); // 63rd char of encoding
        return s;
    }

    static byte[] Base64UrlDecode(string arg)
    {
        string s = arg;
        s = s.Replace('-', '+'); // 62nd char of encoding
        s = s.Replace('_', '/'); // 63rd char of encoding
        switch (s.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 2: s += "=="; break; // Two pad chars
            case 3: s += "="; break; // One pad char
            default: throw new System.Exception(
              "Illegal base64url string!");
        }
        return Convert.FromBase64String(s); // Standard base64 decoder
    }

Solution 4 - C#

I hit here while looking for code to do encode/decode for base64url encoding which is little different than base64 as explained in the question.

Found c# code snippet in this document. JSON Web Signature ietf draft

Solution 5 - C#

In comparison to the accepted answer, here is how you would fundamentally decode a base64 encoded url, using C#:

Decode:

string codedValue = "base64encodedUrlHere";

string decoded;
byte[] buffer =  Convert.FromBase64String(codedValue);
decoded = Encoding.UTF8.GetString(buffer);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKirk LiemohnView Question on Stackoverflow
Solution 1 - C#Fredrik HaglundView Answer on Stackoverflow
Solution 2 - C#AnthonyWJonesView Answer on Stackoverflow
Solution 3 - C#Stefan ZvonarView Answer on Stackoverflow
Solution 4 - C#SushilView Answer on Stackoverflow
Solution 5 - C#Chris HalcrowView Answer on Stackoverflow