当前位置: 首页 > 面试题库 >

C#和Java-hmacsha256哈希之间的区别

黄浩涆
2023-03-14
问题内容

我在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");

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

然后,您应该在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=


 类似资料:
  • 问题内容: 我面临着一个奇怪的问题,它与Java和php5中的MD5-Hashes有关。我发现在某些情况下,以下代码无法生成正确的MD5哈希值: 我不得不迁移现有的用户数据库,密码存储在php5 MD5中。现在,部分用户(并非全部)无法登录,因为我的Java代码无法生成正确的MD5哈希。 任何想法上面有什么问题吗? 问题答案: 无法正确转换<0x10字节,则需要用零填充。 例:

  • 本文向大家介绍Java中的树集和哈希集之间的区别,包括了Java中的树集和哈希集之间的区别的使用技巧和注意事项,需要的朋友参考一下 哈希集和树集都属于集合框架。HashSet是Set接口的实现,而Tree set实现排序的集。树集由TreeMap支持,而HashSet由哈希映射支持。 序号 键 哈希集 树集 1 实作  哈希集是使用HashTable实现的  树集是使用树结构实现的。  2 空对象

  • 本文向大家介绍Java中并发哈希映射和同步哈希映射之间的区别,包括了Java中并发哈希映射和同步哈希映射之间的区别的使用技巧和注意事项,需要的朋友参考一下 并发Hashmap是jdk1.5中引入的类。并发哈希映射仅在添加或更新映射时在称为片段的存储桶级别应用锁。因此,并发哈希映射允许对映射进行并发读写操作。  同步hashmap(Collection.syncronizedHashMap())是C

  • 问题内容: 我有一个大问题。我使用此C#函数对消息进行编码: 在Java方面,我使用以下代码段: 我的消息是:阻止|注释|文本!£$%&/()=?^€> <{}ç°§;:_-。,@#ùàòè+ 我有这个结果: 你能帮我吗??谢谢… 问题答案: 我的猜测是您似乎正在将ASCII字节与Latin1字节进行比较。尝试切换 对此 那可能会解决您的问题。 (或切换C#以使用Latin1) 程序中发生的事情是

  • 问题内容: 是图像文件的字符串。 我在C#中具有以下代码: 和Java中的代码如下: 结果是不同的。 有人说是因为 Java字节:-128至127 C#字节:0到255 但是我该如何解决呢?如何在Java中实现C#?通过使用Java,我需要与C#中相同的结果。 问题答案: 您正在对 字符串进行 base64编码吗?你想做什么?您首先需要将字符串转换为字节序列,然后选择一种编码,例如UTF-8或UT

  • 问题内容: 我只是在阅读一些Java书籍并制作一些小程序进行练习,我创建了一个小代码来获取有关所输入路径的信息,该代码为: 现在在输入对话框中,当我输入时,结果是,但是当我输入C:/时,它将显示C中目录和文件的完整列表。 奇怪的是,D驱动器和其他驱动器不会发生这种情况(即D:/和D:的结果是相同的),这是怎么回事? 更新 使用C#在WPF中也会发生同样的情况! 问题答案: 表示“驱动器上当前选择的