Dmi*_*aev 5 c# base64 rsa openid-connect jwk
我通常想做的是验证从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"
}
Run Code Online (Sandbox Code Playgroud)
我将使用RSACryptoServiceProvider类来解码签名。要初始化它,我必须为RSAParameters提供Modulus和Exponent值。这些值从上述JWK中分别读取为n和e。根据规范,这些值是Base64urlUInt编码的值:
正或零整数值的表示形式,以值的无符号big-endian表示形式的八位字节序列的base64url编码。八位位组序列必须使用表示该值所需的最少八位位组数。零表示为BASE64URL(单个零值八位位组),即“ AA”。
因此,我的问题是如何解码这些值以将其放入RSAParameters?我尝试将它们解码为常见的Base64url字符串(Convert.FromBase64String(modulusRaw)
),但这显然不起作用并产生此错误:
输入内容不是有效的Base-64字符串,因为它包含非base 64字符,两个以上的填充字符或填充字符中的非法字符。
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);
}
Run Code Online (Sandbox Code Playgroud)
该代码可能已经存在于框架中的某个位置,但是我不知道。