NodeJS Javascript 中 HttpServerUtility.UrlTokenEncode 的匹配输出

问题描述 投票:0回答:2

我正在看 dotnet 中的一个示例,如下所示:https://dotnetfiddle.net/t0y8yD

HttpServerUtility.UrlTokenEncode
方法的输出是:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo1

当我尝试在 NodeJS 中使用

encodeURI
encodeURIComponent
或任何其他尝试完成相同的操作时,我得到以下信息:

Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo=

从上面可以看出,“-”应该是“+”,并且最后一个字符部分不同。创建的哈希值相同并输出相同的缓冲区。

  var hmac = crypto.createHmac("sha256", buf);
  hmac.update("9644873");
  var hash = hmac.digest("base64");

如何使两者匹配?另一个重要的注意事项是,这是一个用例,我不确定是否有其他字符执行相同的操作。

我不确定是 dotnet 变体不正确还是 NodeJS 版本不正确。但是,比较将在 dotnet 端完成,因此我需要节点来匹配它。

javascript asp.net node.js base64 urlencode
2个回答
3
投票

两个结果的差异是由于 C# 代码中使用 Base64URL 编码与 Node.js 中使用 Base64 编码造成的。

Base64URL
Base64
几乎相同,但
Base64
编码使用字符
+
/
=
,这些字符在URL中具有特殊含义,因此必须避免使用。在
Base64URL
编码中,
+
替换为
-
/
替换为
_
,而
=
(末尾的填充字符)则替换为
%20
或直接省略。

在您的代码中,您正在计算 HMAC-SHA256 哈希值,因此您会得到 256 位结果,可以用 32 字节进行编码。在

Base64
/
Base64URL
中,每个字符代表 6 位,因此您需要 256/6 = 42,66 => 43 个 Base64 字符。对于 43 个字符,末尾会有 2 个“孤独”位,因此添加了一个填充字符 (
=
)。 现在的问题是为什么
HttpServerUtility.UrlTokenEncode
添加一个
1
来代替末尾的填充字符。我在文档中没有找到任何内容。但你应该记住,无论如何这都是微不足道的。

要在node.js中获得相同的效果,您可以使用包base64url,或者仅在base64编码的哈希上使用简单的

replace
语句。

带有base64url包:

const base64url = require('base64url');
var hmacB64 = "Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo="
var hmacB64url = base64url.fromBase64(hmacb64)

console.log(hmacB64url)

结果是:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo

如您所见,该库只是省略了填充字符。

使用

replace
,同时将填充
=
替换为
1

var hmacB64 = "Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo="
console.log(hmacb64.replace(/\//g,'_').replace(/\+/g,'-').replace(/\=+$/m,'1'))

结果是:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo1

我尝试了使用不同数据的 C# 代码,最后总是得到“1”,因此用

=
替换
1
似乎没问题,尽管它似乎不符合 RFC。

如果您可以选择,另一种选择是更改 C# 代码。使用普通

base64
编码加上字符串替换来获取
base64url
输出,而不是使用
HttpServerUtility.UrlTokenEncode

这里描述了一个可能的解决方案


1
投票
我是新来的,所以无法发表评论(需要 50 声望),但我想在 @jqs 答案中添加一点,如果字符串以两个“=”结尾,则需要用“2”进行替换。所以我的替换看起来像:

hmacb64.replace(/\//g,'_').replace(/\+/g,'-').replace(/\=\=$/m,'2').replace(/\=$/m,'1')
    
© www.soinside.com 2019 - 2024. All rights reserved.