How to achieve Base64 URL safe encoding in C#?
C#EncodingBase64C# 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;