c# 和 java - hmacsha256 哈希之间的区别

标签 c# java encryption hmac sha256

我在 Java 中有以下代码:

byte[] secretKey = secretAccessKey.getBytes("UTF-8");
SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] bytes = data.getBytes("UTF-8");
byte[] rawHmac = mac.doFinal(bytes);
String result = javax.xml.bind.DatatypeConverter.printBase64Binary(rawHmac);

以及以下 C# 代码:

UTF8Encoding enc = new UTF8Encoding();
byte[] secretKey = enc.GetBytes(secretAccessKey);
HMACSHA256 hmac = new HMACSHA256(secretKey);
hmac.Initialize();
byte[] bytes = enc.GetBytes(data);
byte[] rawHmac = hmac.ComputeHash(bytes);
string result = Convert.ToBase64String(rawHmac);

字节数组“secretKey”和“bytes”是等价的,但是字节数组“rawHmac”不同,字符串“result”也不同。谁能看出原因?

最佳答案

不要这样做:

byte[] bytes = data.getBytes();

这将使用平台默认编码将字符串转换为字节数组。这可能因平台而异,而您想要可重复的东西。我建议使用 UTF-8:

byte[] bytes = data.getBytes("UTF-8");

(当然,对 key 执行相同的操作。)

然后您应该在 C# 中使用相同的编码 - 不是 ASCII,除非您真的不想处理非 ASCII 字符。

byte[] bytes = Encoding.UTF8.GetBytes(data);

也不清楚您之后如何比较结果 - 不要忘记 byte 在 Java 中已签名,但在 C# 中未签名。出于比较目的,将哈希值转换为十六进制或 base64 可能是最简单的。

编辑:我强烈怀疑最后一部分是问题所在 - 比较结果。

这里有两个简短但完整的程序(使用 Java 中的 iharder.net base64 转换器)产生相同的 base64 输出:

Java:

import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class Test {
    public static void main (String[] args) throws Exception {
        String secretAccessKey = "mykey";
        String data = "my data";
        byte[] secretKey = secretAccessKey.getBytes();
        SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        byte[] bytes = data.getBytes();
        byte[] rawHmac = mac.doFinal(bytes);
        System.out.println(Base64.encodeBytes(rawHmac));
    }
}

C#:

using System;
using System.Security.Cryptography;
using System.Text;

class Test
{
    static void Main()
    {
        String secretAccessKey = "mykey";
        String data = "my data";
        byte[] secretKey = Encoding.UTF8.GetBytes(secretAccessKey);
        HMACSHA256 hmac = new HMACSHA256(secretKey);
        hmac.Initialize();
        byte[] bytes = Encoding.UTF8.GetBytes(data);
        byte[] rawHmac = hmac.ComputeHash(bytes);
        Console.WriteLine(Convert.ToBase64String(rawHmac));
    }
}

两者的输出:

ivEyFpkagEoghGnTw/LmfhDOsiNbcnEON50mFGzW9/w=

关于c# 和 java - hmacsha256 哈希之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13237456/

相关文章:

c# - 在模块窗口中,我可以看到加载的 dll 以相同的路径出现两次

c# - C# 中的 Switch case - 需要一个常量值

java - 使用 struts2 的 java web 应用程序 :Success. 但是

java - 在java中将KMS CipherText blob解密为纯文本

javascript - 如何让 window.crypto.subtle 输出与 'crypto' js 库相同的签名?

android - 为我的 android 应用程序提供一个用 sqlcipher 加密的数据库不起作用,无法打开它

c# - 非管理员的 HttpListenerException "access denied"

java - @JSonIgnore 注释的等效代码设置是什么?

java - 如何从文件中读取整数(X 和 Y 点)并在 Java 中绘制最小回归线?错误

c# - Google Analytics API BatchRequest - 过滤/回调