Python library for communicating with Yubico YubiKey hardware authentication tokens
npx @tessl/cli install tessl/pypi-python-yubico@1.3.0A comprehensive Python library for communicating with Yubico YubiKey hardware authentication tokens. It enables bidirectional USB communication for advanced YubiKey operations including device configuration, challenge-response authentication, and device management functions.
pip install python-yubicopyusb (for USB HID communication)import yubicoFor specific components:
from yubico import find_yubikey, YubiKey
from yubico.yubikey_config import YubiKeyConfig
from yubico.yubico_exception import YubicoErrorimport yubico
try:
# Find and connect to YubiKey
yubikey = yubico.find_yubikey(debug=False)
# Get device information
print("Version:", yubikey.version())
print("Serial:", yubikey.serial())
# Simple challenge-response example
challenge = b"test challenge data"
response = yubikey.challenge_response(challenge, mode='HMAC', slot=1)
print("Response:", response.hex())
except yubico.yubico_exception.YubicoError as e:
print("ERROR:", e.reason)The library uses a hierarchical class structure:
find_yubikey() automatically detects and returns the appropriate YubiKey class instanceYubiKeyUSBHID, YubiKeyNEO_USBHID, YubiKey4_USBHID handle version-specific featuresYubiKeyConfig provides declarative configuration with validation and version compatibility checkingYubiKeyFrame handles low-level USB HID communication protocolThis design abstracts hardware differences while providing full access to device-specific capabilities, making it suitable for both simple authentication tasks and advanced YubiKey management applications.
Locate and establish communication with YubiKey devices, supporting multiple connected devices and providing automatic device type detection.
def find_yubikey(debug=False, skip=0):
"""
Locate and connect to a YubiKey device.
Parameters:
- debug (bool): Enable debug output
- skip (int): Number of devices to skip
Returns:
YubiKey: Connected YubiKey instance
Raises:
YubiKeyError: If no YubiKey found
"""Core device operations including version detection, serial number retrieval, and basic device status queries available across all YubiKey models.
class YubiKey:
def version(self): ...
def serial(self, may_block=True): ...
def challenge_response(self, challenge, mode='HMAC', slot=1, variable=True, may_block=True): ...
def write_config(self, cfg, slot): ...Comprehensive configuration system supporting all YubiKey modes including Yubico OTP, OATH-HOTP, and challenge-response with full control over device settings, flags, and security parameters.
class YubiKeyConfig:
def __init__(self, ykver=None, capabilities=None, update=False, swap=False, zap=False): ...
def mode_yubikey_otp(self, private_uid, aes_key): ...
def mode_oath_hotp(self, secret, digits=6, factor_seed=None, omp=0x0, tt=0x0, mui=''): ...
def mode_challenge_response(self, secret, type='HMAC', variable=True, require_button=False): ...
def aes_key(self, data): ...
def ticket_flag(self, which, new=None): ...
def config_flag(self, which, new=None): ...
def extended_flag(self, which, new=None): ...HMAC-SHA1 and Yubico challenge-response authentication for secure authentication workflows, supporting both variable and fixed-length responses.
def challenge_response(challenge, mode='HMAC', slot=1, variable=True, may_block=True):
"""
Perform challenge-response operation.
Parameters:
- challenge (bytes): Challenge data
- mode (str): 'HMAC' or 'OTP'
- slot (int): Configuration slot (1 or 2)
- variable (bool): Variable length response
- may_block (bool): Allow blocking operations
Returns:
bytes: Response data
"""Comprehensive error handling with specific exception types for different failure modes including device communication errors, configuration errors, and timeout conditions.
class YubicoError(Exception):
def __init__(self, reason): ...
class YubiKeyError(YubicoError): ...
class YubiKeyTimeout(YubiKeyError): ...
class YubiKeyVersionError(YubiKeyError): ...
class InputError(YubicoError): ...Helper functions for data processing, CRC validation, hex dumping, and ModHex encoding/decoding operations commonly needed in YubiKey applications.
def crc16(data): ...
def validate_crc16(data): ...
def hexdump(src, length=8, colorize=False): ...
def modhex_decode(data): ...
def hotp_truncate(hmac_result, length=6): ...Configuration slot identifiers and command constants:
class SLOT:
CONFIG = 0x01 # First configuration slot
CONFIG2 = 0x03 # Second configuration slot
UPDATE1 = 0x04 # Update slot 1
UPDATE2 = 0x05 # Update slot 2
SWAP = 0x06 # Swap slots
NDEF = 0x08 # Write NDEF recordYubiKey operating mode identifiers:
class MODE:
OTP = 0x00 # OTP only
CCID = 0x01 # CCID only, no eject
OTP_CCID = 0x02 # OTP + CCID composite
U2F = 0x03 # U2F mode
OTP_U2F = 0x04 # OTP + U2F composite
U2F_CCID = 0x05 # U2F + CCID composite
OTP_U2F_CCID = 0x06 # OTP + U2F + CCID composite
MASK = 0x07 # Mask for mode bits
FLAG_EJECT = 0x80 # CCID device supports ejectYubiKey hardware model identification:
class PID:
YUBIKEY = 0x0010 # YubiKey (versions 1 and 2)
NEO_OTP = 0x0110 # YubiKey NEO - OTP only
NEO_OTP_CCID = 0x0111 # YubiKey NEO - OTP and CCID
NEO_CCID = 0x0112 # YubiKey NEO - CCID only
NEO_U2F = 0x0113 # YubiKey NEO - U2F only
NEO_OTP_U2F = 0x0114 # YubiKey NEO - OTP and U2F
NEO_U2F_CCID = 0x0115 # YubiKey NEO - U2F and CCID
NEO_OTP_U2F_CCID = 0x0116 # YubiKey NEO - OTP, U2F and CCID
YK4_OTP = 0x0401 # YubiKey 4 - OTP only
YK4_U2F = 0x0402 # YubiKey 4 - U2F only
YK4_OTP_U2F = 0x0403 # YubiKey 4 - OTP and U2F
YK4_CCID = 0x0404 # YubiKey 4 - CCID only
YK4_OTP_CCID = 0x0405 # YubiKey 4 - OTP and CCID
YK4_U2F_CCID = 0x0406 # YubiKey 4 - U2F and CCID
YK4_OTP_U2F_CCID = 0x0407 # YubiKey 4 - OTP, U2F and CCID