HMAC хеширование с кодировкой Base64 с использованием Javascript - PullRequest
0 голосов
/ 31 мая 2018

Я работаю с Payeezy API для обработки платежей в веб-приложении, для их API для покупки требуется HMAC с полезной нагрузкой, подписанной с использованием API-секрета.Выдержка из документов:

Создайте параметр данных, добавив параметры ниже в том же порядке, как показано.а.apikey - API-ключ разработчика.б.nonce - безопасное случайное число.с.отметка времени - отметка времени в миллисекундах.д.токен - Торговый токен.е.Полезная нагрузка - фактическое содержание тела, переданное в виде почтового запроса.Вычислите хэш HMAC SHA256 для вышеуказанного параметра данных, используя ключ ниже f.apiSecret - токен Consumer Secret для данного ключа API. Вычислите base64 хэша, который будет нашим требуемым значением заголовка авторизации.

Я нашел библиотеку с именем jshashes на NPM и попытался использовать их библиотеку дляхэшируйте мои параметры заголовка, мой код выглядит следующим образом:

const payload = {
        "merchant_ref": "1-Sale",
        "transaction_type": "purchase",
        "method": "credit_card",
        "amount": amount * 100,
        "partial_redemption": "false",
        "currency_code": "USD",
        "credit_card": {
          "type": type,
          "cardholder_name": cardholder_name,
          "card_number": card_number,
          "exp_date": exp_date,
          "cvv": cvv
        }
      }
      const data = apikey + nounce + timestamp + token + JSON.stringify(payload)
      const sha256 = new Hashes.SHA256()
      const shaData = sha256.b64_hmac(apiSecret, data)

Результат по сравнению с хэшированным значением примера выглядит следующим образом:

//mine
beWtpCGDv/iBoAUDAThGFXIge9eli/Xtl7JIBuR1bd4= 


//payeezy sample 
NmUzMTNmYWU0YjExM2UxMmM0NjllZGI1NThjY2M5MmUzMzE3NTFlZmQ1NDQxYzAzMTgwMmIwNDQ0MWVmYTdhMw== 

на основании количества символов, которое я мог быскажи, что мой процесс хеширования не правильный, но я не могу понять, где произошла ошибка.

Я видел похожие вопросы, задаваемые здесь, но никто не ответил, любая помощь приветствуется.

ДОПОЛНИТЕЛЬНО, я пытался использовать криптографическую библиотеку на Node.js:

const data = apikey + nounce + timestamp + token + JSON.stringify(payload)

  const hmac = crypto.createHmac('sha512', apiSecret)

  hmac.on('readable', () => {
    const data = hmac.read()
    if (data) {
      console.log(data.toString('base64'));
    }
  })

  hmac.write(data)
  hmac.end()

Тот же результат, только с половиной длины символа по сравнению с хэшированным значением образца

ОБНОВЛЕНИЕ: После того, как я использовал SHA512 для данных, он, наконец, вернул строку, которая выглядит так же, как длина образца, но проверкавсе еще не проходит ...

1 Ответ

0 голосов
/ 31 мая 2018

, если вы преобразуете пример base64 с этого сайта в строку

console.log(atob('NmUzMTNmYWU0YjExM2UxMmM0NjllZGI1NThjY2M5MmUzMzE3NTFlZmQ1NDQxYzAzMTgwMmIwNDQ0MWVmYTdhMw=='))

Вы получаете

6e313fae4b113e12c469edb558ccc92e331751efd5441c031802b04441efa7a3

Это шестнадцатеричная строка из 64 символов (256 бит)

Так что я думаю, что они получаютшестнадцатеричная строка HMAC и base64 кодируют это - что кажется ужасно глупым, шестнадцатеричный код безопасен для отправки как есть, зачем увеличивать его на 4 / 3rds !!

, если они просто использовали base64 HMAC, это будет всего 45 символов! !!

Вместо этого они получают шестнадцатеричную строку из 64 символов и base64 кодируют ее, чтобы получить 88 символов !!странное дизайнерское решение !!

Итак, ваш код должен делать то же самое

как

Data = Buffer.from(sha256.hex_hmac(apiSecret, data), 'utf-8').toString('base64');

, но не уверен, что в узле есть лучший способ конвертировать гексзакодированная строка в base64, но это работает

И, наконец, (на самом деле этот бит просто "соответствует" тому, как рассчитывается авторизация на странице примера, на которую ссылается OP https://developer.payeezy.com/payeezy-api/apis/post/transactions-3). Итак, этонет необходимости увеличивать полезную нагрузку без причины)

Еще один момент, который вам нужно знать, JSON полезной нагрузки должен быть в определенном формате, кажется ... 2 пробела с отступом ... опять же,это чертовски глупая трата пропускной способности .. {"key":1234} занимает 12 символов

{
  "key": 1234
}

занимает 17

Так что, в любом случае, вам нужно сделать следующее:

JSON.stringify(payload,null, 2)

Эта последняя часть головоломки должна сделать ваш код следующим образом

const data = apikey + nonce + timestamp + token + JSON.stringify(payload,null, 2)
const sha256 = new Hashes.SHA256()
const shaData = Buffer.from(sha256.hex_hmac(secret, data), 'utf-8').toString('base64');
...