首页 > 解决方案 > 在 Java 和 C# 中使用 SHA-1 加密 ID 时,C# 有时会返回带有额外 0 的值

问题描述

我有一个连接到另一个外部网站并传递 ID 号的网站,我正在处理并生成链接的页面是用 c# 编写的,而目标网站是用 Java 编写的,我遇到了一些不匹配

我试图在 C# 中使用与 Java 中的代码相同的方法来加密 ID,代码如下所示:

public static String shaHash(String input) 
throws NoSuchAlgorithmException {
  if (input == null) {
    return null;
  }
  MessageDigest sha = MessageDigest.getInstance("SHA");
  try {
    sha.update(input.getBytes("UTF8"));
    BigInteger hash = new BigInteger(1, sha.digest());
    return hash.toString(16);
  } catch (UnsupportedEncodingException e) {}
  return null;
}

C# 代码看起来像

StringBuilder convertedId = new StringBuilder();
            var idToByte = Encoding.ASCII.GetBytes(id);
            using (SHA1 sha1 = SHA1.Create())
            {
                var bytes = sha1.ComputeHash(idToByte);
                for (int i = 0; i < bytes.Length; i++)
                {
                    convertedId.Append(bytes[i].ToString("x2"));
                }
            }
            return convertedId.ToString();

但是返回值是不同的,因为 C# 代码似乎在开头添加了一个额外的 0:

Java:b83caf2f739209c42a8d02df0f6d4794f288703,C#:0b83caf2f739209c42a8d02df0f6d4794f288703

这会是什么问题?我试图更改 UTF8 的 C# 代码中的编码,但仍然无法正常工作。

有什么想法吗?

提前谢谢了

标签: javac#encryptionsha1

解决方案


问题是,你想要额外的 0 还是不想要?

十六进制输出通常以每个字节 2 个十六进制数字完成,因此您会得到偶数位,即前导 0 通常是您想要的。

JavaBigInteger没有这样做,因为对它来说,输出是 base-16 number,而不是bytes的十六进制编码。

因此,与其在 C# 中删除多余的 0,不如在 Java 中添加前导 0。

如果结果字符串的长度为奇数(例如),您可以继续使用BigInteger但在前面加上 a ,或者使用其他一些十六进制编码的. 请参阅如何在 Java 中将字节数组转换为十六进制字符串?0s.length() % 2 != 0byte[]


推荐阅读