Hash 如何测试添加盐进行散列的有效性?

Hash 如何测试添加盐进行散列的有效性?,hash,salt,Hash,Salt,我对哈希非常陌生,我已经使用SHA-256和自制的生成盐的方法生成了值的哈希。它涉及为随机盐生成器的每个输入确定查找种子。现在我想验证散列值的完整性,并检查添加的salt的有效性。然而,我不知道如何着手这样做。有人能帮忙吗?现在是验证代码正确性的时候了 …一种软件测试方法,通过该方法,对单个源代码单元、一个或多个计算机程序模块集以及相关的控制数据、使用程序和操作程序进行测试,以确定它们是否适合使用。直观地说,可以将单元视为应用程序中最小的可测试部分 单元测试借助于测试框架,测试框架可以检查您的代

我对哈希非常陌生,我已经使用SHA-256和自制的生成盐的方法生成了值的哈希。它涉及为随机盐生成器的每个输入确定查找种子。现在我想验证散列值的完整性,并检查添加的salt的有效性。然而,我不知道如何着手这样做。有人能帮忙吗?

现在是验证代码正确性的时候了

…一种软件测试方法,通过该方法,对单个源代码单元、一个或多个计算机程序模块集以及相关的控制数据、使用程序和操作程序进行测试,以确定它们是否适合使用。直观地说,可以将单元视为应用程序中最小的可测试部分

单元测试借助于测试框架,测试框架可以检查您的代码库,找到任何标记为测试的内容,并按需(即当您告诉它时)和/或作为构建或部署过程的一部分自动运行它。目标是在一定程度上保证对测试代码所做的更改不会破坏应用程序。测试应涵盖输入及其预期输出的组合,从而强制执行行为

流行的测试框架包括Java、.Net语言和

无论如何,为了测试散列方案的完整性,您希望有一个封装所有行为的方法。您的单元测试将涵盖这一方法1。用Java JUnit语法编写(使用matchers,您可以看到更多关于matchers的内容),我们可能会有如下内容:

import org.junit.*;
public class PasswordSha256HasherTest {

    // Known inputs and outputs
    // hashes are precomputed with an external SHA256 calculator and verified
    public static final String password = "thisismypassword";
    public static final String unsaltedHash = "1da9133ab9dbd11d2937ec8d312e1e2569857059e73cc72df92e670928983ab5";
    public static final String salt = "a19044b439748e23ccbc82c5e2549ece5ceae026340ac6cb1f616549e64020e3";

    // This is what we want: SHA256(salt+password);
    public static final String saltedHash = "6c89a97409d598650e458a2040e900abbeca8e697137353fdaae97e382378433"

    // If your hasher has to be instantiated, do it like this
    private PasswordHasher hasher;

    @BeforeClass
    public static void beforeClass() throws Exception {
        hasher = new PasswordHasher();
    }

    @Test
    public void testCorrectPasswordHash() throws Exception {
        String hash = hasher.getPasswordHash(password, salt);
        // If PasswordHasher is a static class, you can skip the instantiation and do this
        String hash = PasswordHasher.getPasswordHash(password, salt);

        assertThat("Hash should match SHA256(salt + password)",
            hash, equalTo(saltedHash));
        // You could also test that the hash doesn't match the password or the salt
    }

    @Test(expected= IllegalArgumentException)
    public void testSaltIsRequired() throws Exception {
        // If the exception for an empty salt IS NOT thrown, this test fails.
        String hash = hasher.getPasswordHash(password, "");
    }

}
这只是一个开始,但这将实现问题的目标-验证哈希实用程序的完整性。您当然可以编写许多其他测试(验证密码复杂性要求、不允许使用字典中的单词、salt长度要求等)。一些测试倡导者认为,编写有用且有意义的测试需要与设计代码本身一样多的思考和投入。甚至还有测试驱动开发的理念,即首先编写测试(描述和封装代码的所有需求),并在所有测试通过后立即停止编写代码。这两者都有各自的优点

如果你有兴趣向(可能)世界上最好的测试人员学习,我也鼓励你去看看

最后,在一个相关的注释中,我想阐明我的观点,即盐应该是非确定性的,并且是全球唯一的。实现这一点的最简单方法是一个足够大的伪随机值,它完全独立于与您的系统和用户有关的一切,例如。正如在Security.SE上一样,解决了确切的主题。作为一个例子,如果你在做你自己的加密工作,你几乎肯定是错的


1:关于单元测试的正确范围有一些争论。有人可能会说,对于登录系统来说,最有意义的工作单元是用户的创建和授权——具体来说,保护密码的机制只是授权模式其余部分的一部分,因此应该一起测试。我对他们说,单独测试每个部分可以使查找和纠正特定错误的过程更容易、更直接。

每个操作系统都有一个随机源,并提供从该源获取随机字节的方法。大多数应用程序无法自行生成加密安全的盐,这就是它们从随机源读取数据的原因。测试此方法是在其他地方完成的,不需要在应用程序中测试这样的salt生成器,只需调用操作系统的方法。

Martin说,最好使用操作系统提供的伪随机值作为salt,从一个记录为适合加密使用的函数中

另外,如果你想评估你自己的salt程序,质量标准是它应该产生大量可能的输出——包括你从随机数中得到的分组、分散和重复的水平,即使salt计算的输入只有一两个不同。对于散列函数来说,这几乎是相同的标准,但是您可能不需要某种安全措施来防止从salt值派生原始输入


另外,如果您正在从某个用户的地址重新生成salt,而他们更改了它,您可能希望他们的当前密码使用新salt重新计算哈希值,或者将旧salt或地址保存到某个地方以供继续使用。。。否则,他们的下一次登录尝试将注定失败。

我不确定您关心的是什么完整性。您是否为哈希函数编写了单元测试?然而,确定性盐是个坏主意。例如,如果您使用密码本身为PRNG种子(如果您的意思是这样的话),那么您的salt不会增加任何保护。攻击者仍然可以在一次bruteforce运行中破解数据库中的每个密码。@PatrickM完整性我指的是如何检查生成的哈希值是否正确。不,我没有写单元测试,我不确定我是否理解你的意思。我不是用密码本身植入PRNG,而是用密码和根据可用用户详细信息确定的一些加扰值的组合植入。非常感谢您的回复,非常感谢。我确实学到了很多关于回应的东西。当你说“分组、分散和重复的级别”时,你到底是什么意思?@jojo:你在其他地方的评论中说,你是通过“密码和一些根据用户详细信息确定的加扰值的组合”来生成salt的-假设你的盐是32位数字-你不想生成通常相似或相近的数字。。。理想情况下,两种盐在统计上的每一位都应该是完全不相关的,即使密码