keycard.commands package¶
Submodules¶
keycard.commands.change_secret module¶
- keycard.commands.change_secret.change_secret(card, new_value, pin_type)¶
Changes the specified secret (PIN, PUK, PAIRING) or secret on the card.
- Return type:
None
- Preconditions:
Secure Channel must be opened
User PIN must be verified
keycard.commands.derive_key module¶
- keycard.commands.derive_key.derive_key(card, path='')¶
Set the derivation path for subsequent SIGN and EXPORT KEY commands.
- Return type:
None- Parameters:
card (CardInterface) – The card interface.
path (str) – BIP-32-style path (e.g., “m/44’/60’/0’/0/0”) or “../0/1” (parent) or “./0” (current).
- Raises:
APDUError – if the derivation fails or the format is invalid.
keycard.commands.ecdh module¶
- keycard.commands.ecdh.ecdh(card, public_key, path)¶
Computes an ECDH shared secret with the key at a path (applet 4.0).
The result is the raw X coordinate of the shared point, not an encryption key; run it through the protocol’s own KDF.
- Return type:
bytes- Parameters:
card – The card interface.
public_key (bytes) – The peer’s uncompressed public key, 65 bytes.
path (str) – Derivation path under “m/44’/1237’” (NIP-44) or “m/43’/60’/1581’” (EIP-1581), at least 5 levels deep. The card rejects any other path.
- Returns:
The 32-byte X coordinate of the shared point.
- Return type:
bytes
- Raises:
ValueError – If the public key is not 65 bytes starting with 0x04, or the path does not start at the master key.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
keycard.commands.export_bip85 module¶
- keycard.commands.export_bip85.export_bip85(card, path, length)¶
Exports BIP-85 entropy derived from the loaded key (applet 4.0).
- Return type:
bytes- Parameters:
card – The card interface.
path (str) – Derivation path starting with “m/83696968’”, every component hardened, e.g. “m/83696968’/0’/0’”. The card rejects any other path.
length (int) – Number of entropy bytes, 1 to 64.
- Returns:
The first length bytes of the BIP-85 entropy.
- Return type:
bytes
- Raises:
ValueError – If the length is out of range or the path does not start at the master key.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
keycard.commands.export_key module¶
- keycard.commands.export_key.export_key(card, derivation_option, public_only, keypath=None, make_current=False, source=DerivationSource.MASTER)¶
Export a key (public or private) from the card using an optional keypath.
If derivation_option == CURRENT, keypath can be omitted or empty.
- Return type:
- Parameters:
card – The card object
derivation_option – e.g. DERIVE, CURRENT, DERIVE_AND_MAKE_CURRENT
public_only – If True, export only public key
keypath – BIP32-style string or packed bytes, or None if CURRENT
make_current – Whether to update the card’s current path
source – MASTER (0x00), PARENT (0x40), CURRENT (0x80)
- Returns:
dict with optional ‘public_key’, ‘private_key’, ‘chain_code’
keycard.commands.export_lee module¶
- keycard.commands.export_lee.export_lee(card, path='m')¶
Exports the LEE keys at a path (applet 4.0).
The card must be in LEE mode, entered by loading a seed with LoadKeyType.LEE_SEED.
- Return type:
- Parameters:
card – The card interface.
path (str) – Derivation path from the master key, e.g. “m/44’/60’”. “m” exports the master keys.
- Returns:
ASK, NSK, VSK_D and VSK_Z, 32 bytes each.
- Return type:
- Raises:
ValueError – If the path does not start at the master key.
InvalidResponseError – If a key is missing or not 32 bytes.
APDUError – If the card returns a failure status word.
keycard.commands.factory_reset module¶
- keycard.commands.factory_reset.factory_reset(card)¶
Sends the FACTORY_RESET command to the card.
- Return type:
None
keycard.commands.generate_key module¶
- keycard.commands.generate_key.generate_key(card)¶
Generates a new key on the card and returns the key UID.
- Return type:
bytes
- Preconditions:
Secure Channel must be opened
PIN must be verified
- Parameters:
transport – Transport instance for APDU communication
session – SecureChannel instance for wrapping/unwrapping
- Returns:
Key UID (SHA-256 of the public key)
- Return type:
bytes
- Raises:
APDUError – If the response status word is not 0x9000
keycard.commands.generate_mnemonic module¶
- keycard.commands.generate_mnemonic.generate_mnemonic(card, checksum_size=6)¶
Generate a BIP39 mnemonic using the card’s RNG.
- Return type:
list[int]- Parameters:
card (CardInterface) – The card interface.
checksum_size (int) – Number of checksum bits (between 4 and 8 inclusive).
- Returns:
- List of integers (0-2047) corresponding to wordlist
indexes.
- Return type:
List[int]
- Raises:
ValueError – If checksum size is outside the allowed range.
APDUError – If the card rejects the request.
keycard.commands.get_challenge module¶
- keycard.commands.get_challenge.get_challenge(card, length)¶
Gets random bytes generated by the card.
Applet 4.0 answers only inside the secure channel, also before INIT. Earlier applets that support the command answer with or without one; without a channel the command is sent in plain.
- Return type:
bytes- Parameters:
card – The card interface.
length (int) – Number of bytes, 1 to 255. The card limits it further: 245 bytes over Secure Channel V2, 221 over V1.
- Returns:
The random bytes.
- Return type:
bytes
- Raises:
ValueError – If the length does not fit in P1.
InvalidStateError – If a Secure Channel V2 card has no open channel.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
keycard.commands.get_data module¶
- keycard.commands.get_data.get_data(card, slot=StorageSlot.PUBLIC)¶
Gets the data on the card previously stored with the store data command in the specified slot.
If the secure channel is open, it uses the secure APDU command. Otherwise, it uses the proprietary APDU command.
NDEF data is the complete NDEF file, starting with its 2-byte length. From applet 4.0 it is read in segments until the whole file is received; earlier applets return at most the first 223 bytes.
- Return type:
bytes- Parameters:
card – The card session object.
slot (StorageSlot) – Where to retrieve the data from (PUBLIC, NDEF, CASH)
- Raises:
InvalidResponseError – If segmented NDEF data is malformed.
keycard.commands.get_status module¶
- keycard.commands.get_status.get_status(card, key_path=False)¶
Query the application status or key path from the Keycard.
Requires an open Secure Channel.
- Return type:
dict[str,int|bool] |list[int]- Parameters:
transport – Transport instance used to send APDU bytes.
session – An established SecureChannel instance.
key_path (bool) – If True, returns the current key path. If False (default), returns application status.
- Returns:
- dict with keys:
pin_retry_count (int)
puk_retry_count (int)
initialized (bool)
- If key_path is True:
List of 32-bit integers representing the current key path.
- Return type:
If key_path is False
- Raises:
APDUError – If the response status word is not 0x9000.
ValueError – If the application status template (tag 0xA3) is missing.
keycard.commands.ident module¶
- keycard.commands.ident.ident(card, challenge)¶
Sends a challenge to the card to receive a signed identity response.
- Return type:
bytes- Parameters:
transport – An instance of the Transport class to communicate with the card.
challenge (bytes) – A challenge (nonce or data) to send to the card. If None, a random 32-byte challenge is generated.
- Returns:
The public key extracted from the card’s identity response.
- Return type:
bytes
- Raises:
APDUError – If the response status word is not successful (0x9000).
keycard.commands.init module¶
- keycard.commands.init.init(card, pin, puk, pairing_secret=None, pin_retries=None, puk_retries=None, alt_pin=None)¶
Initializes the card the way its secure channel version requires.
Secure Channel V1 (3.x) cards need the pairing secret and receive the credentials encrypted once to the card’s public key. Secure Channel V2 (4.x) cards take no pairing secret and receive INIT inside the secure channel, which is opened if needed and stays open.
- Return type:
None- Parameters:
card – The card interface.
pin – The 6-digit PIN.
puk – The 12-digit PUK.
pairing_secret – A 32-byte secret or a passphrase (V1 only).
pin_retries – PIN attempts, 2 to 10 (default 3).
puk_retries – PUK attempts, 3 to 12 (default 5).
alt_pin – Optional 6-digit Alternate PIN.
- Raises:
ValueError – If the pairing secret is missing on V1, given on V2, or a parameter is out of range.
APDUError – If the card returns a failure status word.
keycard.commands.load_key module¶
- keycard.commands.load_key.load_key(card, key_type, public_key=None, private_key=None, chain_code=None, bip39_seed=None)¶
Load a key into the card for signing purposes.
- Return type:
bytes- Parameters:
card – The card interface.
key_type – Key type
public_key – Optional ECC public key (tag 0x80).
private_key – ECC private key (tag 0x81).
chain_code – Optional chain code (tag 0x82, only for extended key).
bip39_seed – 16 to 64-byte binary seed (only for key_type BIP39_SEED, or LEE_SEED to also derive the LEE keys on applet 4.0).
- Returns:
UID of the loaded key (SHA-256 of public key).
keycard.commands.mutually_authenticate module¶
- keycard.commands.mutually_authenticate.mutually_authenticate(card, client_challenge=None)¶
Performs mutual authentication between the client and the Keycard.
- Return type:
None
- Preconditions:
Secure Channel must be opened
The card will respond with a cryptographic challenge. The secure session will verify the response. If the response is not exactly 32 bytes, or if the response has an unexpected status word, the function raises an error.
- Parameters:
transport – A Transport instance for sending APDUs.
session – A SecureChannel instance used for wrapping/unwrapping.
client_challenge (bytes, optional) – Optional challenge bytes. If not provided, a random 32-byte value will be generated.
- Raises:
APDUError – If the response status word is not 0x9000.
ValueError – If the decrypted response is not exactly 32 bytes.
keycard.commands.open_secure_channel module¶
- keycard.commands.open_secure_channel.open_secure_channel(card)¶
Opens a secure channel with the selected card, using the channel version its applet supports.
Secure Channel V1 (3.x) uses the card’s pairing and runs MUTUALLY AUTHENTICATE. Secure Channel V2 (4.x) first checks the card’s Identity Certificate against the trusted Keycard CAs.
- Return type:
- Parameters:
card – The card interface.
- Returns:
The open channel.
- Return type:
- Raises:
InvalidStateError – If a V1 card has no pairing or is not initialized.
UntrustedCardError – If a V2 card is not trusted.
InvalidResponseError – If the handshake does not verify.
APDUError – If the card returns a failure status word.
keycard.commands.pair module¶
- keycard.commands.pair.pair(card, shared_secret, pairing_mode=PairingMode.ANY)¶
Performs an ECDH-based pairing handshake with the card.
- Return type:
tuple[int,bytes]- Parameters:
card – The keycard interface.
shared_secret – A 32-byte secret or a passphrase convertible to one.
pairing_mode – Mode for pairing: ANY, EPHEMERAL, PERSISTENT
- Returns:
Pairing index and derived 32-byte pairing key.
- Return type:
tuple[int, bytes]
- Raises:
ValueError – If the shared secret is not 32 bytes.
APDUError – If the card returns a non-success status word.
InvalidResponseError – If response lengths or values are unexpected.
keycard.commands.remove_key module¶
- keycard.commands.remove_key.remove_key(card)¶
Removes the key from the card, returning it to an uninitialized state.
- Return type:
None
keycard.commands.select module¶
- keycard.commands.select.select(card)¶
Selects the Keycard application on the smart card and retrieves application information.
Sends a SELECT APDU command using the Keycard AID, checks for a successful response, parses the returned application information, and returns it.
- Return type:
- Parameters:
transport – The transport instance used to send the APDU command.
- Returns:
- Parsed information about the selected Keycard
application.
- Return type:
- Raises:
APDUError – If the card returns a status word indicating failure.
keycard.commands.set_pinless_path module¶
- keycard.commands.set_pinless_path.set_pinless_path(card, path)¶
Set a PIN-less path on the card. Allows signing without PIN/auth if the current derived key matches this path.
- Return type:
None- Parameters:
card (CardInterface) – The card interface.
path (str) – BIP-32-style path (e.g., “m/44’/60’/0’/0/0”). An empty string disables the pinless path.
- Raises:
APDUError – if the card rejects the input (invalid path)
keycard.commands.sign module¶
- keycard.commands.sign.sign(card, digest, p1=DerivationOption.CURRENT, p2=SigningAlgorithm.ECDSA_SECP256K1, derivation_path=None, tweak=None)¶
Sign a 32-byte digest using the specified key and signing algorithm.
This command sends the SIGN APDU to the Keycard and parses the response, returning a structured SignatureResult object. The signature may be returned as a DER-encoded structure, a raw 65-byte format including the recovery ID, or an ECDSA template depending on card behavior. Schnorr signatures are 64 bytes, R.x || s, with no recovery ID.
- Return type:
- Preconditions:
Secure Channel must be opened (unless using PINLESS)
PIN must be verified (unless using PINLESS)
A valid keypair must be loaded on the card
If P1=PINLESS, a PIN-less path must be configured
- Parameters:
card (CardInterface) – Active Keycard transport session.
digest (bytes) – 32-byte hash to be signed.
p1 (DerivationOption) –
Key derivation option. One of: - CURRENT: Sign with the currently loaded key; on applet 4.0,
which has no current key, with the master key
DERIVE: Derive key for signing without changing current
DERIVE_AND_MAKE_CURRENT: Derive and load for future use
PINLESS: Use pre-defined PIN-less key without SC/PIN
Applet 4.0 accepts only CURRENT and DERIVE from the master key.
p2 (SigningAlgorithm) – Signing algorithm. Defaults to ECDSA_SECP256K1. Applet 4.0 also supports SCHNORR_BIP340.
derivation_path (Optional[str]) – String-formatted BIP32 path (e.g. “m/44’/60’/0’/0/0”). Required if p1 uses derivation; “m” is the master key. The source (master/parent/current) is inferred from the path prefix.
tweak (Optional[bytes]) – 32 bytes the card adds to the private key before a Schnorr signature, e.g. a Taproot tweak. Defaults to zeros, an untweaked BIP-340 signature. The returned public key is the untweaked one.
- Returns:
Parsed signature result, including the signature (DER or raw), algorithm, and optional recovery ID or public key.
- Return type:
- Raises:
ValueError – If the digest or tweak is not 32 bytes, a tweak is given for ECDSA, or the path is invalid.
InvalidStateError – If preconditions (PIN, SC) are not met.
APDUError – If the card returns an error (e.g., SW=0x6985).
keycard.commands.store_data module¶
- keycard.commands.store_data.store_data(card, data, slot=StorageSlot.PUBLIC)¶
Stores data on the card in the specified slot.
NDEF data is the complete NDEF file, starting with its 2-byte length. From applet 3.2 it can be up to 512 bytes and is sent in chunks.
- Return type:
None- Parameters:
card – The card session object.
data (bytes) – The data to store (max 127 bytes, or 512 bytes for NDEF from applet 3.2).
slot (StorageSlot) – Where to store the data (PUBLIC, NDEF, CASH)
- Raises:
ValueError – If the data is too long.
keycard.commands.unblock_pin module¶
- keycard.commands.unblock_pin.unblock_pin(card, puk_and_pin)¶
Unblocks the user PIN using the provided PUK and sets a new PIN.
- Return type:
None- Parameters:
card – The card session object.
puk_and_pin (bytes | str) – Concatenation of PUK (12 digits) + new PIN (6 digits)
- Raises:
ValueError – If the format is invalid.
APDUError – If the card returns an error.
keycard.commands.unpair module¶
- keycard.commands.unpair.unpair(card, index)¶
Sends the UNPAIR command to remove a pairing index from the card.
- Return type:
None
- Preconditions:
Secure Channel must be opened
PIN must be verified
This function securely communicates with the card using the established session to instruct it to forget a specific pairing index.
- Parameters:
transport – The transport interface used to send APDUs.
secure_session – The active SecureChannel object used to wrap APDUs.
index (int) – The pairing index (0–15) to unpair from the card.
- Raises:
ValueError – If transport or secure_session is not provided, or if the session is not authenticated.
APDUError – If the response status word indicates an error.
keycard.commands.verify_pin module¶
- keycard.commands.verify_pin.verify_pin(card, pin)¶
Verifies the user PIN with the card using a secure session.
- Return type:
bool
- Preconditions:
Secure Channel must be opened
PIN must be verified
Sends the VERIFY PIN APDU command through the secure session. Returns True if the PIN is correct, False if incorrect with remaining attempts, and raises an error if blocked or another APDU error occurs.
- Parameters:
transport – The transport instance used to send the command.
session – An established SecureChannel object.
pin (str) – The PIN string to be verified.
- Returns:
True if the PIN is correct, False if incorrect but still allowed.
- Return type:
bool
- Raises:
ValueError – If no secure session is provided.
RuntimeError – If the PIN is blocked (no attempts remaining).
APDUError – For other status word errors returned by the card.
Module contents¶
- keycard.commands.change_secret(card, new_value, pin_type)¶
Changes the specified secret (PIN, PUK, PAIRING) or secret on the card.
- Return type:
None
- Preconditions:
Secure Channel must be opened
User PIN must be verified
- keycard.commands.derive_key(card, path='')¶
Set the derivation path for subsequent SIGN and EXPORT KEY commands.
- Return type:
None- Parameters:
card (CardInterface) – The card interface.
path (str) – BIP-32-style path (e.g., “m/44’/60’/0’/0/0”) or “../0/1” (parent) or “./0” (current).
- Raises:
APDUError – if the derivation fails or the format is invalid.
- keycard.commands.ecdh(card, public_key, path)¶
Computes an ECDH shared secret with the key at a path (applet 4.0).
The result is the raw X coordinate of the shared point, not an encryption key; run it through the protocol’s own KDF.
- Return type:
bytes- Parameters:
card – The card interface.
public_key (bytes) – The peer’s uncompressed public key, 65 bytes.
path (str) – Derivation path under “m/44’/1237’” (NIP-44) or “m/43’/60’/1581’” (EIP-1581), at least 5 levels deep. The card rejects any other path.
- Returns:
The 32-byte X coordinate of the shared point.
- Return type:
bytes
- Raises:
ValueError – If the public key is not 65 bytes starting with 0x04, or the path does not start at the master key.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
- keycard.commands.export_bip85(card, path, length)¶
Exports BIP-85 entropy derived from the loaded key (applet 4.0).
- Return type:
bytes- Parameters:
card – The card interface.
path (str) – Derivation path starting with “m/83696968’”, every component hardened, e.g. “m/83696968’/0’/0’”. The card rejects any other path.
length (int) – Number of entropy bytes, 1 to 64.
- Returns:
The first length bytes of the BIP-85 entropy.
- Return type:
bytes
- Raises:
ValueError – If the length is out of range or the path does not start at the master key.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
- keycard.commands.export_key(card, derivation_option, public_only, keypath=None, make_current=False, source=DerivationSource.MASTER)¶
Export a key (public or private) from the card using an optional keypath.
If derivation_option == CURRENT, keypath can be omitted or empty.
- Return type:
- Parameters:
card – The card object
derivation_option – e.g. DERIVE, CURRENT, DERIVE_AND_MAKE_CURRENT
public_only – If True, export only public key
keypath – BIP32-style string or packed bytes, or None if CURRENT
make_current – Whether to update the card’s current path
source – MASTER (0x00), PARENT (0x40), CURRENT (0x80)
- Returns:
dict with optional ‘public_key’, ‘private_key’, ‘chain_code’
- keycard.commands.export_lee(card, path='m')¶
Exports the LEE keys at a path (applet 4.0).
The card must be in LEE mode, entered by loading a seed with LoadKeyType.LEE_SEED.
- Return type:
- Parameters:
card – The card interface.
path (str) – Derivation path from the master key, e.g. “m/44’/60’”. “m” exports the master keys.
- Returns:
ASK, NSK, VSK_D and VSK_Z, 32 bytes each.
- Return type:
- Raises:
ValueError – If the path does not start at the master key.
InvalidResponseError – If a key is missing or not 32 bytes.
APDUError – If the card returns a failure status word.
- keycard.commands.factory_reset(card)¶
Sends the FACTORY_RESET command to the card.
- Return type:
None
- keycard.commands.generate_key(card)¶
Generates a new key on the card and returns the key UID.
- Return type:
bytes
- Preconditions:
Secure Channel must be opened
PIN must be verified
- Parameters:
transport – Transport instance for APDU communication
session – SecureChannel instance for wrapping/unwrapping
- Returns:
Key UID (SHA-256 of the public key)
- Return type:
bytes
- Raises:
APDUError – If the response status word is not 0x9000
- keycard.commands.generate_mnemonic(card, checksum_size=6)¶
Generate a BIP39 mnemonic using the card’s RNG.
- Return type:
list[int]- Parameters:
card (CardInterface) – The card interface.
checksum_size (int) – Number of checksum bits (between 4 and 8 inclusive).
- Returns:
- List of integers (0-2047) corresponding to wordlist
indexes.
- Return type:
List[int]
- Raises:
ValueError – If checksum size is outside the allowed range.
APDUError – If the card rejects the request.
- keycard.commands.get_challenge(card, length)¶
Gets random bytes generated by the card.
Applet 4.0 answers only inside the secure channel, also before INIT. Earlier applets that support the command answer with or without one; without a channel the command is sent in plain.
- Return type:
bytes- Parameters:
card – The card interface.
length (int) – Number of bytes, 1 to 255. The card limits it further: 245 bytes over Secure Channel V2, 221 over V1.
- Returns:
The random bytes.
- Return type:
bytes
- Raises:
ValueError – If the length does not fit in P1.
InvalidStateError – If a Secure Channel V2 card has no open channel.
InvalidResponseError – If the card returns a different length.
APDUError – If the card returns a failure status word.
- keycard.commands.get_data(card, slot=StorageSlot.PUBLIC)¶
Gets the data on the card previously stored with the store data command in the specified slot.
If the secure channel is open, it uses the secure APDU command. Otherwise, it uses the proprietary APDU command.
NDEF data is the complete NDEF file, starting with its 2-byte length. From applet 4.0 it is read in segments until the whole file is received; earlier applets return at most the first 223 bytes.
- Return type:
bytes- Parameters:
card – The card session object.
slot (StorageSlot) – Where to retrieve the data from (PUBLIC, NDEF, CASH)
- Raises:
InvalidResponseError – If segmented NDEF data is malformed.
- keycard.commands.get_status(card, key_path=False)¶
Query the application status or key path from the Keycard.
Requires an open Secure Channel.
- Return type:
dict[str,int|bool] |list[int]- Parameters:
transport – Transport instance used to send APDU bytes.
session – An established SecureChannel instance.
key_path (bool) – If True, returns the current key path. If False (default), returns application status.
- Returns:
- dict with keys:
pin_retry_count (int)
puk_retry_count (int)
initialized (bool)
- If key_path is True:
List of 32-bit integers representing the current key path.
- Return type:
If key_path is False
- Raises:
APDUError – If the response status word is not 0x9000.
ValueError – If the application status template (tag 0xA3) is missing.
- keycard.commands.ident(card, challenge)¶
Sends a challenge to the card to receive a signed identity response.
- Return type:
bytes- Parameters:
transport – An instance of the Transport class to communicate with the card.
challenge (bytes) – A challenge (nonce or data) to send to the card. If None, a random 32-byte challenge is generated.
- Returns:
The public key extracted from the card’s identity response.
- Return type:
bytes
- Raises:
APDUError – If the response status word is not successful (0x9000).
- keycard.commands.init(card, pin, puk, pairing_secret=None, pin_retries=None, puk_retries=None, alt_pin=None)¶
Initializes the card the way its secure channel version requires.
Secure Channel V1 (3.x) cards need the pairing secret and receive the credentials encrypted once to the card’s public key. Secure Channel V2 (4.x) cards take no pairing secret and receive INIT inside the secure channel, which is opened if needed and stays open.
- Return type:
None- Parameters:
card – The card interface.
pin – The 6-digit PIN.
puk – The 12-digit PUK.
pairing_secret – A 32-byte secret or a passphrase (V1 only).
pin_retries – PIN attempts, 2 to 10 (default 3).
puk_retries – PUK attempts, 3 to 12 (default 5).
alt_pin – Optional 6-digit Alternate PIN.
- Raises:
ValueError – If the pairing secret is missing on V1, given on V2, or a parameter is out of range.
APDUError – If the card returns a failure status word.
- keycard.commands.load_key(card, key_type, public_key=None, private_key=None, chain_code=None, bip39_seed=None)¶
Load a key into the card for signing purposes.
- Return type:
bytes- Parameters:
card – The card interface.
key_type – Key type
public_key – Optional ECC public key (tag 0x80).
private_key – ECC private key (tag 0x81).
chain_code – Optional chain code (tag 0x82, only for extended key).
bip39_seed – 16 to 64-byte binary seed (only for key_type BIP39_SEED, or LEE_SEED to also derive the LEE keys on applet 4.0).
- Returns:
UID of the loaded key (SHA-256 of public key).
- keycard.commands.mutually_authenticate(card, client_challenge=None)¶
Performs mutual authentication between the client and the Keycard.
- Return type:
None
- Preconditions:
Secure Channel must be opened
The card will respond with a cryptographic challenge. The secure session will verify the response. If the response is not exactly 32 bytes, or if the response has an unexpected status word, the function raises an error.
- Parameters:
transport – A Transport instance for sending APDUs.
session – A SecureChannel instance used for wrapping/unwrapping.
client_challenge (bytes, optional) – Optional challenge bytes. If not provided, a random 32-byte value will be generated.
- Raises:
APDUError – If the response status word is not 0x9000.
ValueError – If the decrypted response is not exactly 32 bytes.
- keycard.commands.open_secure_channel(card)¶
Opens a secure channel with the selected card, using the channel version its applet supports.
Secure Channel V1 (3.x) uses the card’s pairing and runs MUTUALLY AUTHENTICATE. Secure Channel V2 (4.x) first checks the card’s Identity Certificate against the trusted Keycard CAs.
- Return type:
- Parameters:
card – The card interface.
- Returns:
The open channel.
- Return type:
- Raises:
InvalidStateError – If a V1 card has no pairing or is not initialized.
UntrustedCardError – If a V2 card is not trusted.
InvalidResponseError – If the handshake does not verify.
APDUError – If the card returns a failure status word.
- keycard.commands.pair(card, shared_secret, pairing_mode=PairingMode.ANY)¶
Performs an ECDH-based pairing handshake with the card.
- Return type:
tuple[int,bytes]- Parameters:
card – The keycard interface.
shared_secret – A 32-byte secret or a passphrase convertible to one.
pairing_mode – Mode for pairing: ANY, EPHEMERAL, PERSISTENT
- Returns:
Pairing index and derived 32-byte pairing key.
- Return type:
tuple[int, bytes]
- Raises:
ValueError – If the shared secret is not 32 bytes.
APDUError – If the card returns a non-success status word.
InvalidResponseError – If response lengths or values are unexpected.
- keycard.commands.remove_key(card)¶
Removes the key from the card, returning it to an uninitialized state.
- Return type:
None
- keycard.commands.select(card)¶
Selects the Keycard application on the smart card and retrieves application information.
Sends a SELECT APDU command using the Keycard AID, checks for a successful response, parses the returned application information, and returns it.
- Return type:
- Parameters:
transport – The transport instance used to send the APDU command.
- Returns:
- Parsed information about the selected Keycard
application.
- Return type:
- Raises:
APDUError – If the card returns a status word indicating failure.
- keycard.commands.set_pinless_path(card, path)¶
Set a PIN-less path on the card. Allows signing without PIN/auth if the current derived key matches this path.
- Return type:
None- Parameters:
card (CardInterface) – The card interface.
path (str) – BIP-32-style path (e.g., “m/44’/60’/0’/0/0”). An empty string disables the pinless path.
- Raises:
APDUError – if the card rejects the input (invalid path)
- keycard.commands.sign(card, digest, p1=DerivationOption.CURRENT, p2=SigningAlgorithm.ECDSA_SECP256K1, derivation_path=None, tweak=None)¶
Sign a 32-byte digest using the specified key and signing algorithm.
This command sends the SIGN APDU to the Keycard and parses the response, returning a structured SignatureResult object. The signature may be returned as a DER-encoded structure, a raw 65-byte format including the recovery ID, or an ECDSA template depending on card behavior. Schnorr signatures are 64 bytes, R.x || s, with no recovery ID.
- Return type:
- Preconditions:
Secure Channel must be opened (unless using PINLESS)
PIN must be verified (unless using PINLESS)
A valid keypair must be loaded on the card
If P1=PINLESS, a PIN-less path must be configured
- Parameters:
card (CardInterface) – Active Keycard transport session.
digest (bytes) – 32-byte hash to be signed.
p1 (DerivationOption) –
Key derivation option. One of: - CURRENT: Sign with the currently loaded key; on applet 4.0,
which has no current key, with the master key
DERIVE: Derive key for signing without changing current
DERIVE_AND_MAKE_CURRENT: Derive and load for future use
PINLESS: Use pre-defined PIN-less key without SC/PIN
Applet 4.0 accepts only CURRENT and DERIVE from the master key.
p2 (SigningAlgorithm) – Signing algorithm. Defaults to ECDSA_SECP256K1. Applet 4.0 also supports SCHNORR_BIP340.
derivation_path (Optional[str]) – String-formatted BIP32 path (e.g. “m/44’/60’/0’/0/0”). Required if p1 uses derivation; “m” is the master key. The source (master/parent/current) is inferred from the path prefix.
tweak (Optional[bytes]) – 32 bytes the card adds to the private key before a Schnorr signature, e.g. a Taproot tweak. Defaults to zeros, an untweaked BIP-340 signature. The returned public key is the untweaked one.
- Returns:
Parsed signature result, including the signature (DER or raw), algorithm, and optional recovery ID or public key.
- Return type:
- Raises:
ValueError – If the digest or tweak is not 32 bytes, a tweak is given for ECDSA, or the path is invalid.
InvalidStateError – If preconditions (PIN, SC) are not met.
APDUError – If the card returns an error (e.g., SW=0x6985).
- keycard.commands.store_data(card, data, slot=StorageSlot.PUBLIC)¶
Stores data on the card in the specified slot.
NDEF data is the complete NDEF file, starting with its 2-byte length. From applet 3.2 it can be up to 512 bytes and is sent in chunks.
- Return type:
None- Parameters:
card – The card session object.
data (bytes) – The data to store (max 127 bytes, or 512 bytes for NDEF from applet 3.2).
slot (StorageSlot) – Where to store the data (PUBLIC, NDEF, CASH)
- Raises:
ValueError – If the data is too long.
- keycard.commands.unblock_pin(card, puk_and_pin)¶
Unblocks the user PIN using the provided PUK and sets a new PIN.
- Return type:
None- Parameters:
card – The card session object.
puk_and_pin (bytes | str) – Concatenation of PUK (12 digits) + new PIN (6 digits)
- Raises:
ValueError – If the format is invalid.
APDUError – If the card returns an error.
- keycard.commands.unpair(card, index)¶
Sends the UNPAIR command to remove a pairing index from the card.
- Return type:
None
- Preconditions:
Secure Channel must be opened
PIN must be verified
This function securely communicates with the card using the established session to instruct it to forget a specific pairing index.
- Parameters:
transport – The transport interface used to send APDUs.
secure_session – The active SecureChannel object used to wrap APDUs.
index (int) – The pairing index (0–15) to unpair from the card.
- Raises:
ValueError – If transport or secure_session is not provided, or if the session is not authenticated.
APDUError – If the response status word indicates an error.
- keycard.commands.verify_pin(card, pin)¶
Verifies the user PIN with the card using a secure session.
- Return type:
bool
- Preconditions:
Secure Channel must be opened
PIN must be verified
Sends the VERIFY PIN APDU command through the secure session. Returns True if the PIN is correct, False if incorrect with remaining attempts, and raises an error if blocked or another APDU error occurs.
- Parameters:
transport – The transport instance used to send the command.
session – An established SecureChannel object.
pin (str) – The PIN string to be verified.
- Returns:
True if the PIN is correct, False if incorrect but still allowed.
- Return type:
bool
- Raises:
ValueError – If no secure session is provided.
RuntimeError – If the PIN is blocked (no attempts remaining).
APDUError – For other status word errors returned by the card.