java - 使用盐和迭代计数对消息进行哈希处理的正确方法?

标签 java hash cryptography salt

我需要使用随机盐和迭代计数对消息进行哈希处理。

这是我使用的方式(Way-1)

public static void main(String[] args) {

    byte[] message;
    byte[] randomSalt;
    int iterations = 1000;

    MessageDigest digest = MessageDigest.getInstance("SHA-256");

    byte[] hash = digest.digest(message);

    for (int i = 0; i < iterations; i++) {

        // randomSalt used multi-times
        hash = digest.digest(ArrayUtils.appendArrays(randomSalt, hash));
    }

    // Final result:  randomSalt + hash
}

但是,我发现了人们使用的另一种方式(Way-2)

public static void main(String[] args) {

    byte[] message;
    byte[] randomSalt;
    int iterations = 1000;

    MessageDigest digest = MessageDigest.getInstance("SHA-256");

    // Use randomSalt Once
    digest.update(randomSalt);

    byte[] hash = digest.digest(message);

    for (int i = 0; i < iterations; i++) {

        // randomSalt Are Not used here
        hash = digest.digest(hash);
    }

    // Final result:  randomSalt + hash
}

当然,两种方式会产生不同的输出。

Way-1和Way-2之间的主要区别在于Way-1中,多次使用salt。

问题:您推荐哪种方式?谢谢!

最佳答案

没有一个。

如果您要散列密码来生成加密 key ,那么您应该使用可用的标准化方案,例如 PBKDF2、bcrypt、scrypt 或 Argon2。它们是专门为此目的而设计的。例如scrypt和Argon2会使用大量内存,因此无法通过ASIC实现破解加速。

如果您像在 MAC 中那样对消息进行哈希处理以进行身份​​验证,则只需进行两次哈希处理。 HMAC 是这方面的标准化方案,例如,它可以防止仅使用底层哈希函数就可能发生的长度扩展攻击。进行多次迭代并不会增加安全性,除非 HMAC key 具有低熵(例如密码),在这种情况下,您需要使用基于密码的 key 派生函数的第一个建议来派生一个正确的 key 。/p>

如果您只需要一个完整性检查值,那么进行多次迭代是没有用的,消息的单个哈希就足够了(甚至不需要加盐)。完整性没有安全目的,仅防止意外操纵。另一方面,多次迭代通常用于减慢某些操作,这不是您想要的完整性检查。如果您需要检测恶意操纵,那么您需要使用 MAC,在 HMAC 的情况下,它只不过是一个 key 哈希。

如果您需要消息的哈希值来签名,那么多次迭代也无法提供额外的安全性。用于签名的哈希仅用于减少要签名的消息的大小。实际的签名安全性是由非对称算法而不是哈希算法提供的,因此多次迭代不会在此处添加额外的安全性。如果签名算法被破坏,那么攻击者可以简单地创建被操纵消息的哈希值并对其进行签名。

这些只是哈希函数的一些用途,但它们是最流行的。迭代哈希函数仅在 4 种情况中的一种有用。

关于java - 使用盐和迭代计数对消息进行哈希处理的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38084638/

相关文章:

java - 为什么我的 Google App Engine 应用程序抛出 AccessControlException?

algorithm - 有了哈希和密码,我可以重新创建算法吗?

cryptography - 将 Assets 链接到 solana token

javascript - 与 Javascript 相比,执行 AES 加密是 Ruby

java - 配置 ehCache : Cache is null

java - 如何将一个 HashMap 列表中的不同值添加到另一个 HashMap 列表

java - RabbitMQ 消费者线程池随着每个请求而增加

Perl 修改子程序中的散列引用

perl - 由于相似的键而导致哈希值覆盖?

java - 从文件实例化 JavaKeyStore 时遇到问题