如何在C#中实现Base64 URL安全编码?

时间:2014-10-14 06:06:24

标签: c# encoding base64

我想在C#中实现Base64 URL安全编码。在Java中,我们有一个通用的Codec库,它为我提供了一个URL安全编码字符串。如何使用C#实现相同的目标?

byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes("StringToEncode");
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

上面的代码将其转换为Base64,但它会填充==。有没有办法实现URL安全编码?

10 个答案:

答案 0 :(得分:137)

通常只需交换字母以便在网址中使用,因此不需要%-encoding; 65个字符中只有3个有问题 - +/=。最常见的替换为-,而不是+_代替/。至于填充:只是将其删除=);您可以推断所需的填充量。在另一端:只需逆转过程:

string returnValue = System.Convert.ToBase64String(toEncodeAsBytes)
        .TrimEnd(padding).Replace('+', '-').Replace('/', '_');

使用:

static readonly char[] padding = { '=' };

并反转:

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

然而,有趣的问题是:这与“公共编解码库”使用的方法相同吗?测试肯定是合理的第一件事 - 这是一种非常常见的方法。

答案 1 :(得分:55)

您可以使用命名空间Base64UrlEncoder中的课程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!");

答案 2 :(得分:8)

根据这些答案以及一些性能改进,我们发布了一个非常易于使用的url-safe base64 implementation to NuGet源代码available on GitHub(MIT许可)。

用法就像

一样简单
var bytes = Encoding.UTF8.GetBytes("Foo");
var encoded = UrlBase64.Encode(bytes);
var decoded = UrlBase64.Decode(encoded);

答案 3 :(得分:6)

使用System.Web.HttpServerUtility.UrlTokenEncode(bytes)进行编码, System.Web.HttpServerUtility.UrlTokenDecode(bytes)要解码。

答案 4 :(得分:4)

如果您使用的是ASP.NET Core,则另一个选择是使用Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode

如果您没有使用ASP.NET Core,the WebEncoders source下可以使用Apache 2.0 License

答案 5 :(得分:1)

最简单的解决方案: (无填充)

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
  }

贷方转到:Tholle

答案 6 :(得分:0)

这是解码url-safe base64的另一种方法,用与Marc相同的方式进行编码。我只是不明白4-length%4工作的原因(确实如此)。

如下所示,只有原点的位长是6和8的公倍数,base64不会在结果上附加“=”。

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
                "=="            "="

所以我们可以反过来说,如果结果的位长度不能被8整除,那么它就被追加了:

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

答案 7 :(得分:0)

在UWP中使用Microsoft加密引擎。

uint length = 32;

IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
string base64Str = CryptographicBuffer.EncodeToBase64String(buffer)
                   // ensure url safe
                   .TrimEnd('=').Replace('+', '-').Replace('/', '_');

return base64Str;

答案 8 :(得分:0)

Karanvir Kang的答案很好,我投了赞成票。但是,它的确在字符串的末尾保留了一个奇数字符(指示已删除的填充字符的数量)。这是我的解决方法。

var bytesToEncode = System.Text.Encoding.UTF8.GetBytes("StringToEncode"); 
var bytesEncodedPadded = HttpServerUtility.UrlTokenEncode(bytesToEncode);
var objectIdBase64 = bytesEncodedPadded.Substring(0, bytesEncodedPadded.Length - 1);

答案 9 :(得分:0)

    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("_", "/");
    }

这是与 JavaScript 保持一致的方法!