Blog

2015-07-05 18:37:46

Generating Cryptographically Secure Salt Values

Here is a small snippet of C++ code that demonstrates how to generate unpredictable salt values for use in password hashing using cryptographically secure random number generators for linux and win32.

An unpredictable salt is important because using a predictable salt would make it easier for attackers to compromise the system with lookup/rainbow table based attacks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifdef _WIN32
    #define _CRT_RAND_S
    #include <stdlib.h>
#endif

namespace
{
#ifdef _WIN32
    // cryptographically secure win32 entropic sampler (as of 2015)
    // https://msdn.microsoft.com/en-us/library/sxtz2fa8.aspx
    unsigned int GenerateRandomNumber()
    {
        unsigned int randomNumber = 0;
        while(randomNumber == 0)
        {
            rand_s(&randomNumber);
        }
        return randomNumber;
    }
#endif
#ifdef __linux__
    // cryptographically secure linux entropic sampler (as of 2015)
    // https://en.wikipedia.org/wiki//dev/random
    unsigned int GenerateRandomNumber()
    {
        // don't use std::ifstream as it buffers input - this can
        // exhaust the entropy pool prematurely
        FILE* randomDataSource = fopen("/dev/random", "r");
        if(randomDataSource == nullptr)
        {
            throw std::exception("unable to open /dev/random for reading.");
        }

        unsigned int randomData;
        unsigned int result = 0;
        while(result != 1)
        {
            result = fread(
                &randomData, sizeof(randomData), 1, randomDataSource);
        }

        fclose(randomDataSource);
        return randomData;
    }
#endif
    std::string GenerateSalt(unsigned int length)
    {
        const std::string alphanum =
            "0123456789"
            "abcdefghijklmnopqrstuvwxyz"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        std::string resultStr;
        resultStr.reserve(length);

        while(length-- > 0)
        {
            unsigned int sampleOffset =
                GenerateRandomNumber() % (alphanum.length() - 1);

            resultStr.push_back(alphanum[sampleOffset]);
        }

        return resultStr;
    }
}