我通常想做的是验证从OpenID Connect提供程序(例如Google)获得的id_token值。令牌使用RSA算法签名,并且从发现文档(jwks_uri参数)读取公共密钥。例如,此处以JWK格式提供Google密钥:
{ kty: "RSA", alg: "RS256", use: "sig", kid: "38d516cbe31d4345819b786d4d227e3075df02fc", n: "4fQxF6dFabDqsz9a9-XgVhDaadTBO4yBZkpUyUKrS98ZtpKIQRMLoph3bK9Cua828wwDZ9HHhUxOcbcUiNDUbubtsDz1AirWpCVRRauxRdRInejbGSqHMbg1bxWYfquKKQwF7WnrrSbgdInUZPv5xcHEjQ6q_Kbcsts1Nnc__8YRdmIGrtdTAcm1Ga8LfwroeyiF-2xn0mtWDnU7rblQI4qaXCwM8Zm-lUrpSUkO6E1RTJ1L0vRx8ieyLLOBzJNwxpIBNFolMK8-DYXDSX0SdR7gslInKCn8Ihd9mpI2QBuT-KFUi88t8TW4LsoWHAwlgXCRGP5cYB4r30NQ1wMiuQ", e: "AQAB" }
我将使用RSACryptoServiceProvider类来解码签名。要初始化它,我必须为RSAParameters提供Modulus和Exponent值。这些值从上述JWK中分别读取为n和e。根据规范,这些值是Base64urlUInt编码的值:
正或零整数值的表示形式,以值的无符号big-endian表示形式的八位字节序列的base64url编码。八位位组序列必须使用表示该值所需的最少八位位组数。零表示为BASE64URL(单个零值八位位组),即“ AA”。
因此,我的问题是如何解码这些值以将其放入RSAParameters?我尝试将它们解码为常见的Base64url字符串(Convert.FromBase64String(modulusRaw)
),但这显然不起作用并产生此错误:
输入内容不是有效的Base-64字符串,因为它包含非base 64字符,两个以上的填充字符或填充字符中的非法字符。
Jon Skeet.. 5
RFC 7515定义了base64url编码,如下所示:
使用RFC 4648第5节中定义的URL和文件名安全字符集进行的Base64编码,省略了所有结尾的'='字符(如第3.2节所允许),并且不包含任何换行符,空格或其他附加字符。请注意,空字节序列的base64url编码是空字符串。(有关不进行填充而实现base64url编码的说明,请参阅附录C。)
RFC 4648将“使用URL和文件名安全字母的Base 64编码”定义为常规base64,但是:
可以省略填充(如此处所示)
使用-
代替+
和_
代替/
因此,要使用normal Convert.FromBase64String
,您只需要逆转该过程即可:
static byte[] FromBase64Url(string base64Url) { string padded = base64Url.Length % 4 == 0 ? base64Url : base64Url + "====".Substring(base64Url.Length % 4); string base64 = padded.Replace("_", "/") .Replace("-", "+"); return Convert.FromBase64String(base64); }
该代码可能已经存在于框架中的某个位置,但是我不知道。
RFC 7515定义了base64url编码,如下所示:
使用RFC 4648第5节中定义的URL和文件名安全字符集进行的Base64编码,省略了所有结尾的'='字符(如第3.2节所允许),并且不包含任何换行符,空格或其他附加字符。请注意,空字节序列的base64url编码是空字符串。(有关不进行填充而实现base64url编码的说明,请参阅附录C。)
RFC 4648将“使用URL和文件名安全字母的Base 64编码”定义为常规base64,但是:
可以省略填充(如此处所示)
使用-
代替+
和_
代替/
因此,要使用normal Convert.FromBase64String
,您只需要逆转该过程即可:
static byte[] FromBase64Url(string base64Url) { string padded = base64Url.Length % 4 == 0 ? base64Url : base64Url + "====".Substring(base64Url.Length % 4); string base64 = padded.Replace("_", "/") .Replace("-", "+"); return Convert.FromBase64String(base64); }
该代码可能已经存在于框架中的某个位置,但是我不知道。