182

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?

6
  • 1
    Can't you just use Url.Encode on string in BASE64? Commented Oct 14, 2014 at 6:15
  • In which namespace Url class is present in c#? Commented Oct 14, 2014 at 6:22
  • Take a look: msdn.microsoft.com/en-us/library/… You need to reference System.Web assembly. Commented Oct 14, 2014 at 6:24
  • It's converting = into %3D. I dont want that. Commented Oct 14, 2014 at 6:38
  • 3
    So what you mean by url safe? %3D is url safe. Commented Oct 14, 2014 at 6:39

12 Answers 12

270

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.

Sign up to request clarification or add additional context in comments.

8 Comments

In Common Codec they are using [0-9a-zA-Z_-] Character for url safe mode.
this is also mentioned in the wiki page for Base64 under URL applications. en.wikipedia.org/wiki/Base64
You also have this function 'stackoverflow.com/questions/1886686/…' which does all the hard work for you.
Why do we not need: case 1: incoming += "==="; break; ?
@alexdafranca because it will never have a length mod 4 of 1. 3x8 bits become 4x6 bits (and each 6 bits is one of 64 characters in the chosen alphabet), 0x8 bits is encoded as 0x6 bits without padding, 1x8 bits is encoded as 2x6 bits with == padding, 2x8 is encoded as 3x6 with = padding, 3x8 is encoded as 4x6 without padding and then it is aligned so it repeats. Nothing is ever encoded to 1x6 bits, so you never need === padding.
|
177

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!"); 

Microsoft.IdentityModel.Tokens is a NuGet package that has to be downloaded.

5 Comments

This is much cleaner than the accepted answer. Any downside ?
I'm assuming by the name that this isn't cross platform. Is that the case?
@BrandonS. Can confirm that it is cross platform. Generating url encoded base 64 string encoded signature that is handled correctly on google GKE
Is there a solution with streams?
From .NET 9 this works ootb too: System.Buffers.Text > Base64Url Class
56

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.

1 Comment

word of caution, tried microsoft.aspnetcore.webutilities.webencoders.base64urlencode in asp.net core 6 and it strips padding.
12

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); 

3 Comments

Amazing thank you. Out of interest why have you opted for "string".Replace for the encode method, but a loop with manual replaces for the decode?
@ᴍᴀᴛᴛʙᴀᴋᴇʀ I need to revisit it and run some benchmarks, but it's because we add to the latter so it's represented by a growable list of characters instead of an immutable string.
Another class with return type = string instead : github.com/vndevpro/architecture-common/blob/master/…
9

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.

1 Comment

This doesn't provide a standards conform URL-safe Base64 encoding according to RFC4648. See also this Q&A. Use with caution.
6

In .NET 9 you can do this without any extra packages using Base64Url:

ReadOnlySpan<byte> bytes = ...; string encoded = Base64Url.EncodeToString(bytes); 

Comments

2

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

Comments

2
 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!

1 Comment

Just based on the other answers, have you got that last Replace right? The other answers have .Replace("/", "_")
1

In .NET 9.0 there is the Base64Url class. It also supports spans.

Example:

using System.Buffers.Text; var base64UrlEncoded = Base64Url.EncodeToString(url); 

The Microsoft.Bcl.Memory package provides the Base64Url type for .NET Framework 4.6.2 and .NET Standard 2.0.

Comments

0

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); 

Comments

-1

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); 

Comments

-2

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; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.