Node JS Javascript 中 HttpServerUtility.UrlTokenEncode 的匹配输出
Matching ouput for HttpServerUtility.UrlTokenEncode in NodeJS Javascript
我正在查看 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 端完成,所以我需要节点来匹配它。
两个结果的差异是由于node.js中使用了Base64URL encoding in the C# code vs. Base64编码造成的。
Base64URL
和Base64
几乎相同,但是Base64
编码使用字符+
、/
和=
,它们有URL 中的特殊含义,因此必须避免。在 Base64URL
编码中,+
被替换为 -
,/
被替换为 _
,=
(末尾的填充字符)被替换为%20
或干脆省略。
在您的代码中,您正在计算 HMAC-SHA256 哈希值,因此您会得到一个 256 位的结果,可以用 32 个字节进行编码。在 Base64
/Base64URL
中,每个字符代表 6 位,因此您需要 256/6 = 42,66 => 43 个 Base64 字符。对于 43 个字符,您将在末尾有 2 'lonesome' 位,因此添加了一个填充字符 (=
)。
现在的问题是为什么 HttpServerUtility.UrlTokenEncode
添加一个 1
作为末尾填充字符的替代品。我在 documentation 中没有找到任何内容。但是你要记住,反正都是微不足道的。
要在 node.js 中获得相同的结果,您可以使用包 base64url,或者只在 base64 编码哈希上使用简单的 replace
语句。
使用 base64url 包:
const base64url = require('base64url');
var hmacB64 = "Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo="
var hmacB64url = base64url.fromBase64(hmacb64)
console.log(hmacB64url)
结果是:
Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo
如您所见,这个库只是省略了填充字符。
With 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
描述了一个可能的解决方案 here
我是新来的,所以我不能发表评论(需要 50 声望),但我想在@jqs 的回答中补充一点,如果字符串以两个“=”结尾,则替换需要用“2”。所以我的替换看起来像:
hmacb64.replace(///g,'_').replace(/+/g,'-').replace(/\=\=$/m,'2').replace (/\=$/m,'1')
我正在查看 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 端完成,所以我需要节点来匹配它。
两个结果的差异是由于node.js中使用了Base64URL encoding in the C# code vs. Base64编码造成的。
Base64URL
和Base64
几乎相同,但是Base64
编码使用字符+
、/
和=
,它们有URL 中的特殊含义,因此必须避免。在 Base64URL
编码中,+
被替换为 -
,/
被替换为 _
,=
(末尾的填充字符)被替换为%20
或干脆省略。
在您的代码中,您正在计算 HMAC-SHA256 哈希值,因此您会得到一个 256 位的结果,可以用 32 个字节进行编码。在 Base64
/Base64URL
中,每个字符代表 6 位,因此您需要 256/6 = 42,66 => 43 个 Base64 字符。对于 43 个字符,您将在末尾有 2 'lonesome' 位,因此添加了一个填充字符 (=
)。
现在的问题是为什么 HttpServerUtility.UrlTokenEncode
添加一个 1
作为末尾填充字符的替代品。我在 documentation 中没有找到任何内容。但是你要记住,反正都是微不足道的。
要在 node.js 中获得相同的结果,您可以使用包 base64url,或者只在 base64 编码哈希上使用简单的 replace
语句。
使用 base64url 包:
const base64url = require('base64url');
var hmacB64 = "Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo="
var hmacB64url = base64url.fromBase64(hmacb64)
console.log(hmacB64url)
结果是:
Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo
如您所见,这个库只是省略了填充字符。
With 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
描述了一个可能的解决方案 here
我是新来的,所以我不能发表评论(需要 50 声望),但我想在@jqs 的回答中补充一点,如果字符串以两个“=”结尾,则替换需要用“2”。所以我的替换看起来像:
hmacb64.replace(///g,'_').replace(/+/g,'-').replace(/\=\=$/m,'2').replace (/\=$/m,'1')