用于对修改后的base64 URL进行解码/编码的代码


113

我想对数据进行base64编码,以将其放入URL,然后在HttpHandler中对其进行解码。

我发现Base64编码允许使用'/'字符,这会弄乱我的UriTemplate匹配。然后我发现维基百科有一个“ URL的修改后的Base64”概念:

存在URL变体的经过修改的Base64,其中将不使用填充'=',并且标准Base64的'+'和'/'字符分别被替换为'-'和'_',以便使用URL编码器/解码器不再是必需的,并且对编码值的长度没有影响,通常保留相同的编码形式以供关系数据库,Web表单和对象标识符使用。

使用.NET,我希望将当前代码从基本的base64编码和解码修改为使用“ URL的修改后的base64”方法。有人这样做吗?

要解码,我知道它始于以下内容:

string base64EncodedText = base64UrlEncodedText.Replace('-', '+').Replace('_', '/');

// Append '=' char(s) if necessary - how best to do this?

// My normal base64 decoding now uses encodedText

但是,我可能需要在末尾添加一个或两个'='字符,看起来有点复杂。

我的编码逻辑应该更简单一些:

// Perform normal base64 encoding
byte[] encodedBytes = Encoding.UTF8.GetBytes(unencodedText);
string base64EncodedText = Convert.ToBase64String(encodedBytes);

// Apply URL variant
string base64UrlEncodedText = base64EncodedText.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');

我已经看到URL堆栈溢出条目的Base64引导程序,但是它的长度是已知的,因此它们可以对最后所需的等号进行硬编码。


@柯克:用经过测试的数学来调整我的答案。
AnthonyWJones

Answers:


69

这应该正确地填补它:-

 base64 = base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=');

11
ah,你打败我了。我将删除我的帖子,因为它看起来几乎就像我复制了您的内容一样:)
AaronLS,2009年

3
这不等于三个'='字符吗?看来其中只有0、1或2。
Kirk Liemohn

1
@Kirk:如果添加3个字符,则base64字符串已损坏。我想验证字符串是个好主意,它应该只包含期望的字符和Length%4!=
3。– AnthonyWJones

嗯 在尝试这一点时,它并没有成功。仍在寻找答案。等号的数目只是没有正确地平移。
Kirk Liemohn

2
@AnthonyWJones'它应该只包含期望的字符和Length%4!= 1 ',对吗?
blueling

173

还要使用处理URL安全的Base64编码和解码的UrlTokenEncode和UrlTokenDecode方法检查类HttpServerUtility

注意1:结果不是有效的Base64字符串。URL的一些不安全字符已被替换。

注2:结果与RFC4648中的base64url算法不同。

///<summary>
/// Base 64 Encoding with URL and Filename Safe Alphabet using UTF-8 character set.
///</summary>
///<param name="str">The origianl string</param>
///<returns>The Base64 encoded string</returns>
public static string Base64ForUrlEncode(string str)
{
    byte[] encbuff = Encoding.UTF8.GetBytes(str);
    return HttpServerUtility.UrlTokenEncode(encbuff);
}
///<summary>
/// Decode Base64 encoded string with URL and Filename Safe Alphabet using UTF-8.
///</summary>
///<param name="str">Base64 code</param>
///<returns>The decoded string.</returns>
public static string Base64ForUrlDecode(string str)
{
    byte[] decbuff = HttpServerUtility.UrlTokenDecode(str);
    return Encoding.UTF8.GetString(decbuff);
}

谢谢你的提示。下次我会尝试的!
Kirk Liemohn

12
您的秘诀是光荣地结束了长达数小时的搜索,寻找了答案。谢谢
Praesagus

这不是对每个/ +和=使用%编码吗?这没有其他答案那么有效
JoelFan 2012年

不,它用数字替换最后用于填充的等号,并用减号和下划线替换加号和斜杠。
Fredrik Haglund 2012年

15
请注意,UrlTokenEncode严格意义上不是base64url,因为它会根据替换的等号数量将'='填充替换为'0','1'或'2'。
ladenedge 2012年

28

没有足够的注释要注释,但是如果有帮助,则在将Base 64编码为URL中的参数时,Sushil在提供的链接(JSON Web Signature ietf草稿)中找到的代码段适用。

下面是那些懒惰的代码段:

    static string Base64UrlEncode(byte[] arg)
    {
        string s = Convert.ToBase64String(arg); // Regular base64 encoder
        s = s.Split('=')[0]; // Remove any trailing '='s
        s = s.Replace('+', '-'); // 62nd char of encoding
        s = s.Replace('/', '_'); // 63rd char of encoding
        return s;
    }

    static byte[] Base64UrlDecode(string arg)
    {
        string s = arg;
        s = s.Replace('-', '+'); // 62nd char of encoding
        s = s.Replace('_', '/'); // 63rd char of encoding
        switch (s.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 2: s += "=="; break; // Two pad chars
            case 3: s += "="; break; // One pad char
            default: throw new System.Exception(
              "Illegal base64url string!");
        }
        return Convert.FromBase64String(s); // Standard base64 decoder
    }

这与不使用System.Web的Xamarin兼容
Reza Mortazavi

正是我想要的!对于Xamarin而言,确实是一个不错的选择,而无需引入库。
Sleeping_Giant

19

我在这里时是在寻找要对base64url编码进行编码/解码的代码,这与问题中所述的base64几乎没有什么不同。

在此文档中找到了c#代码段。JSON Web签名ietf草案


2
这是在GMail API v1(Message.Raw)中解析消息时唯一对我
有用的

5

与接受的答案相比,这是使用C#从根本上解码 base64编码的url的方式:

解码:

string codedValue = "base64encodedUrlHere";

string decoded;
byte[] buffer =  Convert.FromBase64String(codedValue);
decoded = Encoding.UTF8.GetString(buffer);

也许,如果您提供更多详细信息并与接受的答案进行比较,您可能会感到不满-谢谢
Mauricio Gracia Gutierrez
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.