我正在查看dotnet中的一个示例,它看起来如下所示:https://dotnetfiddle.net/t0y8yD。
HttpServerUtility.UrlTokenEncode方法的输出为:
Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo1当我尝试使用encodeURI、encodeURIComponent或任何其他尝试在NodeJS中完成相同的操作时,会得到以下结果:
Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo=从上面可以看出,'-‘应该是'+’,最后一个字符部分是不同的。散列是以相同的方式创建的,并输出相同的缓冲区。
var hmac = crypto.createHmac("sha256", buf);
hmac.update("9644873");
var hash = hmac.digest("base64");我怎样才能使两者匹配呢?另一个重要的注意是,这只是一个用例,我不确定是否有其他字符做同样的事情。
我不确定是dotnet变体不正确还是NodeJS版本不正确。但是,比较是在dotnet端进行的,所以我需要node来匹配它。
发布于 2020-03-20 06:56:21
两个结果的差异是由于在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个“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如你所见,这个库只是省略了填充字符。
使用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描述了一种可能的解决方案
发布于 2020-03-27 07:55:28
我是新来的,所以我不能评论(需要50个声誉),但我想在@jqs答案中加上,如果字符串以两个"=“结尾,则替换需要以"2”结束。所以我的替换看起来像这样:
Hmacb64.替换(/g,'_').replace(/+/g,'-').replace(/\=\=$/m,'2').replace(/\=$/m,'1')
https://stackoverflow.com/questions/60764586
复制相似问题