Question

I'm writing a program which hashes passwords with the pbkdf2 method using cryptopp.

I have problems with validating the passwords. I have tried to compare the output in "length-constant" time but it always fails and returns false.

// a and b are std strings containing the output of the DeriveKey function

unsigned diff = a.length() ^ b.length();
for(unsigned i = 0; i < a.length() && i < b.length(); i++)
{
      diff |= (unsigned)a[i] ^ (unsigned)b[i];
}

bool equal = diff == 0;

Is using "slow equals" even the right way to validate pbkdf2 passwords? I am a bit confused on this.

Was it helpful?

Solution

I'm writing a program which hashes passwords with the pbkdf2 method using cryptopp.

You linked to the Crypto++ main page, and not a your particular use of PBKDF. Here's some code just in case (it uses the IETF test vectors from RFC 6070):

int main(int argc, char* argv[])
{
    byte password[] ="password";
    size_t plen = strlen((const char*)password);

    byte salt[] = "salt";
    size_t slen = strlen((const char*)salt);

    int c = 1;
    byte derived[20];

    PKCS5_PBKDF2_HMAC<CryptoPP::SHA1> pbkdf2;
    pbkdf2.DeriveKey(derived, sizeof(derived), 0, password, plen, salt, slen, c);

    string result;
    HexEncoder encoder(new StringSink(result));

    encoder.Put(derived, sizeof(derived));
    encoder.MessageEnd();

    cout << "Derived: " << result << endl;

    return 0;
}

I have tried to compare the output in "length-constant" time but it always fails and returns false.

Crypto++ has a constant time compare built in. Use VerifyBufsEqual from misc.h. The source is available in misc.cpp.

$ cd cryptopp
$ grep -R VerifyBufsEqual *
cryptlib.cpp:   return VerifyBufsEqual(digest, digestIn, digestLength);
default.cpp:    if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
fipstest.cpp:   if (!VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
fipstest.cpp:   if (VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
misc.cpp:bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
misc.h:CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
pssr.cpp:   valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
pubkey.cpp: return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
secblock.h:     return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));

What I'm not clear about: VerifyBufsEqual is predicated upon buffers of equal lengths. I'm not sure if its OK to overlook the "not-equal length" case.


There's also a question on the Information Stack Exchange that may be relevant: Timing attacks on password hashes. But I'm not certain if/how it generalizes to arbitrary buffer compares.

The question piqued my interest in an answer to the general problem (the question has always been there): Constant time compares when array sizes are not equal?. That should tell us if we have the proper tools in VerifyBufsEqual (Crypto++), CRYPTO_memcmp (OpenSSL), etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top