locked
Encoding special strings - how to make this work? RRS feed

  • Question

  • Hi everybody,

    I am not sure which forum is the best for this question. We have the following code developed by our former contractors

    public static string ToBase64UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !String.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Convert.ToBase64String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }

    This code is used to pass character primary key using Web API calls. For most of the strings we tried (and we normally use just English strings) everything works fine.

    However, recently we installed our application in Spanish speaking country. One of the categories they are trying is COÑAC and this one is failing miserably. Interestingly similar categories tried by my colleague worked fine

    CONAC, RUÑAC, ÑAC, ÑACÑAC

    Do you see what exactly may be a problem here and how to adjust our code to make it bullet-proof?

    When I ran this in debug mode I noticed that the above returns 11 bytes while the category is actually 10 characters long and for all other categories we get 10 bytes.

    Thanks a lot in advance for suggestions.

    So, the above produces %2f as part of the hash and this represents /. So, we figured why we're getting a problem, but I still don't know what kind of a solution to apply to solve it.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles


    • Edited by Naomi N Thursday, July 13, 2017 4:32 AM
    Thursday, July 13, 2017 3:53 AM

Answers

  • Hi Naomi,

    I can feel your pain due to the issue. Base64 is always a painful for me. We used Base32 to overcome from this issue. I also see one more issue in your code:

    var idBytes = Encoding.UTF8.GetBytes(str);

    The above line will throw exception in case 'str' is null. I also fixed the same in suggested code. Following is the complete suggested code, hope this works for you.

    P.S. To use Base32, you need to install Nuget package: https://www.nuget.org/packages/Base3264-UrlEncoder/ A complete source code is also available here: https://github.com/ericlau-solid/Base3264-UrlEncoder/

     internal class Program
        {
            private static void Main(string[] args)
            {
                Console.WriteLine("Base64:" + "COÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "COÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "RUÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "RUÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "ÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "ÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "ÑACÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "ÑACÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "CONAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "CONAC".ToBase32UrlEncoded());
                Console.Read();
            }
        }
    
        public static class MyExtension
        {
            public static string ToBase64UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Convert.ToBase64String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            public static string ToBase32UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Base32Url.ToBase32String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            [Obsolete("This is obsolete, might not work for encoded languages.")]
            public static string FromBase64UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var base64String = HttpUtility.UrlDecode(str);
                var idBytes = Convert.FromBase64String(base64String);
                return Encoding.UTF8.GetString(idBytes);
            }
        }

    Following is the output of above code:

    Happy Coding!!!


    Thanks & Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com


    • Edited by Gaurav Aroraa Friday, July 14, 2017 9:06 PM Uploaded snapshot of output
    • Marked as answer by Naomi N Monday, July 17, 2017 5:34 PM
    Thursday, July 13, 2017 7:50 AM
  • Hi Naomi,

    Here is the code-snippet (with encoding/decoding):

    using System.Text;
    using System.Web;
    using MhanoHarkness;
    using static System.Console;
    
    namespace Converter
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                const string inputText = "COÑAC";
                const string inputText1 = "RUÑAC";
                const string inputText2 = "ÑAC";
                const string inputText3 = "ÑACÑAC";
                const string inputText4 = "CONAC";
                var base32UrlEncoded = inputText.ToBase32UrlEncoded();
                var base32UrlEncoded1 = inputText1.ToBase32UrlEncoded();
                var base32UrlEncoded2 = inputText2.ToBase32UrlEncoded();
                var base32UrlEncoded3 = inputText3.ToBase32UrlEncoded();
    
                var base32UrlEncoded4 = inputText4.ToBase32UrlEncoded();
                WriteLine("Encoding:");
    
                WriteLine($"string {inputText} and Encoded as {base32UrlEncoded}");
                WriteLine($"string {inputText1} and Encoded as {base32UrlEncoded1}");
                WriteLine($"string {inputText2} and Encoded as {base32UrlEncoded2}");
                WriteLine($"string {inputText3} and Encoded as {base32UrlEncoded3}");
                WriteLine($"string {inputText4} and Encoded as {base32UrlEncoded4}");
    
                WriteLine();
                WriteLine("Decoding:");
    
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded} and Decoded into {base32UrlEncoded.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded1} and Decoded into {base32UrlEncoded1.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded2} and Decoded into {base32UrlEncoded2.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded3} and Decoded into {base32UrlEncoded3.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded4} and Decoded into {base32UrlEncoded4.FromBase32UrlDecoded()}");
                Read();
            }
        }
    
        public static class MyExtension
        {
            public static string ToBase32UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Base32Url.ToBase32String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            public static string FromBase32UrlDecoded(this string base32String)
            {
                var base32Decoded = Base32Url.FromBase32String(base32String);
                var idUrlString = Encoding.UTF8.GetString(base32Decoded);
                return idUrlString;
            }
        }
    }

    Following is output of above code:

    Hope this works for you.


    Thanks & Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    • Marked as answer by Naomi N Monday, July 17, 2017 6:15 PM
    Monday, July 17, 2017 6:02 PM

All replies

  • I tried double encoding and decoding, but it also didn't work, I got another error using

    /api/items/getNewItem/7/127/RkJCQVIgICAgIA%253d%253d/Q0%252fDkUFDICAgICA%253d

    HTTP Error 404.11 - Not Found

    The request filtering module is configured to deny a request that contains a double escape sequence.

    <fieldset style="padding:0px 15px 10px;word-break:break-all;">

    Most likely causes:

    • The request contained a double escape sequence and request filtering is configured on the Web server to deny double escape sequences.
    </fieldset>
    <fieldset style="padding:0px 15px 10px;word-break:break-all;">

    Things you can try:

    • Verify the configuration/system.webServer/security/requestFiltering@allowDoubleEscaping setting in the applicationhost.config or web.confg file.
    </fieldset>

    Since the above represents a security hole, I better not change it. 

    So, is there another solution? May be I should manually replace %2f with something? But how would I create a unique replacement for these cases, so I would know how to decode them correctly?


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Thursday, July 13, 2017 5:06 AM
  • Maybe use an encoding that does not include ‘/’. For example:

       var idUrlString = BitConverter.ToString( idBytes ).Replace( "-", "" );

    It is a hexadecimal sequence. The conversion back to string is not difficult .


    • Edited by Viorel_MVP Thursday, July 13, 2017 5:33 AM
    Thursday, July 13, 2017 5:33 AM
  • @Naomi,

    Do you think the problem might not be on the encoding part like the code you listed here rather on the decoding? Could you please check if the webapi decodes the string properly before use it?

    Simply running the code below will restore the original string:

            public static string ConvertBack(this string str)
            {
                string base64String = HttpUtility.UrlDecode(str);
                byte[] idBytes = Convert.FromBase64String(base64String);
                string text = Encoding.UTF8.GetString(idBytes);
                return text;
            }

    I build UWPs: Arrnage Pro, Cloud Resource Tools

    Thursday, July 13, 2017 6:02 AM
  • Hi Naomi,

    I can feel your pain due to the issue. Base64 is always a painful for me. We used Base32 to overcome from this issue. I also see one more issue in your code:

    var idBytes = Encoding.UTF8.GetBytes(str);

    The above line will throw exception in case 'str' is null. I also fixed the same in suggested code. Following is the complete suggested code, hope this works for you.

    P.S. To use Base32, you need to install Nuget package: https://www.nuget.org/packages/Base3264-UrlEncoder/ A complete source code is also available here: https://github.com/ericlau-solid/Base3264-UrlEncoder/

     internal class Program
        {
            private static void Main(string[] args)
            {
                Console.WriteLine("Base64:" + "COÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "COÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "RUÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "RUÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "ÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "ÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "ÑACÑAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "ÑACÑAC".ToBase32UrlEncoded());
                Console.WriteLine("Base64:" + "CONAC".ToBase64UrlEncoded());
                Console.WriteLine("Base32:" + "CONAC".ToBase32UrlEncoded());
                Console.Read();
            }
        }
    
        public static class MyExtension
        {
            public static string ToBase64UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Convert.ToBase64String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            public static string ToBase32UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Base32Url.ToBase32String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            [Obsolete("This is obsolete, might not work for encoded languages.")]
            public static string FromBase64UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var base64String = HttpUtility.UrlDecode(str);
                var idBytes = Convert.FromBase64String(base64String);
                return Encoding.UTF8.GetString(idBytes);
            }
        }

    Following is the output of above code:

    Happy Coding!!!


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com


    • Edited by Gaurav Aroraa Friday, July 14, 2017 9:06 PM Uploaded snapshot of output
    • Marked as answer by Naomi N Monday, July 17, 2017 5:34 PM
    Thursday, July 13, 2017 7:50 AM
  • Hi Gaurav,

    I'm thinking that we have to bite the bullet and do some re-factoring and fixing.

    The project started with the contractors and when many of our tables used character primary keys.

    Since then the tables that originally used these character primary keys now use the integer PKs. So, hashing these original primary keys and using methods to get values based on hash is now unnecessary. We do still use character PKs in few places, so we do need to fix this particular routine to be free of above mentioned problem with the /, but I think right now it would be time to re-factor and get rid of hashing completely for the areas that no longer need them. It may be a lot, but we're making our web-site slower by doing that process right now when we can just use the integer keys that don't require any hashing at all.

    I think this is what I'll propose at our standup today. I don't know if that proposal will meet an approval or not as it's quite time consuming process. In fact, last night I did start it, but then ran into another area that used hashes and so had to revert all the changes I did. But I think if we'll re-factor to get rid of these hashes, we'll make our life easier and pages run a bit faster.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles


    • Edited by Naomi N Thursday, July 13, 2017 12:34 PM
    Thursday, July 13, 2017 12:32 PM
  • Can you please post output of your program and also FromBase32UrlEncoded routine to get the string back?

    I think we may need to use this package as immediate solution.

    Thanks again.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Thursday, July 13, 2017 3:40 PM
  • Hi,

    I got this error trying to install 

    Severity Code Description Project File Line Suppression State
    Error Could not install package 'Base3264-UrlEncoder 1.0.2'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author. 0

    Do you know what may be a problem?


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Friday, July 14, 2017 5:38 PM
  • Hi Naomi,

    Please use this version

    Install-Package Base3264-UrlEncoder -Version 1.0.0

    This support .NET Framework 4.5


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Friday, July 14, 2017 8:41 PM
  • Hi Naomi,

    I don't have background of your project but refactoring is always a better idea.


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Friday, July 14, 2017 8:59 PM
  • Hi Naomi,

    Here is output snapshot


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Friday, July 14, 2017 9:08 PM
  • Hi Naomi,

    Your project is based on .NET framework 4.5 and Nuget package v1.0.2 require .NET framework 5 or later.

    Please install v1.0.0 as below:

    Install-Package Base3264-UrlEncoder -Version 1.0.0


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Friday, July 14, 2017 9:10 PM
  • Hi Gaurav,

    Just wondering how should I adjust my restoring routine?

    /// <summary>
            /// Decodes the string
            /// </summary>
            /// <param name="str"></param>
            /// <returns></returns>
            public static string FromBase64UrlEncoded(this string str)
            {
                var base64String = HttpUtility.UrlDecode(str);
                var encodedIdBytes = Convert.FromBase64String(base64String);
                var id = Encoding.UTF8.GetString(encodedIdBytes);
                return id;
            }


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Monday, July 17, 2017 4:42 PM
  • That's a huge undertaking...

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Monday, July 17, 2017 5:34 PM
  • Seems to be working nice, I'll do more tests, but I'm now able to add items to this category.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Monday, July 17, 2017 5:35 PM
  • Hi Naomi,

    Here is the code-snippet (with encoding/decoding):

    using System.Text;
    using System.Web;
    using MhanoHarkness;
    using static System.Console;
    
    namespace Converter
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                const string inputText = "COÑAC";
                const string inputText1 = "RUÑAC";
                const string inputText2 = "ÑAC";
                const string inputText3 = "ÑACÑAC";
                const string inputText4 = "CONAC";
                var base32UrlEncoded = inputText.ToBase32UrlEncoded();
                var base32UrlEncoded1 = inputText1.ToBase32UrlEncoded();
                var base32UrlEncoded2 = inputText2.ToBase32UrlEncoded();
                var base32UrlEncoded3 = inputText3.ToBase32UrlEncoded();
    
                var base32UrlEncoded4 = inputText4.ToBase32UrlEncoded();
                WriteLine("Encoding:");
    
                WriteLine($"string {inputText} and Encoded as {base32UrlEncoded}");
                WriteLine($"string {inputText1} and Encoded as {base32UrlEncoded1}");
                WriteLine($"string {inputText2} and Encoded as {base32UrlEncoded2}");
                WriteLine($"string {inputText3} and Encoded as {base32UrlEncoded3}");
                WriteLine($"string {inputText4} and Encoded as {base32UrlEncoded4}");
    
                WriteLine();
                WriteLine("Decoding:");
    
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded} and Decoded into {base32UrlEncoded.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded1} and Decoded into {base32UrlEncoded1.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded2} and Decoded into {base32UrlEncoded2.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded3} and Decoded into {base32UrlEncoded3.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded4} and Decoded into {base32UrlEncoded4.FromBase32UrlDecoded()}");
                Read();
            }
        }
    
        public static class MyExtension
        {
            public static string ToBase32UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Base32Url.ToBase32String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            public static string FromBase32UrlDecoded(this string base32String)
            {
                var base32Decoded = Base32Url.FromBase32String(base32String);
                var idUrlString = Encoding.UTF8.GetString(base32Decoded);
                return idUrlString;
            }
        }
    }

    Following is output of above code:

    Hope this works for you.


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    • Marked as answer by Naomi N Monday, July 17, 2017 6:15 PM
    Monday, July 17, 2017 6:02 PM
  • Hi Naomi,

    Here is complete code with two different sources (with Nuget package and using custom code):

    using System;
    using System.Text;
    using System.Web;
    using MhanoHarkness;
    using static System.Console;
    
    namespace Converter
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                const string inputText = "COÑAC";
                const string inputText1 = "RUÑAC";
                const string inputText2 = "ÑAC";
                const string inputText3 = "ÑACÑAC";
                const string inputText4 = "CONAC";
    
                EncodingDecodingUsingNugetPackage(inputText, inputText1, inputText2, inputText3, inputText4);
                CustomEncodingDecoding(inputText, inputText1, inputText2, inputText3, inputText4);
                ReadLine();
            }
    
            /// <summary>
            /// Written using Nuget package: https://www.nuget.org/packages/Base3264-UrlEncoder/
            /// </summary>
    
            private static void EncodingDecodingUsingNugetPackage(string inputText, string inputText1, string inputText2,
                string inputText3, string inputText4)
            {
                var base32UrlEncoded = inputText.ToBase32UrlEncoded();
                var base32UrlEncoded1 = inputText1.ToBase32UrlEncoded();
                var base32UrlEncoded2 = inputText2.ToBase32UrlEncoded();
                var base32UrlEncoded3 = inputText3.ToBase32UrlEncoded();
    
                var base32UrlEncoded4 = inputText4.ToBase32UrlEncoded();
                WriteLine("Encoding/Decoding using Nuget Package");
                WriteLine("Encoding:");
    
                WriteLine($"string {inputText} and Encoded as {base32UrlEncoded}");
                WriteLine($"string {inputText1} and Encoded as {base32UrlEncoded1}");
                WriteLine($"string {inputText2} and Encoded as {base32UrlEncoded2}");
                WriteLine($"string {inputText3} and Encoded as {base32UrlEncoded3}");
                WriteLine($"string {inputText4} and Encoded as {base32UrlEncoded4}");
    
                WriteLine();
                WriteLine("Decoding:");
    
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded} and Decoded into {base32UrlEncoded.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded1} and Decoded into {base32UrlEncoded1.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded2} and Decoded into {base32UrlEncoded2.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded3} and Decoded into {base32UrlEncoded3.FromBase32UrlDecoded()}");
                WriteLine(
                    $"Encoded Base32:{base32UrlEncoded4} and Decoded into {base32UrlEncoded4.FromBase32UrlDecoded()}");
               ReadLine();
            }
            /// <summary>
            /// Adapted from: https://web.archive.org/web/20060422042142/http://www.atrevido.net/blog/PermaLink.aspx?guid=debdd47c-9d15-4a2f-a796-99b0449aa8af
            /// </summary>
            private static void CustomEncodingDecoding(string inputText, string inputText1, string inputText2,
               string inputText3, string inputText4)
            {
                var base32UrlEncoded = Base32.ToBase32String(Encoding.UTF8.GetBytes(inputText));
                var base32UrlEncoded1 = Base32.ToBase32String(Encoding.UTF8.GetBytes(inputText1));
                var base32UrlEncoded2 = Base32.ToBase32String(Encoding.UTF8.GetBytes(inputText2));
                var base32UrlEncoded3 = Base32.ToBase32String(Encoding.UTF8.GetBytes(inputText3));
                var base32UrlEncoded4 = Base32.ToBase32String(Encoding.UTF8.GetBytes(inputText4));
                WriteLine("Encoding/Decoding using custom methods");
                WriteLine("Encoding:");
    
                WriteLine($"string {inputText} and Encoded as {base32UrlEncoded}");
                WriteLine($"string {inputText1} and Encoded as {base32UrlEncoded1}");
                WriteLine($"string {inputText2} and Encoded as {base32UrlEncoded2}");
                WriteLine($"string {inputText3} and Encoded as {base32UrlEncoded3}");
                WriteLine($"string {inputText4} and Encoded as {base32UrlEncoded4}");
    
                WriteLine();
                WriteLine("Decoding:");
    
                WriteLine($"Encoded Base32:{base32UrlEncoded} and Decoded into {Encoding.UTF8.GetString(Base32.FromBase32String(base32UrlEncoded))}");
                WriteLine($"Encoded Base32:{base32UrlEncoded1} and Decoded into {Encoding.UTF8.GetString(Base32.FromBase32String(base32UrlEncoded1))}");
                WriteLine($"Encoded Base32:{base32UrlEncoded2} and Decoded into {Encoding.UTF8.GetString(Base32.FromBase32String(base32UrlEncoded2))}");
                WriteLine($"Encoded Base32:{base32UrlEncoded3} and Decoded into {Encoding.UTF8.GetString(Base32.FromBase32String(base32UrlEncoded3))}");
                WriteLine($"Encoded Base32:{base32UrlEncoded4} and Decoded into {Encoding.UTF8.GetString(Base32.FromBase32String(base32UrlEncoded4))}");
                
            }
        }
     
        public sealed class Base32
        {
            // the valid chars for the encoding
            private static readonly string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP";
    
            /// <summary>
            ///     Converts an array of bytes to a Base32-k string.
            /// </summary>
            public static string ToBase32String(byte[] bytes)
            {
                var sb = new StringBuilder(); // holds the base32 chars
                byte index;
                var hi = 5;
                var currentByte = 0;
    
                while (currentByte < bytes.Length)
                {
                    // do we need to use the next byte?
                    if (hi > 8)
                    {
                        // get the last piece from the current byte, shift it to the right
                        // and increment the byte counter
                        index = (byte) (bytes[currentByte++] >> (hi - 5));
                        if (currentByte != bytes.Length)
                        {
                            // if we are not at the end, get the first piece from
                            // the next byte, clear it and shift it to the left
                            index = (byte) (((byte) (bytes[currentByte] << (16 - hi)) >> 3) | index);
                        }
    
                        hi -= 3;
                    }
                    else if (hi == 8)
                    {
                        index = (byte) (bytes[currentByte++] >> 3);
                        hi -= 3;
                    }
                    else
                    {
                        // simply get the stuff from the current byte
                        index = (byte) ((byte) (bytes[currentByte] << (8 - hi)) >> 3);
                        hi += 5;
                    }
    
                    sb.Append(ValidChars[index]);
                }
    
                return sb.ToString();
            }
    
    
            /// <summary>
            ///     Converts a Base32-k string into an array of bytes.
            /// </summary>
            /// <exception cref="System.ArgumentException">
            ///     Input string <paramref name="s">s</paramref> contains invalid Base32-k characters.
            /// </exception>
            public static byte[] FromBase32String(string str)
            {
                var numBytes = str.Length*5/8;
                byte[] bytes = new Byte[numBytes];
    
                // all UPPERCASE chars
                str = str.ToUpper();
    
                int bit_buffer;
                int currentCharIndex;
                int bits_in_buffer;
    
                if (str.Length < 3)
                {
                    bytes[0] = (byte) (ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5);
                    return bytes;
                }
    
                bit_buffer = ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5;
                bits_in_buffer = 10;
                currentCharIndex = 2;
                for (var i = 0; i < bytes.Length; i++)
                {
                    bytes[i] = (byte) bit_buffer;
                    bit_buffer >>= 8;
                    bits_in_buffer -= 8;
                    while (bits_in_buffer < 8 && currentCharIndex < str.Length)
                    {
                        bit_buffer |= ValidChars.IndexOf(str[currentCharIndex++]) << bits_in_buffer;
                        bits_in_buffer += 5;
                    }
                }
    
                return bytes;
            }
        }
    
        public static class MyExtension
        {
            public static string ToBase32UrlEncoded(this string str, bool trimBeforeHashing = false)
            {
                if (trimBeforeHashing && !string.IsNullOrEmpty(str))
                {
                    str = str.Trim();
                }
                if (string.IsNullOrEmpty(str)) return null; //return your custom message
                var idBytes = Encoding.UTF8.GetBytes(str);
                var idBase64String = Base32Url.ToBase32String(idBytes);
                var idUrlString = HttpUtility.UrlEncode(idBase64String);
                return idUrlString;
            }
    
            public static string FromBase32UrlDecoded(this string base32String)
            {
                var base32Decoded = Base32Url.FromBase32String(base32String);
                var idUrlString = Encoding.UTF8.GetString(base32Decoded);
                return idUrlString;
            }
        }
    }

    Following is the output:

    Hope this works for you.

    Happy coding!


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Monday, July 17, 2017 6:21 PM
  • Glad to know that suggested solution works for you.

    Happy coding!


    Thanks &amp;amp; Regards, Gaurav Kumar Arora http://gaurav-arora.com http://mynangal.com

    Friday, July 21, 2017 12:42 PM
  • Hi Gaurav,

    Thanks again. Do you know how to decode this string in JavaScript?

    Thanks a lot in advance.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Wednesday, March 14, 2018 8:49 PM