类似 Base64 的字符串转换为更小的字符集

本文关键字:字符集 转换 Base64 字符串 类似 | 更新日期: 2023-09-27 18:32:29

我有一系列加密字符串,我在C#/ASP.Net Web应用程序中用作ID。我需要在 id 属性中使用这些字符,但是,字符串包含非法字符(有效字符仅为 '[A-Za-z0-9-_:.]`).我需要一个双向转换,将我的加密字符串映射到这个小集合。类似于 Base64,但更小。

我有什么选择?是否有标准的算法,或者我必须自己发明它足够奇怪?

溶液:如果有人需要这个,这就是我最终所做的。替换无效字符,并删除填充 = 字符。然后撤消此操作以还原。

    private static string MakeReferenceJavascriptCompatible(string reference)
    {
        return reference.Replace("+", "_")
                        .Replace("/", "-")
                        .Replace("=", "");
    }
    private static string UndoMakeReferenceJavascriptCompatible(string reference)
    {
        int padding = 4 - (reference.Length % 4);
        return reference.Replace("-", "/")
                        .Replace("_", "+")
                        .PadRight(reference.Length + padding, '=');
    }

类似 Base64 的字符串转换为更小的字符集

如果您有 A-Z (26)、a-z (26)、0-9 (10) 和 '_'、':' 和 '."(3)那么你有65个字符可用,就像Base64一样。(它需要 65 而不是 64,因为最后使用 = 作为填充。我不清楚你是否包括-,这会给你 66...:)可用的角色非常丰富

听起来您只需要将"正常"形式转换为略有不同的字母表即可。您可以通过找到一个灵活的 base64 实现来指定要使用的值,或者只需调用 string.Replace 来执行此操作:

var base64 = Convert.ToBase64String(input)
                    .Replace('+', '_')
                    .Replace('/', ':')
                    .Replace('=', '.');

反转替换以从"修改后的"base64 返回到"正常"base64,它将对Convert.FromBase64String有效。

"更小"?在问题中,您指出有 66 个有效字符:

  • [A-Z] : 26
  • [a-z] : 26
  • [0-9] : 10
  • [-_:.] : 4

给 Base64 一个机会,也许用其他字符替换"非法字符"(+、/、=)。

您已经有 65 个有效字符可供使用。因此,您可以将base64编码与String.Replace一起使用。但是,如果要使用不区分大小写的编码(例如,在Windows中使用文件名),则可以使用base36

编码

您可以使用内置的System.Web.HttpServerUtility来执行此操作。

要将值转换为编码值(对 URL 和 JavaScript 使用安全):

string result = value;
if (!string.IsNullOrEmpty(value))
{
  var bytes = System.Text.Encoding.UTF8.GetBytes(value);
  result = HttpServerUtility.UrlTokenEncode(bytes);
}
return result;

要将编码值转换回原始值,请执行以下操作:

// If a non-base64 string is passed as value, the result will
// be same as the passed value
string result = value;
if (!string.IsNullOrEmpty(value))
{
  var bytes = HttpServerUtility.UrlTokenDecode(value);
  if (bytes != null) {
    result = System.Text.Encoding.UTF8.GetString(bytes);
  }
}
return result;