3

我有一个 C# WebService 和一个 (Java) Android 应用程序。是否有一个简单的哈希函数可以在这两种语言之间产生相同的结果?最简单的 C# 哈希是 String.GetHashCode(),但我无法在 Java 中复制它。最简单的 Java 哈希一点也不简单。而且我不知道我是否可以在 C# 中完全复制它。

如果它是相关的,我会在通过互联网发送密码之前对密码进行哈希处理。我目前正在使用 Encode64,但这显然不安全,因为我们可以反转它。


编辑:好的,我决定使用 SHA256。万一其他人需要一个快速的解决方案,这里是我使用的代码,考虑到我希望 C# 和 Java 都输出完全相同的字符串,我需要最简单的解决方案。

爪哇

public String Hash(String s)
{
    StringBuffer sb = new StringBuffer();
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(s.getBytes());
        byte byteData[] = md.digest();
        for (int i = 0; i < byteData.length; i++) {
            sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16)
                    .substring(1));
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return sb.toString();
}

C#

public static string Hash(String s)
{
    HashAlgorithm Hasher = new SHA256CryptoServiceProvider();
    byte[] strBytes = Encoding.UTF8.GetBytes(s);
    byte[] strHash = Hasher.ComputeHash(strBytes);
    return BitConverter.ToString(strHash).Replace("-","").ToLowerInvariant().Trim();
}

多谢你们!:)

4

4 回答 4

7

首先,由实现的散列类型String.GetHashCode()并且String.hashCode()不是为这种事情设计的。首先,它们只散列到 32 但数字(至少在 Java 案例中),因此存在很大的冲突风险。在这种情况下,如果两个不同的密码映射到同一个哈希......那么某人有 2 ^ 32 分之一的机会接受随机选择的密码。(另一方面,如果坏人可以截获 32 位散列以获得有效密码,他们在猜测原始密码是什么方面有很大的“优势”!)

其次,发送加密哈希(例如由 MD5、SHA-256 等生成)可能不会解决您的安全问题……除非您通过 SSL 或其他方式发送哈希。当然,坏人将无法恢复原始密码,但他们可以拦截并在“重放”攻击中使用哈希。(有一些方法可以解决这个问题,但它们要么需要共享密钥,要么需要使用公钥/私钥加密......如果你想让它安全,你必须知道你在做什么。)

简而言之,您需要与具有扎实安全专业知识的人讨论您的整个问题和提出的解决方案。


如果您真的认为这不是安全问题,那么 MD5 哈希应该没问题。但不要说你没有被警告...

(但不要使用简单的 32 位哈希码,因为它几乎不比 base64 更安全。)

于 2012-06-02T04:15:09.747 回答
3

使用标准算法,例如 MD5 或 SHA256,这将在任何平台上产生相同的结果(如果实施正确),但您可能需要考虑这是否真的是在发送密码之前“加密”密码的最佳方式电线。

于 2012-06-02T04:11:26.810 回答
1

如果您正在寻找安全性,您应该尝试加密。否则,有一个内置的散列算法,如 MD5。这应该在 2 之间可靠地一致

于 2012-06-02T04:09:54.000 回答
0

您可以在 Java 中使用以下代码,它可以匹配 C#

public static String getEncryptedPassword(String clearTextPassword) throws NoSuchAlgorithmException{

    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(clearTextPassword.getBytes(StandardCharsets.UTF_8));
    byte[] digest = md.digest();
    String hex = String.format("%064x", new BigInteger(1, digest));
    String st = new String(hex.toUpperCase());
    for (int i = 2; i < (hex.length() + hex.length() / 2) - 1 ;) {
        st = new StringBuffer(st).insert(i, "-").toString();
            i = i + 3;        
    }
    return st ; 

}
于 2018-08-03T14:12:33.500 回答