kdbxtool.security.yubikey

YubiKey HMAC-SHA1 challenge-response support.

This module provides hardware-backed key derivation using YubiKey devices configured with HMAC-SHA1 challenge-response in slot 1 or 2.

The implementation follows the KeePassXC approach: 1. Database’s KDF salt (32 bytes) is used as the challenge 2. YubiKey computes HMAC-SHA1(challenge, hardware_secret) 3. 20-byte response is SHA-256 hashed and incorporated into composite key

This provides hardware-backed security: the database cannot be decrypted without physical access to the configured YubiKey, even if the password is known.

Requirements:
  • yubikey-manager package (install with: pip install kdbxtool[yubikey])

  • YubiKey 2.2+ with HMAC-SHA1 configured in slot 1 or 2

  • Linux: udev rules for YubiKey access (usually automatic)

  • Windows: May require administrator privileges

  • macOS: Works out of box

Security Notes:
  • The YubiKey’s HMAC secret is never extracted or stored

  • Response is wrapped in SecureBytes for automatic zeroization

  • YubiKey loss = data loss (unless backup credentials exist)

Functions

check_slot_configured([slot, serial])

Check if a YubiKey slot is configured for HMAC-SHA1.

compute_challenge_response(challenge[, config])

Send challenge to YubiKey and return HMAC-SHA1 response.

list_yubikeys()

List connected YubiKey devices.

Classes

YubiKeyConfig([slot, serial, timeout_seconds])

Configuration for YubiKey challenge-response.

class kdbxtool.security.yubikey.YubiKeyConfig(slot=2, serial=None, timeout_seconds=15.0)[source]

Bases: object

Configuration for YubiKey challenge-response.

Parameters:
  • slot (int)

  • serial (int | None)

  • timeout_seconds (float)

slot

YubiKey slot to use (1 or 2). Slot 2 is typically used for challenge-response as slot 1 is often used for OTP.

Type:

int

serial

Optional serial number to select a specific YubiKey when multiple devices are connected. If None, uses the first device. Use list_yubikeys() to discover available devices and serials.

Type:

int | None

timeout_seconds

Timeout for challenge-response operation in seconds. If touch is required, this is the time to wait for the button press.

Type:

float

slot: int
serial: int | None
timeout_seconds: float
__init__(slot=2, serial=None, timeout_seconds=15.0)
Parameters:
  • slot (int)

  • serial (int | None)

  • timeout_seconds (float)

Return type:

None

kdbxtool.security.yubikey.list_yubikeys()[source]

List connected YubiKey devices.

Returns:

  • serial: Device serial number (if available)

  • name: Device name/model

Return type:

List of dictionaries containing device info

Raises:

YubiKeyNotAvailableError – If yubikey-manager is not installed.

kdbxtool.security.yubikey.compute_challenge_response(challenge, config=None)[source]

Send challenge to YubiKey and return HMAC-SHA1 response.

This function sends the challenge (the database’s KDF salt) to the YubiKey and returns the HMAC-SHA1 response. The response is computed by the YubiKey hardware using a secret that never leaves the device.

Parameters:
  • challenge (bytes) – Challenge bytes (32-byte KDF salt from KDBX header). Must be at least 1 byte.

  • config (YubiKeyConfig | None) – Optional YubiKey configuration. If not provided, uses slot 2 with 15 second timeout.

Returns:

20-byte HMAC-SHA1 response wrapped in SecureBytes for automatic zeroization when no longer needed.

Raises:
Return type:

SecureBytes

kdbxtool.security.yubikey.check_slot_configured(slot=2, serial=None)[source]

Check if a YubiKey slot is configured for HMAC-SHA1.

This is a convenience function to verify that a slot is properly configured before attempting to use it.

Parameters:
  • slot (int) – YubiKey slot to check (1 or 2).

  • serial (int | None) – Optional serial number to select a specific YubiKey when multiple devices are connected.

Returns:

True if the slot is configured for HMAC-SHA1, False otherwise.

Raises:
Return type:

bool