Skip to content

PBKDF2 DeriveKey treats count 0 like count 1 when timeInSeconds is 0.0 #1366

Open

Description

@LLian7

Summary

  • Version: Crypto++ 8.9.0.

  • Public/native API: CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256>::DeriveKey.

  • Observed result: for PBKDF2-HMAC-SHA256 with password password, salt salt, output length 32, count 0, and timeInSeconds = 0.0, the function returned 1 and wrote: 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b.

  • Effective control: the same call with count 1 and timeInSeconds = 0.0 also returned 1 and wrote the same 32-byte value.

  • Standard/API conflict: RFC 8018 defines the PBKDF2 count input as a positive integer. This public API accepts zero and returns derived key bytes.

This report only concerns the timeInSeconds = 0.0 path, where the API documentation describes the operation as using the caller-supplied count.

Minimal reproducer

The attached repro.cpp is deterministic and uses only CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256>::DeriveKey. It compares:

  • count_1: count 1, timeInSeconds = 0.0
  • count_0: count 0, timeInSeconds = 0.0

All other inputs are fixed.

Build and run

export CRYPTOPP_INCLUDE_DIR=/path/containing/cryptopp
export CRYPTOPP_LIB=/path/to/libcryptopp.a
./build.sh
./run.sh

Observed behavior

row,library,version,algorithm,api,param,case,count,return_value,success,out_prefix8,out_hex,matches_count_1
case,Crypto++,890,PBKDF2-HMAC-SHA256,CryptoPP::PKCS5_PBKDF2_HMAC<SHA256>::DeriveKey,count,count_1,1,1,true,120fb6cffcf8b32c,120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b,true
case,Crypto++,890,PBKDF2-HMAC-SHA256,CryptoPP::PKCS5_PBKDF2_HMAC<SHA256>::DeriveKey,count,count_0,0,1,true,120fb6cffcf8b32c,120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b,true
result,count_0_accepted_and_equal_to_count_1

Expected behavior

The count-0 call with no time budget should reject the input and should not return derived key bytes. If Crypto++ intentionally treats count 0 as count 1, that behavior should be documented explicitly because RFC 8018 defines the PBKDF2 count input as a positive integer and the timeInSeconds = 0.0 API path is documented as using the caller-supplied count.

build.sh
repro.cpp
run.sh

Activity

  1. Coralesoft commented on Jul 19, 2026

    @Coralesoft
    Contributor

    Thanks for the report. I reproduced the issue and found the same behaviour in PBKDF1 and the PKCS #12 KDF. In each case, the only guard was a debug assert, so release builds silently treated zero iterations as one.

    I submitted PR #1367 to reject zero iterations with InvalidArgument unless a positive TimeInSeconds is supplied. This preserves the existing timed mode.

  2. tearsaalainah26 commented on Sep 29, 2026

    @tearsaalainah26

    Since PR #1367 addresses the input validation for PBKDF2, we should also verify if the PKCS #12 KDF implementation is consistently throwing InvalidArgument across both debug and release builds. If the intent is to enforce RFC 8018 compliance, the guard clause should probably be moved out of the timeInSeconds conditional block entirely to prevent any path from defaulting to a single iteration. Have you considered whether this change should also return an explicit error code for count == 0 when timeInSeconds is greater than 0, or should the time-based auto-calibration logic remain the primary mechanism for that path?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions