解码 Base64urlUInt 编码的值
Posted
技术标签:
【中文标题】解码 Base64urlUInt 编码的值【英文标题】:Decoding Base64urlUInt-encoded value 【发布时间】:2016-03-20 23:35:39 【问题描述】:我通常尝试做的是验证从 OpenID Connect 提供商(例如 Google)获得的 id_token 值。令牌使用 RSA 算法签名,公钥从 Discovery 文档(jwks_uri 参数)中读取。例如,Google 密钥以 JWK 格式提供 here:
kty: "RSA",
alg: "RS256",
use: "sig",
kid: "38d516cbe31d4345819b786d4d227e3075df02fc",
n: "4fQxF6dFabDqsz9a9-XgVhDaadTBO4yBZkpUyUKrS98ZtpKIQRMLoph3bK9Cua828wwDZ9HHhUxOcbcUiNDUbubtsDz1AirWpCVRRauxRdRInejbGSqHMbg1bxWYfquKKQwF7WnrrSbgdInUZPv5xcHEjQ6q_Kbcsts1Nnc__8YRdmIGrtdTAcm1Ga8LfwroeyiF-2xn0mtWDnU7rblQI4qaXCwM8Zm-lUrpSUkO6E1RTJ1L0vRx8ieyLLOBzJNwxpIBNFolMK8-DYXDSX0SdR7gslInKCn8Ihd9mpI2QBuT-KFUi88t8TW4LsoWHAwlgXCRGP5cYB4r30NQ1wMiuQ",
e: "AQAB"
我将使用RSACryptoServiceProvider 类来解码签名。要初始化它,我必须为RSAParameters 提供模数和指数值。这些值从上述 JWK 中读取为对应的 n 和 e。根据specification,这些值是Base64urlUInt编码的值:
将正整数或零整数值表示为 值的无符号大端表示的 base64url 编码 作为八位字节序列。八位字节序列必须使用最小的 表示值所需的八位字节数。零表示 作为 BASE64URL(单个零值八位字节),即“AA”。
那么,我的问题是如何解码这些值以将它们放入 RSAParameters?我尝试将它们解码为常见的 Base64url 字符串 (Convert.FromBase64String(modulusRaw)
),但这显然不起作用并生成此错误:
输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或非法字符 在填充字符之间。
【问题讨论】:
HttpServerUtility.UrlTokenDecode
不适用于您的情况吗?
@Baldrick 谢谢!但是,这在这种情况下不起作用。
【参考方案1】:
RFC 7515 定义 base64url 编码如下:
使用 URL 和文件名安全字符集的 Base64 编码 在RFC 4648 的第 5 节中定义,所有尾随 '=' 省略的字符(如第 3.2 节所允许的)并且没有 包含任何换行符、空格或其他额外的 人物。注意空八位字节的base64url编码 序列是空字符串。 (见附录 C 的注释 实现 base64url 编码而不进行填充。)
RFC 4648 将“使用 URL 和文件名安全字母的 Base 64 编码”定义为常规 base64,但是:
可以省略填充(就像这里一样) 使用-
代替+
和_
代替/
所以要使用普通的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);
这段代码可能已经存在于框架的某个地方,但我不知道。
【讨论】:
【参考方案2】:谁从 Java 来到这里:java.util.Base64
中有两种方法:
getDecoder()
getUrlDecoder()
正如您可能假设的那样:使用第二个已经为您完成了所有字符替换。
【讨论】:
以上是关于解码 Base64urlUInt 编码的值的主要内容,如果未能解决你的问题,请参考以下文章