Ruby против Go / sha256 несоответствия строк в кодировке hmac base64 - PullRequest
3 голосов
/ 12 июня 2019

играя с воображаемым, я пытаюсь создать клиент ruby.

В целях безопасности мне нужно подписать URL

Вот пример с предоставленным ходом:

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "fmt"
)

func main() {
  signKey := "ea79b7fd-287b-4ffe-b941-bf983181783f"
  urlPath := "/resize"
  url := "https%3A%2F%2Fxyz"
  urlQuery := "nocrop=true&type=jpeg&url=" + url + "&width=500"

  h := hmac.New(sha256.New, []byte(signKey))
  h.Write([]byte(urlPath))
  h.Write([]byte(urlQuery))
  buf := h.Sum(nil)
    fmt.Println(base64.RawURLEncoding.EncodeToString(buf)
}

Преобразовано в рубин, это дает нам:

require 'openssl'
require 'base64'

signKey = "ea79b7fd-287b-4ffe-b941-bf983181783f"
urlPath = "/resize"
url = "https%3A%2F%2Fxyz"
urlQuery = "nocrop=true&type=jpeg&url=" + url + "&width=500"

digest = OpenSSL::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, signKey, "#{urlPath}#{urlQuery}")
pp Base64.strict_encode64(hmac)

Мы почти у цели, но есть небольшая проблема, не знаю, связано ли это с openssl или base64, но, например, когда я получаю это с go:

wClkWcUvI9ILs7noAr_HtnKpRCeeWBXE1Ne2C99sAco

Я получаю следующее с версией ruby:

wClkWcUvI9ILs7noAr/HtnKpRCeeWBXE1Ne2C99sAco=

С ruby, что бы ни делалось, в итоге получается =

Хотя в go используется подчеркивание, в ruby ​​используются обратные слэши (это последнее утверждение может быть результатом полной неосведомленности о конкретных частях ruby, но давайте просто подробно рассмотрим проблему)

Что нужно сделать, чтобы получить одинаковый вывод в обеих версиях? Почему мы получаем близкий, но не точный результат между этими языками?

Большое спасибо за ответ

1 Ответ

7 голосов
/ 12 июня 2019

Код Go использует безопасный для URL вариант кодировки base64, где ваш код Ruby использует обычную версию. Безопасная версия URL использует - и _ вместо + и /, поэтому она безопасна для использования в URL. Версия Ruby также включает отступы (= в конце).

Вы можете использовать безопасную версию URL в Ruby , и вы также можете указать отсутствие заполнения, чтобы получить тот же результат, что и Go:

Base64.urlsafe_encode64(hmac, false)
...