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.
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.