首页 > 代码库 > Base64编解码中的坑

Base64编解码中的坑

本文主要针对.net 中的System.Web.ServerUtility.UrlTokenEncode()/UrlTokenDecode()进行解释

在巨硬的源码文档中找到4.6.2的释义:

https://referencesource.microsoft.com/#System.Web/Util/HttpEncoder.cs,0e3cb83cf51ca334

 

通过分析可知

1:最后一个‘=‘被编码成一个由源字符串与其长度差的加密字符.

2:‘+‘ to ‘-‘,‘/‘ to ‘_‘

相信看到这里读者都已经发现问题所在了,如果在不知道源字符串长度与最后一个补位符存在与否的情况下想解码获得源字符串是不大可能的。

那怎么办呢?自己手动写一个呗...

编码:

        /// <summary>
        /// 字节码转为base64
        /// 替换System.Web.ServerUtility.UrlTokenEncode方法
        ///  "/" to "_a","+" to "_b", and "=" to "_c"
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        internal static string UrlTokenEncode(byte[] input)
        {
            if (input == null)
                throw new ArgumentNullException("input");
            if (input.Length < 1)
                return String.Empty;

            string base64Str = null;
            StringBuilder newbase64Str = new StringBuilder();
            ////////////////////////////////////////////////////////
            // Step 1: Do a Base64 encoding
            base64Str = Convert.ToBase64String(input);

            ////////////////////////////////////////////////////////
            // Step 2: Copy in the other chars. Transform the "/" to "_a" ,"+" to "_b", and "=" to "_c"
            foreach(var i in base64Str)
            {
                switch (i)
                {
                    case ‘/‘:
                        newbase64Str.Append( "_a");
                        break;
                    case ‘+‘:
                        newbase64Str.Append( "_b");
                        break;
                    case ‘=‘:
                        newbase64Str.Append( "_c");
                        break;

                    default:
                        newbase64Str.Append(i);
                        break;
                }
            }
            return newbase64Str.ToString();
        }

解码:

        /// <summary>
        /// base64解码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        internal static byte[] UrlTokenDecode(string input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            string newInput = input.Replace("_a", "/").Replace("_b", "+").Replace("_c", "=");
            int len = newInput.Length;
            if (len < 1)
                return new byte[0];

            // Do the actual conversion
            return Convert.FromBase64String(newInput);
        }

不要问我为什么不把核心的编解码代码自己实现,因为懒。ok?

Base64编解码中的坑