Skip to content

Commit baa5d59

Browse files
authored
feat(pbkdf2): add RFC6070 test vectors
2 parents ba78996 + c4b1dbb commit baa5d59

2 files changed

Lines changed: 47 additions & 4 deletions

File tree

src/hmac_utils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ namespace hmac_cpp {
4444
throw std::invalid_argument("PBKDF2: iterations too large");
4545
if (dk_len == 0)
4646
throw std::invalid_argument("PBKDF2: dk_len must be positive");
47-
if (salt_len < 16)
48-
throw std::invalid_argument("PBKDF2: salt must be at least 16 bytes");
47+
if (salt_len == 0)
48+
throw std::invalid_argument("PBKDF2: salt must not be empty");
4949

5050
size_t hlen = 0;
5151
TypeHash hash_type = to_type_hash(prf);

test_all.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ TEST(TokenBoundaryFingerprintTest, MinTime) {
222222
EXPECT_TRUE(hmac::is_token_valid(token_next, key, fingerprint, interval));
223223
}
224224

225-
TEST(PBKDF2Validation, ShortSaltThrows) {
226-
EXPECT_THROW(hmac::pbkdf2("password", "salt", 2, 20, hmac::Pbkdf2Hash::Sha1), std::invalid_argument);
225+
TEST(PBKDF2Validation, EmptySaltThrows) {
226+
EXPECT_THROW(hmac::pbkdf2("password", "", 2, 20, hmac::Pbkdf2Hash::Sha1), std::invalid_argument);
227227
}
228228

229229
TEST(PBKDF2Validation, ZeroIterationsThrows) {
@@ -237,6 +237,49 @@ TEST(PBKDF2Validation, TooLargeDkLenThrows) {
237237
EXPECT_THROW(hmac::pbkdf2("password", salt, 1, too_large, hmac::Pbkdf2Hash::Sha1), std::invalid_argument);
238238
}
239239

240+
TEST(PBKDF2Rfc6070, Sha1Iter1) {
241+
auto dk = hmac::pbkdf2("password", "salt", 1, 20, hmac::Pbkdf2Hash::Sha1);
242+
std::string hex = hmac::to_hex(std::string(dk.begin(), dk.end()));
243+
EXPECT_EQ(hex, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
244+
}
245+
246+
TEST(PBKDF2Rfc6070, Sha1Iter2) {
247+
auto dk = hmac::pbkdf2("password", "salt", 2, 20, hmac::Pbkdf2Hash::Sha1);
248+
std::string hex = hmac::to_hex(std::string(dk.begin(), dk.end()));
249+
EXPECT_EQ(hex, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
250+
}
251+
252+
TEST(PBKDF2Rfc6070, Sha1Iter4096) {
253+
auto dk = hmac::pbkdf2("password", "salt", 4096, 20, hmac::Pbkdf2Hash::Sha1);
254+
std::string hex = hmac::to_hex(std::string(dk.begin(), dk.end()));
255+
EXPECT_EQ(hex, "4b007901b765489abead49d926f721d065a429c1");
256+
}
257+
258+
TEST(PBKDF2Rfc6070, Sha1LongPassword) {
259+
auto dk = hmac::pbkdf2("passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, hmac::Pbkdf2Hash::Sha1);
260+
std::string hex = hmac::to_hex(std::string(dk.begin(), dk.end()));
261+
EXPECT_EQ(hex, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
262+
}
263+
264+
TEST(PBKDF2Rfc6070, Sha1WithNull) {
265+
std::string password("pass\0word", 9);
266+
std::string salt("sa\0lt", 5);
267+
auto dk = hmac::pbkdf2(password, salt, 4096, 16, hmac::Pbkdf2Hash::Sha1);
268+
std::string hex = hmac::to_hex(std::string(dk.begin(), dk.end()));
269+
EXPECT_EQ(hex, "56fa6aa75548099dcc37d7f03425e0c3");
270+
}
271+
272+
TEST(PBKDF2Unicode, Sha1) {
273+
std::string password = u8"пароль";
274+
std::string salt = u8"соль";
275+
auto dk = hmac::pbkdf2(password, salt, 4096, 20, hmac::Pbkdf2Hash::Sha1);
276+
std::vector<uint8_t> ref(20);
277+
ASSERT_TRUE(PKCS5_PBKDF2_HMAC(password.data(), password.size(),
278+
reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
279+
4096, EVP_sha1(), ref.size(), ref.data()));
280+
EXPECT_TRUE(hmac::constant_time_equals(dk, ref));
281+
}
282+
240283
TEST(PBKDF2Validation, IterationsLimit) {
241284
std::string salt(16, 'a');
242285
uint32_t limit = hmac::MAX_PBKDF2_ITERATIONS;

0 commit comments

Comments
 (0)