CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-python-yubico

Python library for communicating with Yubico YubiKey hardware authentication tokens

Pending
Overview
Eval results
Files

configuration.mddocs/

YubiKey Configuration

Comprehensive YubiKey configuration system supporting all operational modes including Yubico OTP, OATH-HOTP, and challenge-response with full control over device settings, flags, and security parameters.

Capabilities

Configuration Object Creation

Create and initialize YubiKey configuration objects with version compatibility checking.

class YubiKeyConfig:
    def __init__(self, ykver=None, capabilities=None, update=False, swap=False, zap=False):
        """
        Initialize YubiKey configuration object.
        
        Parameters:
        - ykver (tuple): YubiKey version tuple for compatibility checking
        - capabilities (YubiKeyCapabilities): Device capabilities object
        - update (bool): True for configuration update (preserves other slot)
        - swap (bool): True to swap configuration slots after writing
        - zap (bool): True to clear configuration slot
        """
    
    def version_required(self):
        """
        Get minimum YubiKey version required for this configuration.
        
        Returns:
        tuple: Minimum version tuple (major, minor, build)
        """

Basic configuration creation:

import yubico
from yubico.yubikey_config import YubiKeyConfig

yk = yubico.find_yubikey()

# Create new configuration
cfg = YubiKeyConfig()

# Or use device-specific initialization
cfg = yk.init_config()

# Check version requirements
min_version = cfg.version_required()
print(f"Minimum version required: {min_version}")

Yubico OTP Configuration

Configure YubiKey for standard Yubico OTP validation with Yubico's authentication servers.

def mode_yubikey_otp(self, private_uid, aes_key):
    """
    Configure YubiKey for Yubico OTP mode.
    
    Parameters:
    - private_uid (bytes): 6-byte private UID
    - aes_key (bytes): 16-byte AES key
    
    Raises:
    InputError: If parameters are invalid
    """

Yubico OTP configuration example:

import yubico
from yubico.yubikey_config import YubiKeyConfig
import os

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Generate random private UID and AES key
private_uid = os.urandom(6)
aes_key = os.urandom(16)

# Configure for Yubico OTP
cfg.mode_yubikey_otp(private_uid, aes_key)

# Write to slot 1
yk.write_config(cfg, slot=1)
print("Yubico OTP configured")

OATH-HOTP Configuration

Configure YubiKey for OATH-HOTP (RFC 4226) authentication.

def mode_oath_hotp(self, secret, digits=6, factor_seed=None, omp=0x0, tt=0x0, mui=''):
    """
    Configure YubiKey for OATH-HOTP mode.
    
    Parameters:
    - secret (bytes): HOTP secret key (up to 20 bytes)
    - digits (int): Number of digits in HOTP output (6 or 8)
    - factor_seed (int): Initial counter value
    - omp (int): Moving factor seed
    - tt (int): Truncation offset
    - mui (str): Management Unit Identifier
    
    Raises:
    InputError: If parameters are invalid
    """

OATH-HOTP configuration example:

import yubico
from yubico.yubikey_config import YubiKeyConfig
import base32

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Use standard base32-encoded secret
secret_b32 = "JBSWY3DPEHPK3PXP"
secret = base32.b32decode(secret_b32)

# Configure for OATH-HOTP with 6 digits
cfg.mode_oath_hotp(secret, digits=6, factor_seed=1)

# Write to slot 2
yk.write_config(cfg, slot=2)
print("OATH-HOTP configured")

Challenge-Response Configuration

Configure YubiKey for challenge-response authentication using HMAC-SHA1 or Yubico protocols.

def mode_challenge_response(self, secret, type='HMAC', variable=True, require_button=False):
    """
    Configure YubiKey for challenge-response mode.
    
    Parameters:
    - secret (bytes): Secret key (up to 20 bytes for HMAC, 16 bytes for Yubico)
    - type (str): Challenge type - 'HMAC' for HMAC-SHA1 or 'OTP' for Yubico
    - variable (bool): Variable length response (HMAC only)
    - require_button (bool): Require button press for challenge-response
    
    Raises:
    InputError: If parameters are invalid
    """

Challenge-response configuration example:

import yubico
from yubico.yubikey_config import YubiKeyConfig
import os

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Generate random secret for HMAC-SHA1
secret = os.urandom(20)

# Configure for HMAC challenge-response
cfg.mode_challenge_response(
    secret=secret,
    type='HMAC',
    variable=True,
    require_button=False
)

# Write to slot 1
yk.write_config(cfg, slot=1)
print("Challenge-response configured")

# Test the configuration
challenge = b"test challenge"
response = yk.challenge_response(challenge, slot=1)
print(f"Response: {response.hex()}")

Cryptographic Key Management

Set various cryptographic keys and access codes for YubiKey security.

def aes_key(self, data):
    """
    Set AES128 key for YubiKey operations.
    
    Parameters:
    - data (bytes): 16-byte AES key
    
    Raises:
    InputError: If key length is invalid
    """

def unlock_key(self, data):
    """
    Set access code required for re-programming this configuration.
    
    Parameters:
    - data (bytes): 6-byte access code
    """

def access_key(self, data):
    """
    Set new access code for future programming operations.
    
    Parameters:
    - data (bytes): 6-byte access code
    """

Key management example:

import yubico
from yubico.yubikey_config import YubiKeyConfig
import os

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Set AES key
aes_key = os.urandom(16)
cfg.aes_key(aes_key)

# Set access code for future programming
access_code = os.urandom(6)
cfg.access_key(access_code)

# Configure mode and write
cfg.mode_yubikey_otp(os.urandom(6), aes_key)
yk.write_config(cfg, slot=1)

Configuration Flags

Control YubiKey behavior through various configuration flags.

def ticket_flag(self, which, new=None):
    """
    Get or set ticket flags.
    
    Parameters:
    - which (str): Flag name (e.g., 'APPEND_CR', 'APPEND_TAB')
    - new (bool): New flag value, or None to query current value
    
    Returns:
    bool: Current flag value if new is None
    """

def config_flag(self, which, new=None):
    """
    Get or set configuration flags.
    
    Parameters:
    - which (str): Flag name (e.g., 'SEND_REF', 'TICKET_FIRST')
    - new (bool): New flag value, or None to query current value
    
    Returns:
    bool: Current flag value if new is None
    """

def extended_flag(self, which, new=None):
    """
    Get or set extended flags.
    
    Parameters:
    - which (str): Flag name (e.g., 'SERIAL_BTN_VISIBLE', 'SERIAL_USB_VISIBLE')
    - new (bool): New flag value, or None to query current value
    
    Returns:
    bool: Current flag value if new is None
    """

Configuration flags example:

import yubico
from yubico.yubikey_config import YubiKeyConfig

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Set ticket flags
cfg.ticket_flag('APPEND_CR', True)   # Append carriage return
cfg.ticket_flag('APPEND_TAB', False) # Don't append tab

# Set configuration flags  
cfg.config_flag('SEND_REF', True)    # Send reference string first
cfg.config_flag('TICKET_FIRST', False)

# Set extended flags
cfg.extended_flag('SERIAL_BTN_VISIBLE', True)  # Serial visible after button press
cfg.extended_flag('SERIAL_USB_VISIBLE', False) # Serial not visible via USB

# Query current flag values
cr_flag = cfg.ticket_flag('APPEND_CR')
print(f"APPEND_CR flag: {cr_flag}")

Token Identifier Configuration

Configure the fixed string (Token Identifier) portion of YubiKey output.

def fixed_string(self, data=None):
    """
    Get or set fixed string (Token Identifier).
    
    The fixed string is the first part of YubiKey OTP output and can be
    used to identify the specific YubiKey or user.
    
    Parameters:
    - data (bytes): Fixed string data (up to 16 bytes), or None to query
    
    Returns:
    bytes: Current fixed string if data is None
    """

Fixed string configuration example:

import yubico
from yubico.yubikey_config import YubiKeyConfig

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Set custom fixed string (Token Identifier)
token_id = b"mytoken001"
cfg.fixed_string(token_id)

# Configure Yubico OTP mode
cfg.mode_yubikey_otp(os.urandom(6), os.urandom(16))

# Write configuration
yk.write_config(cfg, slot=1)
print(f"Token ID set to: {token_id}")

Advanced Configuration Options

Enable advanced YubiKey features and modes.

def enable_extended_scan_code_mode(self):
    """
    Enable extended scan code mode.
    
    Allows YubiKey to output characters not available in basic scan code mode.
    """

def enable_shifted_1(self):
    """
    Enable shifted character 1 before output.
    
    Prepends shifted character 1 to YubiKey output.
    """

Advanced configuration example:

import yubico
from yubico.yubikey_config import YubiKeyConfig

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Enable advanced features
cfg.enable_extended_scan_code_mode()
cfg.enable_shifted_1()

# Configure and write
cfg.mode_yubikey_otp(os.urandom(6), os.urandom(16))
yk.write_config(cfg, slot=1)

Configuration Export

Export configuration objects as binary data or frames for transmission.

def to_string(self):
    """
    Export configuration as 64-byte binary string.
    
    Returns:
    bytes: 64-byte configuration data
    """

def to_frame(self, slot=1):
    """
    Export configuration as YubiKeyFrame object.
    
    Parameters:
    - slot (int): Target configuration slot
    
    Returns:
    YubiKeyFrame: Frame object ready for transmission
    """

Configuration export example:

import yubico
from yubico.yubikey_config import YubiKeyConfig

yk = yubico.find_yubikey()
cfg = yk.init_config()

# Configure YubiKey
cfg.mode_challenge_response(os.urandom(20))

# Export as binary data
config_data = cfg.to_string()
print(f"Configuration size: {len(config_data)} bytes")

# Export as frame
frame = cfg.to_frame(slot=1)
print(f"Frame command: {frame.command}")

Configuration Validation

The configuration system includes automatic validation and version compatibility checking:

import yubico
from yubico.yubikey_config import YubiKeyConfig, YubiKeyConfigError

try:
    yk = yubico.find_yubikey()
    cfg = yk.init_config()
    
    # Invalid configuration will raise error
    cfg.mode_oath_hotp(b"too_long_secret_key_data", digits=10)  # Invalid
    
except YubiKeyConfigError as e:
    print(f"Configuration error: {e.reason}")
except yubico.yubikey_base.YubiKeyVersionError as e:
    print(f"Version compatibility error: {e.reason}")

Install with Tessl CLI

npx tessl i tessl/pypi-python-yubico

docs

challenge-response.md

configuration.md

device-discovery.md

device-interface.md

exceptions.md

index.md

utilities.md

tile.json