TextEncodings.Base64Url.Decode vs Convert.FromBase64String

时间:2017-01-16 22:19:48

标签: arrays character-encoding base64 jwt

我正在创建一个生成JWT令牌的方法。该方法的一部分从我的web.config读取一个值,该值作为用于生成用于创建JWT令牌签名的哈希的“秘密”服务。

<add key="MySecret" value="j39djak49H893hsk297353jG73gs72HJ3tdM37Vk397" />

最初我尝试使用以下命令将“secret”值转换为字节数组。

byte[] key = Convert.FromBase64String(ConfigurationManager.AppSettings["MySecret"]);

但是,达到此行时会抛出异常......

输入不是有效的Base-64字符串,因为它包含非基本64个字符,两个以上的填充字符或填充字符中的非法字符。

所以我查看了OAuth代码,因此使用另一种方法将base64字符串更改为字节数组

byte[] key = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["MySecret"]);

这种方法没有问题。对我来说,看起来他们正在做同样的事情。将Base64文本值更改为字节数组。但是,我必须遗漏一些东西。为什么Convert.FromBase64String失败并且TextEncodings.Base64Url.Decode有效?

1 个答案:

答案 0 :(得分:5)

当我将身份验证服务迁移到.NET Core时,我遇到了同样的事情。我查看了我们在之前的实现中使用的库的源代码,实际上区别在于名称本身。

TextEncodings类有两种类型的文本编码器,Base64TextEncoder和 Base64UrlEncoder 。后者稍微修改字符串,以便在网址中使用base64字符串。

我的理解是替换+和/ with - 和_ quite common。事实上,我们的握手令牌一直在做同样的事情。此外,还可以删除末尾的填充字符。这给我们留下了以下实现(this is from the source code):

public class Base64UrlTextEncoder : ITextEncoder
{
    public string Encode(byte[] data)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }

        return Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_');
    }

    public byte[] Decode(string text)
    {
        if (text == null)
        {
            throw new ArgumentNullException("text");
        }

        return Convert.FromBase64String(Pad(text.Replace('-', '+').Replace('_', '/')));
    }

    private static string Pad(string text)
    {
        var padding = 3 - ((text.Length + 3) % 4);
        if (padding == 0)
        {
            return text;
        }
        return text + new string('=', padding);
    }
}