1

I am fairly new with hashing and I have generated hashes for values using SHA-256 and a self made method of generating salts. It involves deterministically finding the seed for each input for the random salt generator. Now I would like to verify the integrity of the hash values and also check the effectiveness of the salt added. However, I do not know how to go about doing this. Can anyone help with this?

peterh
  • 11,875
  • 18
  • 85
  • 108
jojo
  • 11
  • 1
  • I'm not sure what integrity you're concerned about. Did you write a unit test for your hash function? Deterministic salt is a bad idea, however. For instance, if you seed the PRNG with the password itself (if that's what you meant), then your salt adds no protection. An attacker can still crack every password in your database in a single bruteforce run. – Patrick M Aug 05 '14 at 14:41
  • @PatrickM By integrity I mean how to check if the hash values generated are correct. No I did not write a unit test and I am not sure I understand what you mean by that. I am not seeding the PRNG with the password itself, rather I am seeding with a combination of the password and some scrambled values determined from user details available. – jojo Aug 05 '14 at 16:49

3 Answers3

1

Each operating system has a random source and offer methods to get random bytes from this source. Most applications are not able on their own to generate cryptographically safe salts, that's why they read from the random source. Testing this method is done elsewhere, there is no need to test such a salt generator in your application, just call the method of the operating system.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
0

Verifying the correctness of your code is the time for Unit Testing.

...a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use.1 Intuitively, one can view a unit as the smallest testable part of an application.

Unit testing is aided by testing frameworks, which can examine your code base, find anything marked as a test and run it on demand (i.e. when you tell it to) and/or automatically as part of a build or deploy process. The goal is to gain some level of guarantee that changes you've made to the code under test won't break your application. The test should cover combinations of inputs and their expected outputs, thus enforcing behavior.

Popular testing frameworks include JUnit for Java, NUnit for .Net languages and many others.

Anyways, to test the integrity of your hashing scheme, you would hopefully have a single method that encapsulates all the behavior. Your unit test would cover this one method1. Writing this in a Java JUnit syntax (with matchers, which you can see more about here), we might have something like this:

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, "");
    }

}

This is just a start, but this would accomplish the goal of your question - verify the integrity of your hashing utility. There are many other tests you could surely write (verify password complexity requirements, disallow dictionary words, salt length requirements, etc.). Some advocates of testing maintain that writing useful and meaningful tests requires as much thought and dedication as designing the code itself. There is even the philosophy of Test Driven Development, which states you should write tests first (which describe and encapsulate all the requirements of the code), and stop writing code as soon as all the tests pass. Both of these have their merits.

I also encourage you to check out the Google testing blog if you're interested in learning from (probably) some of the best testers on the planet.

Finally, on a related note, I want to drive home my point that salts should be non-deterministic and globally unique. The easiest way to accomplish this is a sufficiently large pseudo-random value that is completely independent of everything to do with your system and your users, such as a GUID. This question tackles the exact topic, as does this question on Security.SE. As the common adage on the internet goes, if you're doing your own thing with cryptography, you are almost certainly wrong.

1: There is some debate over the proper scope of a unit test. Some might say that the lowest meaningful unit of work for a login system is the creation and authorization of a user - specifically, the mechanism of securing the password is only a part of the rest of authorization schema, and therefore it should be tested all together. To them I say that testing each part separately makes the process of finding and correcting specific bugs easier and more straightforward.

Community
  • 1
  • 1
Patrick M
  • 10,547
  • 9
  • 68
  • 101
0

At Martin says, you're best of using an OS-provided pseudo-random value as salt, from a function's that's documented to be appropriate for cryptographic use.

Separately, if you want to to assess your own salt routine, the criterion for quality is that it should produce a vast range of possible outputs - with the levels of grouping, scatter and repetition that you'd get from random numbers, even if the inputs to the salt calculation only differ in a bit or two. It's pretty much the same criterion for a hash function, but you probably don't need something secure against deriving the original inputs from the salt value.

Separately, if you're regenerating the salt from say a user's address and they change it, you'd want their current password to recalcualte the hash with a new salt, or to save the old salt or address somewhere for ongoing use... otherwise their next login attempt is doomed.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • thanks a lot for the response. when you say "levels of grouping, scatter and repetition", what exactly do you mean? – jojo Aug 08 '14 at 14:33
  • @jojo: you say in a comment elsewhere you're generating the salt from a "combination of the password and some scrambled values determined from user details" - say your salts were 32 bit numbers - you wouldn't want to generate numbers that were often similar or nearby... ideally two salts should statistically be totally uncorrelated in every bit even if the password and user details involved only differ in a single bit. But, it's still better to get something random from the OS - it may get entropy from mouse movements, webcams, temperature sensors, fan speed etc. that makes the salts random. – Tony Delroy Aug 09 '14 at 19:28