我对哈希很新,我使用SHA-256和自制的盐生成方法生成值的哈希值。它涉及确定性地为随机盐生成器的每个输入找到种子。现在我想验证哈希值的完整性,并检查添加的盐的有效性。但是,我不知道该怎么做。任何人都可以帮忙吗?
答案 0 :(得分:1)
每个操作系统都有一个随机源并提供从该源获取随机字节的方法。大多数应用程序无法自己生成加密安全的盐,这就是他们从随机源读取的原因。测试此方法是在其他地方完成的,不需要在应用程序中测试这样的salt生成器,只需调用操作系统的方法。
答案 1 :(得分:0)
验证代码的正确性是Unit Testing的时间。
...一种软件测试方法,通过该方法测试各个源代码单元,一个或多个计算机程序模块的集合以及相关的控制数据,使用程序和操作程序,以确定它们是否适合使用。{ {3}}直观地,可以将单元视为应用程序中最小的可测试部分。
单元测试由测试框架辅助,框架可以检查您的代码库,查找标记为测试的任何内容并按需运行(即,当您告知它时)和/或自动作为构建或部署过程的一部分。我们的目标是获得某种程度的保证,即您对测试代码所做的更改不会破坏您的应用程序。测试应涵盖输入组合及其预期输出,从而强制执行行为。
热门测试框架包括用于Java的1,用于.Net语言的JUnit和NUnit。
无论如何,为了测试散列方案的完整性,您希望有一个封装所有行为的方法。您的单元测试将涵盖这一方法 1 。用Java JUnit语法编写它(使用匹配器,您可以看到更多关于many others的信息),我们可能会有这样的结果:
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, "");
}
}
这只是一个开始,但这将完成您的问题的目标 - 验证哈希实用程序的完整性。您可以确定地编写许多其他测试(验证密码复杂性要求,禁止字典单词,盐长度要求等)。一些测试倡导者认为,编写有用且有意义的测试需要与设计代码本身一样多的思考和奉献。甚至还有测试驱动开发的理念,它指出你应该首先编写测试 (描述和封装代码的所有要求),并在所有测试通过后立即停止编写代码。这两者都有其优点。
如果您有兴趣向(可能)这个星球上的一些最好的测试人员学习,我也鼓励您查看here。
最后,在相关的说明中,我想把我的观点告诉我们,盐应该是非确定性的并且是全球唯一的。实现此目标的最简单方法是使用足够大的伪随机值,该值与您的系统和用户完全无关,例如Google testing blog。 GUID解决了确切的主题,Security.SE上的This question也是如此。作为this question,如果您使用加密技术做自己的事情,那几乎肯定是错的。
1 :关于单元测试的适当范围存在争议。有人可能会说,登录系统最低有意义的工作单元是用户的创建和授权 - 具体来说,保护密码的机制只是授权模式其余部分的一部分,因此应该一起测试。对他们来说,我说分别测试每个部分会使查找和纠正特定错误的过程更容易,更直接。
答案 2 :(得分:0)
Martin说,你最好使用操作系统提供的伪随机值作为salt,从一个记录的适合加密用途的函数中使用。
另外,如果你想评估自己的盐常规,质量的标准是它应该产生大量可能的输出 - 具有从随机数得到的分组,分散和重复的水平,即使盐计算的输入只有一两个不同。它几乎与哈希函数的标准相同,但您可能不需要安全的东西来防止从salt值派生原始输入。
另外,如果您从用户的地址重新生成盐并且他们更改了它,您希望他们的当前密码用新盐重新计算哈希值,或者将旧盐或地址保存在某处以供持续使用...否则他们的下次登录尝试将注定失败。