我需要使用随机盐和迭代计数对消息进行哈希处理。
这是我使用的方式(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/