设置额外的哈希算法

3

我刚接触C#,正在查看前任生成的代码。以下是代码:

public static string ComputeHash(string plainText,
                                     string hashAlgorithm, byte[] saltBytes)
    {
        if (saltBytes == null)
            saltBytes = CreateSalt(8);

        // Convert plain text into a byte array.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        // Allocate array, which will hold plain text and salt.
        byte[] plainTextWithSaltBytes =
                new byte[plainTextBytes.Length + saltBytes.Length];

        // Copy plain text bytes into resulting array.
        for (int i = 0; i < plainTextBytes.Length; i++)
            plainTextWithSaltBytes[i] = plainTextBytes[i];

        // Append salt bytes to the resulting array.
        for (int i = 0; i < saltBytes.Length; i++)
            plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i];

        // Because we support multiple hashing algorithms, we must define
        // hash object as a common (abstract) base class. We will specify the
        // actual hashing algorithm class later during object creation.
        HashAlgorithm hash;

        // Make sure hashing algorithm name is specified.
        if (hashAlgorithm == null)
            hashAlgorithm = "";

        // Initialize appropriate hashing algorithm class.
        switch (hashAlgorithm.ToUpper())
        {
            case "SHA1":
                hash = new SHA1Managed();
                break;

            case "SHA256":
                hash = new SHA256Managed();
                break;

            case "SHA384":
                hash = new SHA384Managed();
                break;

            case "SHA512":
                hash = new SHA512Managed();
                break;

            default:
                hash = new MD5CryptoServiceProvider();
                break;
        }

        // Compute hash value of our plain text with appended salt.
        byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

        // Create array which will hold hash and original salt bytes.
        byte[] hashWithSaltBytes = new byte[hashBytes.Length +
                                            saltBytes.Length];

        // Copy hash bytes into resulting array.
        for (int i = 0; i < hashBytes.Length; i++)
            hashWithSaltBytes[i] = hashBytes[i];

        // Append salt bytes to the result.
        for (int i = 0; i < saltBytes.Length; i++)
            hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];

        // Convert result into a base64-encoded string.
        string hashValue = Convert.ToBase64String(hashWithSaltBytes);

        // Return the result.
        return hashValue;
    }

    public static bool VerifyHash(string plainText,
                                  string hashAlgorithm,
                                  string hashValue)
    {
        // Convert base64-encoded hash value into a byte array.
        byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue);

        // We must know size of hash (without salt).
        int hashSizeInBits, hashSizeInBytes;

        // Make sure that hashing algorithm name is specified.
        if (hashAlgorithm == null)
            hashAlgorithm = "";

        // Size of hash is based on the specified algorithm.
        switch (hashAlgorithm.ToUpper())
        {
            case "SHA1":
                hashSizeInBits = 160;
                break;

            case "SHA256":
                hashSizeInBits = 256;
                break;

            case "SHA384":
                hashSizeInBits = 384;
                break;

            case "SHA512":
                hashSizeInBits = 512;
                break;

            default: // Must be MD5
                hashSizeInBits = 128;
                break;
        }

        // Convert size of hash from bits to bytes.
        hashSizeInBytes = hashSizeInBits / 8;

        // Make sure that the specified hash value is long enough.
        if (hashWithSaltBytes.Length < hashSizeInBytes)
            return false;

        // Allocate array to hold original salt bytes retrieved from hash.
        byte[] saltBytes = new byte[hashWithSaltBytes.Length -
                                    hashSizeInBytes];

        // Copy salt from the end of the hash to the new array.
        for (int i = 0; i < saltBytes.Length; i++)
            saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];

        // Compute a new hash string.
        string expectedHashString =
                    ComputeHash(plainText, hashAlgorithm, saltBytes);

        // If the computed hash matches the specified hash,
        // the plain text value must be correct.
        return (hashValue == expectedHashString);
    }

公司已升级其安全标准,要求使用安全哈希算法,如SHA-1、3DES(三重DES)或AES MAC。我不知道在哪里包含它们。请有人帮忙吗?


3
3DES不是散列算法,而AES MAC听起来像是一个消息认证码,而不是哈希函数。 - Kerrek SB
@KerrekSB,3DES不就是Triple DES吗?我认为那是一个哈希算法。MAC(消息认证码)不是基于Poly1305-AES吗?如果我错了,请纠正我,因为我对这些都很陌生。 - inquisitive_one
4
在你对加密货币有很牢固的理解并可以自己回答这些问题之前,你应该绝对要避开与加密货币相关的话题!3DES(三重DES)是一种密码算法;MAC是MAC,不是散列函数-- 可以使用哈希设计MAC(例如HMAC),但那是一个单独的主题。 - Kerrek SB
3个回答

2
公司已升级其安全标准,要求使用诸如SHA-1、3DES(三重DES)或AES MAC等安全哈希算法。首先,您已经有了SHA-1,虽然这种哈希算法比SHA-256/512稍微弱一些,但仍然非常好。坚持使用SHA-512将使您非常安全,除非您正在处理愿意花费10年时间使用超级计算机破解您的信息的恶棍。
关于另外两个算法,3DES 是一种对称加密算法,因此不适用于哈希,而 MACs 是使用诸如 SHA-2 的哈希算法创建的(不同之处在于你在消息中哈希一个“秘密密钥”(类似于“固定盐”)以确保其真实性)。AES 也是一种对称加密算法,因此也不适用于哈希。
告诉你公司的人去检查this page并选择其中一个哈希函数(换句话说:不要改变任何东西)。如果你没有经验处理密码学,你的哈希选择可能会使系统不安全。

1

我猜你所说的"AES MAC"是指Poly1305-AES。Poly1305-AES不是一个简单的哈希函数,它需要一个AES密钥和一个128位的nonce,在两个实体之间通信时使用。

3DES(Triple DES)是一种加密密码,它不能确保消息的认证或完整性。3DES的唯一功能是确保消息的机密性。

关于SHA-1,你不应该再使用它,因为它自2005年以来就已经被攻破

我建议你获取这些新安全标准的正式描述。你列出的两个东西甚至都不是哈希算法,第三个也是一个糟糕的选择。在你当前的实现中,列出的哈希算法中,SHA-256及以上的算法应该是可以的(即SHA-2类别)。目前我所知道的这些算法没有任何已发布的漏洞。

附注:您可能希望使用arraycopy而不是循环字节。

0

在.NET Framework基类库中有一个HMAC类型可能对你很有用。

你也可以使用我编写的C#密码工具库的全部或部分内容。但是你需要适应它以添加更多的哈希类型。我写了一系列博客文章来解释为什么以及如何构建这个库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接