How to achieve Base64 URL safe encoding in C#?

C#EncodingBase64

C# Problem Overview


I want to achieve Base64 URL safe encoding in C#. In Java, we have the common Codec library which gives me an URL safe encoded string. How can I achieve the same using C#?

byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes("StringToEncode");
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

The above code converts it to Base64, but it pads ==. Is there is way to achieve URL safe encoding?

C# Solutions


Solution 1 - C#

It is common to simply swap alphabet for use in urls, so that no %-encoding is necessary; only 3 of the 65 characters are problematic - +, / and =. the most common replacements are - in place of + and _ in place of /. As for the padding: just remove it (the =); you can infer the amount of padding needed. At the other end: just reverse the process:

string returnValue = System.Convert.ToBase64String(toEncodeAsBytes)
        .TrimEnd(padding).Replace('+', '-').Replace('/', '_');

with:

static readonly char[] padding = { '=' };

and to reverse:

string incoming = returnValue
    .Replace('_', '/').Replace('-', '+');
switch(returnValue.Length % 4) {
    case 2: incoming += "=="; break;
    case 3: incoming += "="; break;
}
byte[] bytes = Convert.FromBase64String(incoming);
string originalText = Encoding.ASCII.GetString(bytes);

The interesting question, however, is: is this the same approach that the "common codec library" uses? It would certainly be a reasonable first thing to test - this is a pretty common approach.

Solution 2 - C#

You can use class Base64UrlEncoder from namespace Microsoft.IdentityModel.Tokens.

const string StringToEncode = "He=llo+Wo/rld";

var encodedStr = Base64UrlEncoder.Encode(StringToEncode);
var decodedStr = Base64UrlEncoder.Decode(encodedStr);

if (decodedStr == StringToEncode)
    Console.WriteLine("It works!");
else
    Console.WriteLine("Dangit!");

Solution 3 - C#

Another option, if you are using ASP.NET Core, would be to use Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode.

If you are not using ASP.NET Core, the WebEncoders source is available under the Apache 2.0 License.

Solution 4 - C#

Based off the answers here with some performance improvements, we've published a very easy to use url-safe base64 implementation to NuGet with the source code available on GitHub (MIT licensed).

Usage is as easy as

var bytes = Encoding.UTF8.GetBytes("Foo");
var encoded = UrlBase64.Encode(bytes);
var decoded = UrlBase64.Decode(encoded);

Solution 5 - C#

To get an URL-safe base64-like encoding, but not "base64url" according to RFC4648, use System.Web.HttpServerUtility.UrlTokenEncode(bytes) to encode, and System.Web.HttpServerUtility.UrlTokenDecode(bytes) to decode.

Solution 6 - C#

Simplest solution: (with no padding)

private static string Base64UrlEncode(string input) {
    var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
    // Special "url-safe" base64 encode.
    return Convert.ToBase64String(inputBytes)
      .Replace('+', '-') // replace URL unsafe characters with safe ones
      .Replace('/', '_') // replace URL unsafe characters with safe ones
      .Replace("=", ""); // no padding
  }

Credit goes to: Tholle

Solution 7 - C#

	public string Decode(string str)
	{
	   byte[] decbuff = Convert.FromBase64String(str.Replace(",", "=").Replace("-", "+").Replace("/", "_"));
	   return System.Text.Encoding.UTF8.GetString(decbuff);
	}
	
    public string Encode(string input)
    {
        byte[] encbuff = Encoding.UTF8.GetBytes(input ?? "");
        return Convert.ToBase64String(encbuff).Replace("=", ",").Replace("+", "-").Replace("_", "/");
    }

This is the way to do it to align with JavaScript!

Solution 8 - C#

Here is another method to decode an url-safe base64 was encode by same way with Marc. I just don't get why 4-length%4 worked(it does).

As follows, only the origin's bit length are common multiple of 6 and 8, base64 do not append "=" to result.

1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8 
1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6
                "=="            "="

So we can do it conversely, if result's bit length can't divisible by 8, it has been appended:

base64String = base64String.Replace("-", "+").Replace("_", "/");
var base64 = Encoding.ASCII.GetBytes(base64String);
var padding = base64.Length * 3 % 4;//(base64.Length*6 % 8)/2
if (padding != 0)
{
    base64String = base64String.PadRight(base64String.Length + padding, '=');
}
return Convert.FromBase64String(base64String);

Solution 9 - C#

Karanvir Kang's answer is a good one and I voted for it. However, it does leave an odd character on the end of the string (indicating the number of padding characters removed). Here is my solution.

var bytesToEncode = System.Text.Encoding.UTF8.GetBytes("StringToEncode"); 
var bytesEncodedPadded = HttpServerUtility.UrlTokenEncode(bytesToEncode);
var objectIdBase64 = bytesEncodedPadded.Substring(0, bytesEncodedPadded.Length - 1);

Solution 10 - C#

Using Microsoft cryptographic engine in UWP.

uint length = 32;

IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
string base64Str = CryptographicBuffer.EncodeToBase64String(buffer)
                   // ensure url safe
                   .TrimEnd('=').Replace('+', '-').Replace('/', '_');

return base64Str;

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
QuestionVishvesh PhadnisView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#JeromeView Answer on Stackoverflow
Solution 3 - C#KevinoidView Answer on Stackoverflow
Solution 4 - C#Mahmoud Al-QudsiView Answer on Stackoverflow
Solution 5 - C#Karanvir KangView Answer on Stackoverflow
Solution 6 - C#AshiView Answer on Stackoverflow
Solution 7 - C#ShiroyView Answer on Stackoverflow
Solution 8 - C#joyjyView Answer on Stackoverflow
Solution 9 - C#JoshcodesView Answer on Stackoverflow
Solution 10 - C#viscView Answer on Stackoverflow