java - Java 中生成的 HmacSha256 签名与 Go 中不同

标签 java go hmac

我正在将代码从 Go 转换为 Java。要转换的源位于 https://github.com/h2non/imaginary#url-signature这是我当前转换为 Java 的代码。

问题是我遗漏了一些东西,因为在 Java 中生成的签名与在 Go 中生成的签名不同。

预期结果(如 Go 中的源代码所示):

ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo

Java 中的实际结果:

x2clz4ynSxcFPNc6h3W832vyrIQ=

我的 Java 代码:

@Test
public void testSomeString() throws Exception {
    String signKey = "4f46feebafc4b5e988f131c4ff8b5997";
    String urlPath = "/resize";
    String urlQuery = "file=image.jpg&height=200&type=jpeg&width=300";

    byte[] signKeyAsBytes = signKey.getBytes("UTF-8");
    SecretKey SHA256_KEY = new SecretKeySpec(signKeyAsBytes, "HmacSHA256");

    byte[] hashAsBytes=Hashing.hmacSha1(SHA256_KEY)
            .newHasher()
            .putString(urlPath, UTF_8)
            .putString(urlQuery, UTF_8)
            .hash().asBytes();
    String hash = Base64.getUrlEncoder().encodeToString(hashAsBytes);

    //correct value in GoLang is: "ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo"
    Assert.assertEquals("ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo", hash);

    /*
    Junit test fails with:
    Expected :ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo
    Actual   :x2clz4ynSxcFPNc6h3W832vyrIQ=
    */
}

这是 Go 中的原始内容:

package main

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

func main() {
    fmt.Println("Hello, playground")
    signKey := "4f46feebafc4b5e988f131c4ff8b5997"
    urlPath := "/resize"
    urlQuery := "file=image.jpg&height=200&type=jpeg&width=300"

    h := hmac.New(sha256.New, []byte(signKey))
    h.Write([]byte(urlPath))
    h.Write([]byte(urlQuery))
    buf := h.Sum(nil)

    fmt.Println("sign=" + base64.RawURLEncoding.EncodeToString(buf))
}

最佳答案

我不知道你在 Java 中使用什么 Hashing 类,因为它不是标准的,但是如果我使用标准类 javax.crypto.Mac使用该 key 和数据执行 HmacSHA256(不是 HmacSHA1)——并使用 JSON 提升的 Base64 的“未填充 URLsafe”变体进行编码,而不是 Java 默认的传统变体——我确实得到 ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo.

但是,在没有定界的情况下对路径和查询进行签名是非常糟糕的做法——这可能允许将签名“移动”到不同的数据。使用字符但只有十六进制数字字符的 key 也很奇怪,但并不直接危险。如果没有进行广泛的调查,我不会将这样设计的方案用于任何重要的事情。

关于java - Java 中生成的 HmacSha256 签名与 Go 中不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51259453/

相关文章:

java - Nexus 存储库管理器找不到 pom 文件

java - 删除选定的 JTable 元素

java - JTable 不会更新 fireXXXXX() 事件

go - 初始化嵌套的匿名结构

go - 为 io.Reader 添加前缀

rest - 在 RESTful API 的上下文中,使用 RSA 签署 JWT 比 SHA 有什么优势?

java - 是什么导致了 java.lang.ArrayIndexOutOfBoundsException 以及如何防止它?

go - 为什么发送数据到 no buffered chan 会阻塞 go routine

node.js - 如何使用 HMACSHA256 Node js 验证 Xero Webhook 有效负载

c# - HMAC 验证失败,代码为 403