Соответствующий выход для HttpServerUtility.UrlTokenEncode в NodeJS Javascript - PullRequest
1 голос
/ 19 марта 2020

Я смотрю на пример в do tnet, который выглядит следующим образом: https://dotnetfiddle.net/t0y8yD.

Выход для метода HttpServerUtility.UrlTokenEncode:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo1

Когда я пытаюсь выполнить то же самое в NodeJS с encodeURI, encodeURIComponent или любой другой попыткой, которую я получаю следующее:

Pn55YBwEH2S2BEM5qlNrq+LMNE8BDdHYwbWKFEHiPZo=

Как видно из вышеприведенного, «-» должно быть «+», а последняя часть символа отличается. Ха sh создается одинаково и выводит один и тот же буфер.

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

Как я могу получить два совпадения? Еще одно важное замечание: это один из вариантов использования, и я не уверен, есть ли другие символы, которые делают то же самое.

Я не уверен, что вариант do tnet неверен или версия NodeJS , Однако сравнение будет выполнено на стороне do tnet, поэтому мне нужен узел, чтобы соответствовать этому.

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Разница между этими двумя результатами вызвана использованием кодировки Base64URL в коде C# против Base64 кодирования в node.js.

Base64URL и Base64 почти идентичны, но в кодировке Base64 используются символы +, / и =, которые имеют особое значение в URL-адресах и поэтому их следует избегать. В Base64URL кодировка + заменяется на -, / с _ и = (символ заполнения на конце) либо заменяется на %20, либо просто опускается.

В вашем коде вы вычисляете HMA C -SHA256 га sh, так что вы получите 256-битный результат, который может быть закодирован в 32 байта. В Base64 / Base64URL каждый символ представляет 6 бит, поэтому вам потребуется 256/6 = 42,66 => 43 символа Base64. С 43 символами у вас будет 2 «одиноких» бита на конце, поэтому добавляется символ заполнения (=). Теперь возникает вопрос, почему HttpServerUtility.UrlTokenEncode добавляет 1 в качестве замены для отступа в конце. Я не нашел ничего в документации . Но вы должны помнить, что в любом случае это незначительно.

Чтобы получить то же самое в node.js, вы можете использовать пакет base64url или просто использовать простые операторы replace для в кодировке base64 ha sh.

С пакетом base64url:

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

console.log(hmacB64url)

В результате:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo

, как видите, в этой библиотеке просто пропущена padding char.

С replace, также заменяя padding = на 1:

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

Результат:

Pn55YBwEH2S2BEM5qlNrq-LMNE8BDdHYwbWKFEHiPZo1

Я пытался код C# с различными данными и всегда имеет '1' в конце, поэтому заменить = на 1, кажется, все в порядке, хотя он не соответствует RF C.

Другой вариант, если это вариант для вас, это изменить код C#. Используйте обычную base64 кодировку и замену строки, чтобы получить base64url вывод вместо использования HttpServerUtility.UrlTokenEncode

Возможное решение для этого описано здесь

0 голосов
/ 27 марта 2020

Я новичок здесь, поэтому я не могу комментировать (нужно 50 репутации), но я хотел бы добавить к ответу @jqs, что если строка заканчивается двумя "=", замена должна быть сделана с "2 ». Так что моя замена выглядит так:

hmacb64.replace (/// g, '_'). Replace (/ + / g, '-'). Replace (/ \ = \ = $ / m, ' 2 '). заменить (/ \ = $ / т,' 1' )

...