Main Content

Missing salt for hashing operation

Hashed data is vulnerable to rainbow table attack

Description

This defect occurs when you use a digest context in these functions, but you hash data into the context only once or you use a null salt in all subsequent hashing operations. A salt is random data that you use to improve the security of a hashing operation. The hashing operation takes the salt as an input to produce a more secure hashed value.

  • EVP_DigestFinal

  • EVP_DigestSignUpdate

  • EVP_DigestVerifyUpdate

  • SHA*_Final family of functions

Missing salt for hashing operation raises no defect if no information is available about the context. For instance, if the context is passed as an argument to the function that calls the hashing operation or if the context is declared outside the scope of the function. For example, no defect is raised in this code snippet.

EVP_MD_CTX ctx_global;

void foo(EVP_MD_CTX* ctx) {
//ctx passed as argument of func()
    EVP_DigestFinal(ctx, out_buf, &out_len); //no defect
}

void bar() {
// ctx_global declared outside of bar() 
    EVP_DigestFinal(&ctx_glob, out_buf, &out_len); //no defect
}

Risk

Hashing the same data without a salt results in the same hashed value. For instance, if you hash user passwords and two users have the same passwords, the hashed passwords are identical. The hashing is then vulnerable to precomputed rainbow attacks.

Fix

Provide a salt when you hash data.

Examples

expand all

#include <openssl/evp.h>
#include <cstring>

unsigned char* out_buf;
unsigned int out_len;

void func()
{
    const char* src = "toto";
    EVP_MD_CTX ctx;

    EVP_DigestInit(&ctx, EVP_sha256());
    EVP_DigestUpdate(&ctx, src, strlen(src));
    EVP_DigestFinal(&ctx, out_buf, &out_len);
    EVP_cleanup();
}

In this example, context ctx is initialized with secure hashing algorithm SHA-256, then EVP_DigestUpdate hashes src into ctx. Because EVP_DigestUpdate is called only once, no salt can be provided to improve the security of the hashing operation. The digest value that EVP_DigestFinal retrieves is then vulnerable to precomputed rainbow attacks.

Correction — Hash Salt Into Context After Initial Data Hash

One possible correction is to hash a salt into the context ctx after the first hashing operation. The resulting digest value that EVP_DigestFinal retrieves is more secure.

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <cstring>

#define BUFF_SIZE_32 32

unsigned char* out_buf;
unsigned int out_len;

void func()
{
    const char* src = "toto";
    const char* salt;

    RAND_bytes((unsigned char*)salt, BUFF_SIZE_32);
    EVP_MD_CTX ctx;

    EVP_DigestInit(&ctx, EVP_sha256());
    EVP_DigestUpdate(&ctx, src, strlen(src));
    EVP_DigestUpdate(&ctx, salt, BUFF_SIZE_32);
    EVP_DigestFinal(&ctx, out_buf, &out_len);
    EVP_cleanup();
}

Result Information

Group: Cryptography
Language: C | C++
Default: Off
Command-Line Syntax: CRYPTO_MD_NO_SALT
Impact: Medium

Version History

Introduced in R2019b