#ifndef BOOST_TEST_DYN_LINK #define BOOST_TEST_DYN_LINK #endif #define BOOST_TEST_NO_MAIN #include #include #include "config.h" #include "credentials.hh" BOOST_AUTO_TEST_SUITE(credentials_cc) #if defined(DISABLE_HASHED_CREDENTIALS) #undef HAVE_EVP_PKEY_CTX_SET1_SCRYPT_SALT #endif #ifdef HAVE_EVP_PKEY_CTX_SET1_SCRYPT_SALT BOOST_AUTO_TEST_CASE(test_CredentialsUtils) { const std::string plaintext("test"); /* generated with hashPassword("test") */ const std::string sampleHash("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI="); auto hashed = hashPassword(plaintext); BOOST_CHECK(!hashed.empty()); BOOST_CHECK(verifyPassword(hashed, plaintext)); BOOST_CHECK(verifyPassword(sampleHash, plaintext)); BOOST_CHECK(!verifyPassword(hashed, "not test")); BOOST_CHECK(!verifyPassword(sampleHash, "not test")); BOOST_CHECK(!verifyPassword("test", "test")); BOOST_CHECK(isPasswordHashed(hashed)); BOOST_CHECK(isPasswordHashed(sampleHash)); BOOST_CHECK(!isPasswordHashed(plaintext)); { // hash password with custom parameters auto customParams = hashPassword(plaintext, 512, 2, 16); // check that the output is OK BOOST_CHECK(boost::starts_with(customParams, "$scrypt$ln=9,p=2,r=16$")); // check that we can verify the password BOOST_CHECK(verifyPassword(customParams, plaintext)); } { // hash password with invalid parameters BOOST_CHECK_THROW(hashPassword(plaintext, 0, 2, 16), std::runtime_error); BOOST_CHECK_THROW(hashPassword(plaintext, 512, 0, 16), std::runtime_error); BOOST_CHECK_THROW(hashPassword(plaintext, 512, 2, 0), std::runtime_error); } // empty BOOST_CHECK(!isPasswordHashed("")); // missing leading $ BOOST_CHECK(!isPasswordHashed("scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // prefix-only BOOST_CHECK(!isPasswordHashed("$scrypt$")); // unknown algo BOOST_CHECK(!isPasswordHashed("$tcrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // missing parameters BOOST_CHECK(!isPasswordHashed("$scrypt$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // empty parameters BOOST_CHECK(!isPasswordHashed("$scrypt$$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // missing r BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // salt is too short BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$dGVzdA==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // hash is too short BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$c2hvcnQ=")); // missing salt BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // missing $ between the salt and hash BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=")); // no hash BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$")); // hash is too long BOOST_CHECK(!isPasswordHashed("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$dGhpcyBpcyBhIHZlcnkgbG9uZyBoYXNoLCBtdWNoIG11Y2ggbG9uZ2VyIHRoYW4gdGhlIG9uZXMgd2UgYXJlIGdlbmVyYXRpbmc=")); // empty r BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=1,r=$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // too many parameters BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=1,r=8,t=1$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // invalid ln BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=A,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // invalid p BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=p,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // missing ln BOOST_CHECK_THROW(verifyPassword("$scrypt$la=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // missing p BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,q=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // missing r BOOST_CHECK_THROW(verifyPassword("$scrypt$l,ln=10,q=1,s=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // work factor is too large BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=16,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // salt is too long BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=1,r=8$dGhpcyBpcyBhIHZlcnkgbG9uZyBzYWx0$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // invalid b64 salt BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI=", plaintext), std::runtime_error); // invalid b64 hash BOOST_CHECK_THROW(verifyPassword("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJd", plaintext), std::runtime_error); } #endif BOOST_AUTO_TEST_CASE(test_CredentialsHolder) { const std::string plaintext("test"); auto holder = CredentialsHolder(std::string(plaintext), false); BOOST_CHECK(holder.matches(plaintext)); BOOST_CHECK(!holder.matches("not test")); BOOST_CHECK(!holder.wasHashed()); BOOST_CHECK(!holder.isHashed()); #ifdef HAVE_EVP_PKEY_CTX_SET1_SCRYPT_SALT BOOST_CHECK(CredentialsHolder::isHashingAvailable()); const std::string sampleHash("$scrypt$ln=10,p=1,r=8$1GZ10YdmSGtTmKK9jTH85Q==$JHeICW1mUCnTC+nnULDr7QFQ3kRrZ7u12djruJdrPhI="); auto fromHashedHolder = CredentialsHolder(std::string(sampleHash), true); BOOST_CHECK(fromHashedHolder.wasHashed()); BOOST_CHECK(fromHashedHolder.isHashed()); BOOST_CHECK(fromHashedHolder.matches(plaintext)); BOOST_CHECK(!fromHashedHolder.matches("not test")); auto fromPlaintextHolder = CredentialsHolder(std::string(plaintext), true); BOOST_CHECK(!fromPlaintextHolder.wasHashed()); BOOST_CHECK(fromPlaintextHolder.isHashed()); BOOST_CHECK(fromPlaintextHolder.matches(plaintext)); BOOST_CHECK(!fromPlaintextHolder.matches("not test")); #else BOOST_CHECK(!CredentialsHolder::isHashingAvailable()); #endif } BOOST_AUTO_TEST_CASE(test_SensitiveData) { size_t bytes = 16; SensitiveData data(bytes); BOOST_CHECK_EQUAL(data.getString().size(), bytes); SensitiveData data2("test"); data2 = std::move(data); BOOST_CHECK_EQUAL(data2.getString().size(), bytes); BOOST_CHECK_EQUAL(data.getString().size(), 0U); data2.clear(); BOOST_CHECK_EQUAL(data2.getString().size(), 0U); } BOOST_AUTO_TEST_SUITE_END()