Ruby vs. Go / sha256 hmac base64 编码字符串不匹配

5

我正在尝试创建一个Ruby客户端,与虚构的内容互动。

出于安全考虑,我需要对URL进行签名。

以下是提供的Go示例:

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)
}

转换为 Ruby 代码,得到的结果如下:
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个回答

10

Go代码使用URL安全变体的base64编码,而您的Ruby代码使用正常版本。 URL安全版本使用 - _ 代替 + / ,因此可以安全地在URL中使用。 Ruby版本还包括填充(即末尾的 = )。

您可以在Ruby中使用URL安全版本,并且还可以指定不进行填充以获得与Go相同的结果:

Base64.urlsafe_encode64(hmac, false)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接