keycard.commands package¶
Submodules¶
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)¶
Initializes a Keycard device with PIN, PUK, and pairing secret.
Establishes an ephemeral ECDH key exchange and sends encrypted credentials to the card.
- Return type:
None
- Parameters:
transport – The transport used to send APDU commands to the card.
card_public_key (bytes) – The card’s ECC public key, usually retrieved via select().
pin (bytes) – The personal identification number (PIN) as bytes.
puk (bytes) – The personal unblocking key (PUK) as bytes.
pairing_secret (bytes) – A 32-byte shared secret or a passphrase that will be converted into one.
- Raises:
NotSelectedError – If no card public key is provided.
ValueError – If the encrypted data exceeds a single APDU length.
APDUError – If the card returns a failure status word.
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, pairing_index, pairing_key)¶
Opens a secure session with the Keycard using ECDH and a pairing key.
This function performs an ephemeral ECDH key exchange with the card, sends the ephemeral public key, and receives cryptographic material from the card to derive a secure session.
- Return type:
- Parameters:
transport – The transport used to communicate with the card.
card_public_key (bytes) – The ECC public key of the card, retrieved via select().
pairing_index (int) – The index of the previously established pairing slot.
pairing_key (bytes) – The shared 32-byte pairing key.
- Returns:
A newly established secure session with the card.
- Return type:
- Raises:
NotSelectedError – If no card public key is provided.
APDUError – If the card returns a failure status word.
keycard.commands.pair module¶
- keycard.commands.pair.pair(card, shared_secret)¶
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.
- 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.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.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¶
- exception keycard.commands.APDUError(sw)¶
Bases:
KeyCardError
Raised when APDU returns non-success status word.
- class keycard.commands.ApplicationInfo(capabilities, ecc_public_key, instance_uid, key_uid, version_major, version_minor)¶
Bases:
object
Represents parsed application information from a TLV-encoded response.
- capabilities¶
Parsed capabilities value, if present.
- Type:
Optional[int]
- ecc_public_key¶
ECC public key bytes, if present.
- Type:
Optional[bytes]
- instance_uid¶
Unique identifier for the application instance, if present.
- Type:
Optional[bytes]
- key_uid¶
Unique identifier for the key, if present.
- Type:
Optional[bytes]
- version_major¶
Major version number of the application.
- Type:
int
- version_minor¶
Minor version number of the application.
- Type:
int
-
capabilities:
Optional
[int
]¶
-
ecc_public_key:
Optional
[bytes
]¶
-
instance_uid:
Optional
[bytes
]¶
- property is_initialized: bool¶
Checks if the application is initialized based on the presence of the key_uid.
- Returns:
True if the key_uid is present, False otherwise.
- Return type:
bool
-
key_uid:
Optional
[bytes
]¶
- static parse(data)¶
Parses a byte sequence containing TLV-encoded application information and returns an ApplicationInfo instance.
- Return type:
- Parameters:
data (bytes) – The TLV-encoded response data to parse.
- Returns:
- An instance populated with the parsed application
information fields.
- Return type:
- The function extracts the following fields from the TLV data:
version_major (int): Major version number (from tag 0x02).
version_minor (int): Minor version number (from tag 0x02).
instance_uid (bytes or None): Instance UID (from tag 0x8F).
key_uid (bytes or None): Key UID (from tag 0x8E).
ecc_public_key (bytes or None): ECC public key (from tag 0x80).
- capabilities (Capabilities or None): Capabilities object
(from tag 0x8D).
- Raises:
Any exceptions raised by ApplicationInfo._parse_response or –
Capabilities.parse. –
-
version_major:
int
¶
-
version_minor:
int
¶
- class keycard.commands.CardInterface(*args, **kwargs)¶
Bases:
Protocol
Abstract base class representing a Keycard interface for command functions.
-
card_public_key:
Optional
[bytes
]¶
- property is_initialized: bool¶
- property is_pin_verified: bool¶
- property is_secure_channel_open: bool¶
- property is_selected: bool¶
- send_apdu(ins, p1=0, p2=0, data=b'', cla=None)¶
- Return type:
bytes
- send_secure_apdu(ins, p1=0, p2=0, data=b'')¶
- Return type:
bytes
-
card_public_key:
- class keycard.commands.DerivationOption(*values)¶
Bases:
IntEnum
- CURRENT = 0¶
- DERIVE = 1¶
- DERIVE_AND_MAKE_CURRENT = 2¶
- PINLESS = 3¶
- class keycard.commands.DerivationSource(*values)¶
Bases:
IntEnum
- CURRENT = 128¶
- MASTER = 0¶
- PARENT = 64¶
- class keycard.commands.ECDH(curve=None, private_key=None, public_key=None)¶
Bases:
object
Elliptic-curve Diffie-Hellman (ECDH). A key agreement protocol.
Allows two parties, each having an elliptic-curve public-private key pair, to establish a shared secret over an insecure channel
- generate_private_key()¶
Generate local private key for ecdh operation with curve that was set.
- Raises:
NoCurveError – Curve must be set before key generation.
- Returns:
public (verifying) key from this private key.
- Return type:
Generate shared secret from local private key and remote public key.
The objects needs to have both private key and received public key before generation is allowed.
It’s the same for local and remote party, shared secret(local private key, remote public key) == shared secret(local public key, remote private key)
- Raises:
InvalidCurveError – public_key curve not the same as self.curve
NoKeyError – public_key or private_key is not set
- Returns:
shared secret
- Return type:
int
Generate shared secret from local private key and remote public key.
The objects needs to have both private key and received public key before generation is allowed.
- Raises:
InvalidCurveError – public_key curve not the same as self.curve
NoKeyError – public_key or private_key is not set
- Returns:
shared secret
- Return type:
bytes
- get_public_key()¶
Provides a public key that matches the local private key.
Needs to be sent to the remote party.
- Returns:
public (verifying) key from local private key.
- Return type:
- load_private_key(private_key)¶
Load private key from SigningKey (keys.py) object.
Needs to have the same curve as was set with set_curve method. If curve is not set - it sets from this SigningKey
- Parameters:
private_key (SigningKey) – Initialised SigningKey class
- Raises:
InvalidCurveError – private_key curve not the same as self.curve
- Returns:
public (verifying) key from this private key.
- Return type:
- load_private_key_bytes(private_key)¶
Load private key from byte string.
Uses current curve and checks if the provided key matches the curve of ECDH key agreement. Key loads via from_string method of SigningKey class
- Parameters:
private_key (bytes-like object) – private key in bytes string format
- Raises:
NoCurveError – Curve must be set before loading.
- Returns:
public (verifying) key from this private key.
- Return type:
- load_private_key_der(private_key_der)¶
Load private key from DER byte string.
Compares the curve of the DER-encoded key with the ECDH set curve, uses the former if unset.
Note, the only DER format supported is the RFC5915 Look at keys.py:SigningKey.from_der()
- Parameters:
private_key_der (string) – string with the DER encoding of private ECDSA key
- Raises:
InvalidCurveError – private_key curve not the same as self.curve
- Returns:
public (verifying) key from this private key.
- Return type:
- load_private_key_pem(private_key_pem)¶
Load private key from PEM string.
Compares the curve of the DER-encoded key with the ECDH set curve, uses the former if unset.
Note, the only PEM format supported is the RFC5915 Look at keys.py:SigningKey.from_pem() it needs to have EC PRIVATE KEY section
- Parameters:
private_key_pem (string) – string with PEM-encoded private ECDSA key
- Raises:
InvalidCurveError – private_key curve not the same as self.curve
- Returns:
public (verifying) key from this private key.
- Return type:
- load_received_public_key(public_key)¶
Load public key from VerifyingKey (keys.py) object.
Needs to have the same curve as set as current for ecdh operation. If curve is not set - it sets it from VerifyingKey.
- Parameters:
public_key (VerifyingKey) – Initialised VerifyingKey class
- Raises:
InvalidCurveError – public_key curve not the same as self.curve
- load_received_public_key_bytes(public_key_str, valid_encodings=None)¶
Load public key from byte string.
Uses current curve and checks if key length corresponds to the current curve. Key loads via from_string method of VerifyingKey class
- Parameters:
public_key_str (bytes-like object) – public key in bytes string format
valid_encodings (set-like object) – list of acceptable point encoding formats, supported ones are: uncompressed, compressed, hybrid, and raw encoding (specified with
raw
name). All formats by default (specified withNone
).
- load_received_public_key_der(public_key_der)¶
Load public key from DER byte string.
Compares the curve of the DER-encoded key with the ECDH set curve, uses the former if unset.
Note, the only DER format supported is the RFC5912 Look at keys.py:VerifyingKey.from_der()
- Parameters:
public_key_der (string) – string with the DER encoding of public ECDSA key
- Raises:
InvalidCurveError – public_key curve not the same as self.curve
- load_received_public_key_pem(public_key_pem)¶
Load public key from PEM string.
Compares the curve of the PEM-encoded key with the ECDH set curve, uses the former if unset.
Note, the only PEM format supported is the RFC5912 Look at keys.py:VerifyingKey.from_pem()
- Parameters:
public_key_pem (string) – string with PEM-encoded public ECDSA key
- Raises:
InvalidCurveError – public_key curve not the same as self.curve
- set_curve(key_curve)¶
Set the working curve for ecdh operations.
- Parameters:
key_curve (Curve) – curve from curves module
- class keycard.commands.ExportedKey(public_key=None, private_key=None, chain_code=None)¶
Bases:
object
-
chain_code:
Optional
[bytes
] = None¶
- property has_private: bool¶
- property is_extended: bool¶
-
private_key:
Optional
[bytes
] = None¶
-
public_key:
Optional
[bytes
] = None¶
-
chain_code:
- exception keycard.commands.InvalidResponseError¶
Bases:
KeyCardError
Raised when response parsing fails.
- exception keycard.commands.InvalidStateError(message)¶
Bases:
KeyCardError
Raised when a precondition is not met.
- class keycard.commands.KeyExportOption(*values)¶
Bases:
IntEnum
- EXTENDED_PUBLIC = 2¶
- PRIVATE_AND_PUBLIC = 0¶
- PUBLIC_ONLY = 1¶
- class keycard.commands.KeyPath(path, source=DerivationSource.MASTER)¶
Bases:
object
- MAX_COMPONENTS = 10¶
- to_string()¶
- Return type:
str
- exception keycard.commands.NotSelectedError¶
Bases:
KeyCardError
Raised when trying to use card before select().
- class keycard.commands.SecureChannel(enc_key, mac_key, iv, authenticated=False)¶
Bases:
object
SecureChannel manages a secure communication channel using AES encryption and MAC authentication.
- enc_key¶
The AES encryption key for the session.
- Type:
bytes
- mac_key¶
The AES MAC key for message authentication.
- Type:
bytes
- iv¶
The initialization vector for AES operations.
- Type:
bytes
- authenticated¶
Indicates if the session is authenticated.
- Type:
bool
-
authenticated:
bool
= False¶
-
enc_key:
bytes
¶
-
iv:
bytes
¶
-
mac_key:
bytes
¶
- classmethod open(shared_secret, pairing_key, salt, seed_iv)¶
Opens a new SecureChannel using the provided cryptographic parameters.
- Return type:
- Parameters:
shared_secret (bytes) – The shared secret used for key derivation.
pairing_key (bytes) – The pairing key used for key derivation.
salt (bytes) – The salt value used in the key derivation process.
seed_iv (bytes) – The initialization vector (IV) to seed the session.
- Returns:
- An instance of SecureChannel initialized with
derived encryption and MAC keys, and the provided IV.
- Return type:
- unwrap_response(response)¶
Unwraps and verifies a secure channel response.
- Return type:
tuple
[bytes
,int
]- Parameters:
response (bytes) – The encrypted response bytes to unwrap.
- Returns:
- A tuple containing the decrypted plaintext
(excluding the status word) and the status word as an integer.
- Return type:
tuple[bytes, int]
- Raises:
ValueError – If the secure channel is not authenticated.
ValueError – If the response length is invalid.
ValueError – If the MAC verification fails.
ValueError – If the decrypted plaintext is too short to contain a status word.
- wrap_apdu(cla, ins, p1, p2, data)¶
Wraps an APDU command with secure channel encryption and MAC.
- Return type:
bytes
- Parameters:
cla (int) – The APDU class byte.
ins (int) – The APDU instruction byte.
p1 (int) – The APDU parameter 1 byte.
p2 (int) – The APDU parameter 2 byte.
data (bytes) – The APDU data field to be encrypted.
- Returns:
- The wrapped APDU as a tuple
containing the class, instruction, parameter 1, parameter 2, and the concatenated MAC and encrypted data.
- Return type:
tuple[int, int, int, int, bytes]
- Raises:
ValueError – If the secure channel is not authenticated and the instruction is not 0x11.
- class keycard.commands.SignatureResult(digest, algo, r, s, recovery_id=None, public_key=None)¶
Bases:
object
-
algo:
SigningAlgorithm
¶
-
public_key:
Optional
[bytes
] = None¶
-
r:
bytes
¶
-
recovery_id:
Optional
[int
] = None¶
-
s:
bytes
¶
- property signature: bytes¶
- property signature_der: bytes¶
-
algo:
- class keycard.commands.SigningAlgorithm(*values)¶
Bases:
IntEnum
- BLS12_381 = 2¶
- ECDSA_SECP256K1 = 0¶
- EDDSA_ED25519 = 1¶
- SCHNORR_BIP340 = 3¶
- class keycard.commands.SigningKey(_error__please_use_generate=None)¶
Bases:
object
Class for handling keys that can create signatures (private keys).
- Variables:
curve (Curve) – The Curve over which all the cryptographic operations will take place
default_hashfunc – the function that will be used for hashing the data. Should implement the same API as
hashlib.sha1
baselen (int) – the length of a raw encoding of private key
verifying_key (VerifyingKey) – the public key associated with this private key
privkey (Private_key) – the actual private key
- classmethod from_der(string, hashfunc=<built-in function openssl_sha1>, valid_curve_encodings=None)¶
Initialise from key stored in DER format.
The DER formats supported are the un-encrypted RFC5915 (the ssleay format) supported by OpenSSL, and the more common un-encrypted RFC5958 (the PKCS #8 format).
Both formats contain an ASN.1 object following the syntax specified in RFC5915:
ECPrivateKey ::= SEQUENCE { version INTEGER { ecPrivkeyVer1(1) }} (ecPrivkeyVer1), privateKey OCTET STRING, parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, publicKey [1] BIT STRING OPTIONAL }
publicKey field is ignored completely (errors, if any, in it will be undetected).
Two formats are supported for the parameters field: the named curve and the explicit encoding of curve parameters. In the legacy ssleay format, this implementation requires the optional parameters field to get the curve name. In PKCS #8 format, the curve is part of the PrivateKeyAlgorithmIdentifier.
The PKCS #8 format includes an ECPrivateKey object as the privateKey field within a larger structure:
OneAsymmetricKey ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] Attributes OPTIONAL, ..., [[2: publicKey [1] PublicKey OPTIONAL ]], ... }
The attributes and publicKey fields are completely ignored; errors in them will not be detected.
- Parameters:
string (bytes-like object) – binary string with DER-encoded private ECDSA key
valid_curve_encodings (set-like object) – list of allowed encoding formats for curve parameters. By default (
None
) all are supported:named_curve
andexplicit
. Ignored for EdDSA.
- Raises:
MalformedPointError – if the length of encoding doesn’t match the provided curve or the encoded values is too large
RuntimeError – if the generation of public key from private key failed
UnexpectedDER – if the encoding of the DER file is incorrect
- Returns:
Initialised SigningKey object
- Return type:
- classmethod from_pem(string, hashfunc=<built-in function openssl_sha1>, valid_curve_encodings=None)¶
Initialise from key stored in PEM format.
The PEM formats supported are the un-encrypted RFC5915 (the ssleay format) supported by OpenSSL, and the more common un-encrypted RFC5958 (the PKCS #8 format).
The legacy format files have the header with the string
BEGIN EC PRIVATE KEY
. PKCS#8 files have the headerBEGIN PRIVATE KEY
. Encrypted files (ones that include the stringProc-Type: 4,ENCRYPTED
right after the PEM header) are not supported.See
from_der()
for ASN.1 syntax of the objects in this files.- Parameters:
string (str) – text with PEM-encoded private ECDSA key
valid_curve_encodings (set-like object) – list of allowed encoding formats for curve parameters. By default (
None
) all are supported:named_curve
andexplicit
.
- Raises:
MalformedPointError – if the length of encoding doesn’t match the provided curve or the encoded values is too large
RuntimeError – if the generation of public key from private key failed
UnexpectedDER – if the encoding of the PEM file is incorrect
- Returns:
Initialised SigningKey object
- Return type:
- classmethod from_secret_exponent(secexp, curve=NIST192p, hashfunc=<built-in function openssl_sha1>)¶
Create a private key from a random integer.
Note: it’s a low level method, it’s recommended to use the
generate()
method to create private keys.- Parameters:
secexp (int) – secret multiplier (the actual private key in ECDSA). Needs to be an integer between 1 and the curve order.
curve (Curve) – The curve on which the point needs to reside
hashfunc (callable) – The default hash function that will be used for signing, needs to implement the same interface as hashlib.sha1
- Raises:
MalformedPointError – when the provided secexp is too large or too small for the curve selected
RuntimeError – if the generation of public key from private key failed
- Returns:
Initialised SigningKey object
- Return type:
- classmethod from_string(string, curve=NIST192p, hashfunc=<built-in function openssl_sha1>)¶
Decode the private key from raw encoding.
Note: the name of this method is a misnomer coming from days of Python 2, when binary strings and character strings shared a type. In Python 3, the expected type is bytes.
- Parameters:
string (bytes-like object) – the raw encoding of the private key
curve (Curve) – The curve on which the point needs to reside
hashfunc (callable) – The default hash function that will be used for signing, needs to implement the same interface as hashlib.sha1
- Raises:
MalformedPointError – if the length of encoding doesn’t match the provided curve or the encoded values is too large
RuntimeError – if the generation of public key from private key failed
- Returns:
Initialised SigningKey object
- Return type:
- classmethod generate(curve=NIST192p, entropy=None, hashfunc=<built-in function openssl_sha1>)¶
Generate a random private key.
- Parameters:
curve (Curve) – The curve on which the point needs to reside, defaults to NIST192p
entropy (callable) – Source of randomness for generating the private keys, should provide cryptographically secure random numbers if the keys need to be secure. Uses os.urandom() by default.
hashfunc (callable) – The default hash function that will be used for signing, needs to implement the same interface as hashlib.sha1
- Returns:
Initialised SigningKey object
- Return type:
- get_verifying_key()¶
Return the VerifyingKey associated with this private key.
Equivalent to reading the verifying_key field of an instance.
- Returns:
a public key that can be used to verify the signatures made with this SigningKey
- Return type:
- sign(data, entropy=None, hashfunc=None, sigencode=<function sigencode_string>, k=None, allow_truncate=True)¶
Create signature over data.
Uses the probabilistic ECDSA algorithm for Weierstrass curves (NIST256p, etc.) and the deterministic EdDSA algorithm for the Edwards curves (Ed25519, Ed448).
This method uses the standard ECDSA algorithm that requires a cryptographically secure random number generator.
It’s recommended to use the
sign_deterministic()
method instead of this one.- Parameters:
data (bytes-like object) – data that will be hashed for signing
entropy (callable) – randomness source,
os.urandom()
by default. Ignored with EdDSA.hashfunc (callable) – hash function to use for hashing the provided
data
. If unspecified the default hash function selected during object initialisation will be used (seeVerifyingKey.default_hashfunc
). Should behave likesha1()
fromhashlib
. The output length of the hash (in bytes) must not be longer than the length of the curve order (rounded up to the nearest byte), so using SHA256 with NIST256p is ok, but SHA256 with NIST192p is not. (In the 2**-96ish unlikely event of a hash output larger than the curve order, the hash will effectively be wrapped mod n). If you want to explicitly allow use of large hashes with small curves set theallow_truncate
toTrue
. Usehashfunc=hashlib.sha1
to match openssl’s-ecdsa-with-SHA1
mode, orhashfunc=hashlib.sha256
for openssl-1.0.0’s-ecdsa-with-SHA256
. Ignored for EdDSAsigencode (callable) – function used to encode the signature. The function needs to accept three parameters: the two integers that are the signature and the order of the curve over which the signature was computed. It needs to return an encoded signature. See
sigencode_string()
andsigencode_der()
as examples of such functions. Ignored for EdDSAk (int) – a pre-selected nonce for calculating the signature. In typical use cases, it should be set to None (the default) to allow its generation from an entropy source. Ignored for EdDSA.
allow_truncate (bool) – if
True
, the provided digest can have bigger bit-size than the order of the curve, the extra bits (at the end of the digest) will be truncated. Use it when signing SHA-384 output using NIST256p or in similar situations. True by default. Ignored for EdDSA.
- Raises:
RSZeroError – in the unlikely event when r parameter or s parameter of the created signature is equal 0, as that would leak the key. Caller should try a better entropy source, retry with different
k
, or use thesign_deterministic()
in such case.- Returns:
encoded signature of the hash of data
- Return type:
bytes or sigencode function dependent type
- sign_deterministic(data, hashfunc=None, sigencode=<function sigencode_string>, extra_entropy=b'')¶
Create signature over data.
For Weierstrass curves it uses the deterministic RFC6979 algorithm. For Edwards curves it uses the standard EdDSA algorithm.
For ECDSA the data will be hashed using the hashfunc function before signing. For EdDSA the data will be hashed with the hash associated with the curve (SHA-512 for Ed25519 and SHAKE-256 for Ed448).
This is the recommended method for performing signatures when hashing of data is necessary.
- Parameters:
data (bytes-like object) – data to be hashed and computed signature over
hashfunc (callable) – hash function to use for computing the signature, if unspecified, the default hash function selected during object initialisation will be used (see VerifyingKey.default_hashfunc). The object needs to implement the same interface as hashlib.sha1. Ignored with EdDSA.
sigencode (callable) – function used to encode the signature. The function needs to accept three parameters: the two integers that are the signature and the order of the curve over which the signature was computed. It needs to return an encoded signature. See ecdsa.util.sigencode_string and ecdsa.util.sigencode_der as examples of such functions. Ignored with EdDSA.
extra_entropy (bytes-like object) – additional data that will be fed into the random number generator used in the RFC6979 process. Entirely optional. Ignored with EdDSA.
- Returns:
encoded signature over data
- Return type:
bytes or sigencode function dependent type
- sign_digest(digest, entropy=None, sigencode=<function sigencode_string>, k=None, allow_truncate=False)¶
Create signature over digest using the probabilistic ECDSA algorithm.
This method uses the standard ECDSA algorithm that requires a cryptographically secure random number generator.
This method does not hash the input.
It’s recommended to use the
sign_digest_deterministic()
method instead of this one.- Parameters:
digest (bytes-like object) – hash value that will be signed
entropy (callable) – randomness source, os.urandom by default
sigencode (callable) – function used to encode the signature. The function needs to accept three parameters: the two integers that are the signature and the order of the curve over which the signature was computed. It needs to return an encoded signature. See ecdsa.util.sigencode_string and ecdsa.util.sigencode_der as examples of such functions.
k (int) – a pre-selected nonce for calculating the signature. In typical use cases, it should be set to None (the default) to allow its generation from an entropy source.
allow_truncate (bool) – if True, the provided digest can have bigger bit-size than the order of the curve, the extra bits (at the end of the digest) will be truncated. Use it when signing SHA-384 output using NIST256p or in similar situations.
- Raises:
RSZeroError – in the unlikely event when “r” parameter or “s” parameter of the created signature is equal 0, as that would leak the key. Caller should try a better entropy source, retry with different ‘k’, or use the
sign_digest_deterministic()
in such case.- Returns:
encoded signature for the digest hash
- Return type:
bytes or sigencode function dependent type
- sign_digest_deterministic(digest, hashfunc=None, sigencode=<function sigencode_string>, extra_entropy=b'', allow_truncate=False)¶
Create signature for digest using the deterministic RFC6979 algorithm.
digest should be the output of cryptographically secure hash function like SHA256 or SHA-3-256.
This is the recommended method for performing signatures when no hashing of data is necessary.
- Parameters:
digest (bytes-like object) – hash of data that will be signed
hashfunc (callable) – hash function to use for computing the random “k” value from RFC6979 process, if unspecified, the default hash function selected during object initialisation will be used (see
VerifyingKey.default_hashfunc
). The object needs to implement the same interface assha1()
fromhashlib
.sigencode (callable) – function used to encode the signature. The function needs to accept three parameters: the two integers that are the signature and the order of the curve over which the signature was computed. It needs to return an encoded signature. See
sigencode_string()
andsigencode_der()
as examples of such functions.extra_entropy (bytes-like object) – additional data that will be fed into the random number generator used in the RFC6979 process. Entirely optional.
allow_truncate (bool) – if True, the provided digest can have bigger bit-size than the order of the curve, the extra bits (at the end of the digest) will be truncated. Use it when signing SHA-384 output using NIST256p or in similar situations.
- Returns:
encoded signature for the digest hash
- Return type:
bytes or sigencode function dependent type
- sign_number(number, entropy=None, k=None)¶
Sign an integer directly.
Note, this is a low level method, usually you will want to use
sign_deterministic()
orsign_digest_deterministic()
.- Parameters:
number (int) – number to sign using the probabilistic ECDSA algorithm.
entropy (callable) – entropy source, os.urandom by default
k (int) – pre-selected nonce for signature operation. If unset it will be selected at random using the entropy source.
- Raises:
RSZeroError – in the unlikely event when “r” parameter or “s” parameter of the created signature is equal 0, as that would leak the key. Caller should try a better entropy source, retry with different ‘k’, or use the
sign_digest_deterministic()
in such case.- Returns:
the “r” and “s” parameters of the signature
- Return type:
tuple of ints
- to_der(point_encoding='uncompressed', format='ssleay', curve_parameters_encoding=None)¶
Convert the private key to the DER format.
See
from_der()
method for format specification.Only the named curve format is supported. The public key will be included in the generated string.
- Parameters:
point_encoding (str) – format to use for encoding public point Ignored for EdDSA
format (str) – either
ssleay
(default) orpkcs8
. EdDSA keys requirepkcs8
.curve_parameters_encoding (str) – format of encoded curve parameters, default depends on the curve, if the curve has an associated OID,
named_curve
format will be used, if no OID is associated with the curve, the fallback ofexplicit
parameters will be used. Ignored for EdDSA.
- Returns:
DER encoded private key
- Return type:
bytes
- to_pem(point_encoding='uncompressed', format='ssleay', curve_parameters_encoding=None)¶
Convert the private key to the PEM format.
See
from_pem()
method for format description.Only the named curve format is supported. The public key will be included in generated string.
The PEM header will specify
BEGIN EC PRIVATE KEY
orBEGIN PRIVATE KEY
, depending on the desired format.- Parameters:
point_encoding (str) – format to use for encoding public point
format (str) – either
ssleay
(default) orpkcs8
curve_parameters_encoding (str) – format of encoded curve parameters, default depends on the curve, if the curve has an associated OID,
named_curve
format will be used, if no OID is associated with the curve, the fallback ofexplicit
parameters will be used.
- Returns:
PEM encoded private key
- Return type:
bytes
Warning
The PEM is encoded to US-ASCII, it needs to be re-encoded if the system is incompatible (e.g. uses UTF-16)
- to_ssh()¶
Convert the private key to the SSH format.
- Returns:
SSH encoded private key
- Return type:
bytes
- to_string()¶
Convert the private key to raw encoding.
Note: while the method is named “to_string”, its name comes from Python 2 days, when binary and character strings used the same type. The type used in Python 3 is bytes.
- Returns:
raw encoding of private key
- Return type:
bytes
- class keycard.commands.VerifyingKey(_error__please_use_generate=None)¶
Bases:
object
Class for handling keys that can verify signatures (public keys).
- Variables:
~.curve (Curve) – The Curve over which all the cryptographic operations will take place
default_hashfunc (callable) – the function that will be used for hashing the data. Should implement the same API as hashlib.sha1
pubkey (Public_key) – the actual public key
- classmethod from_der(string, hashfunc=<built-in function openssl_sha1>, valid_encodings=None, valid_curve_encodings=None)¶
Initialise the key stored in DER format.
The expected format of the key is the SubjectPublicKeyInfo structure from RFC5912 (for RSA keys, it’s known as the PKCS#1 format):
SubjectPublicKeyInfo {PUBLIC-KEY: IOSet} ::= SEQUENCE { algorithm AlgorithmIdentifier {PUBLIC-KEY, {IOSet}}, subjectPublicKey BIT STRING }
Note: only public EC keys are supported by this method. The SubjectPublicKeyInfo.algorithm.algorithm field must specify id-ecPublicKey (see RFC3279).
Only the named curve encoding is supported, thus the SubjectPublicKeyInfo.algorithm.parameters field needs to be an object identifier. A sequence in that field indicates an explicit parameter curve encoding, this format is not supported. A NULL object in that field indicates an “implicitlyCA” encoding, where the curve parameters come from CA certificate, those, again, are not supported.
- Parameters:
string (bytes-like object) – binary string with the DER encoding of public ECDSA key
valid_encodings (set-like object) – list of allowed point encodings. By default uncompressed, compressed, and hybrid. To read malformed files, include raw encoding with
raw
in the list.valid_curve_encodings (set-like object) – list of allowed encoding formats for curve parameters. By default (
None
) all are supported:named_curve
andexplicit
.
- Returns:
Initialised VerifyingKey object
- Return type:
- classmethod from_pem(string, hashfunc=<built-in function openssl_sha1>, valid_encodings=None, valid_curve_encodings=None)¶
Initialise from public key stored in PEM format.
The PEM header of the key should be
BEGIN PUBLIC KEY
.See the
from_der()
method for details of the format supported.Note: only a single PEM object decoding is supported in provided string.
- Parameters:
string (str) – text with PEM-encoded public ECDSA key
valid_encodings (set-like object) – list of allowed point encodings. By default uncompressed, compressed, and hybrid. To read malformed files, include raw encoding with
raw
in the list.valid_curve_encodings (set-like object) – list of allowed encoding formats for curve parameters. By default (
None
) all are supported:named_curve
andexplicit
.
- Returns:
Initialised VerifyingKey object
- Return type:
- classmethod from_public_key_recovery(signature, data, curve, hashfunc=<built-in function openssl_sha1>, sigdecode=<function sigdecode_string>, allow_truncate=True)¶
Return keys that can be used as verifiers of the provided signature.
Tries to recover the public key that can be used to verify the signature, usually returns two keys like that.
- Parameters:
signature (bytes-like object) – the byte string with the encoded signature
data (bytes-like object) – the data to be hashed for signature verification
curve (Curve) – the curve over which the signature was performed
hashfunc (callable) – The default hash function that will be used for verification, needs to implement the same interface as hashlib.sha1
sigdecode (callable) – Callable to define the way the signature needs to be decoded to an object, needs to handle signature as the first parameter, the curve order (an int) as the second and return a tuple with two integers, “r” as the first one and “s” as the second one. See
ecdsa.util.sigdecode_string()
andecdsa.util.sigdecode_der()
for examples.allow_truncate (bool) – if True, the provided hashfunc can generate values larger than the bit size of the order of the curve, the extra bits (at the end of the digest) will be truncated.
- Returns:
Initialised VerifyingKey objects
- Return type:
list of VerifyingKey
- classmethod from_public_key_recovery_with_digest(signature, digest, curve, hashfunc=<built-in function openssl_sha1>, sigdecode=<function sigdecode_string>, allow_truncate=False)¶
Return keys that can be used as verifiers of the provided signature.
Tries to recover the public key that can be used to verify the signature, usually returns two keys like that.
- Parameters:
signature (bytes-like object) – the byte string with the encoded signature
digest (bytes-like object) – the hash value of the message signed by the signature
curve (Curve) – the curve over which the signature was performed
hashfunc (callable) – The default hash function that will be used for verification, needs to implement the same interface as hashlib.sha1
sigdecode (callable) – Callable to define the way the signature needs to be decoded to an object, needs to handle signature as the first parameter, the curve order (an int) as the second and return a tuple with two integers, “r” as the first one and “s” as the second one. See
ecdsa.util.sigdecode_string()
andecdsa.util.sigdecode_der()
for examples.allow_truncate (bool) – if True, the provided hashfunc can generate values larger than the bit size of the order of the curve (and the length of provided digest), the extra bits (at the end of the digest) will be truncated.
- Returns:
Initialised VerifyingKey object
- Return type:
- classmethod from_public_point(point, curve=NIST192p, hashfunc=<built-in function openssl_sha1>, validate_point=True)¶
Initialise the object from a Point object.
This is a low-level method, generally you will not want to use it.
- Parameters:
point (AbstractPoint) – The point to wrap around, the actual public key
curve (Curve) – The curve on which the point needs to reside, defaults to NIST192p
hashfunc (callable) – The default hash function that will be used for verification, needs to implement the same interface as
hashlib.sha1
- Raises:
MalformedPointError – if the public point does not lay on the curve
- Returns:
Initialised VerifyingKey object
- Return type:
- classmethod from_string(string, curve=NIST192p, hashfunc=<built-in function openssl_sha1>, validate_point=True, valid_encodings=None)¶
Initialise the object from byte encoding of public key.
The method does accept and automatically detect the type of point encoding used. It supports the raw encoding, uncompressed, compressed, and hybrid encodings. It also works with the native encoding of Ed25519 and Ed448 public keys (technically those are compressed, but encoded differently than in other signature systems).
Note, while the method is named “from_string” it’s a misnomer from Python 2 days when there were no binary strings. In Python 3 the input needs to be a bytes-like object.
- Parameters:
string (bytes-like object) – single point encoding of the public key
curve (Curve) – the curve on which the public key is expected to lay
hashfunc (callable) – The default hash function that will be used for verification, needs to implement the same interface as hashlib.sha1. Ignored for EdDSA.
validate_point (bool) – whether to verify that the point lays on the provided curve or not, defaults to True. Ignored for EdDSA.
valid_encodings (set-like object) – list of acceptable point encoding formats, supported ones are: uncompressed, compressed, hybrid, and raw encoding (specified with
raw
name). All formats by default (specified withNone
). Ignored for EdDSA.
- Raises:
MalformedPointError – if the public point does not lay on the curve or the encoding is invalid
- Returns:
Initialised VerifyingKey object
- Return type:
- precompute(lazy=False)¶
Precompute multiplication tables for faster signature verification.
Calling this method will cause the library to precompute the scalar multiplication tables, used in signature verification. While it’s an expensive operation (comparable to performing as many signatures as the bit size of the curve, i.e. 256 for NIST256p) it speeds up verification 2 times. You should call this method if you expect to verify hundreds of signatures (or more) using the same VerifyingKey object.
Note: You should call this method only once, this method generates a new precomputation table every time it’s called.
- Parameters:
lazy (bool) – whether to calculate the precomputation table now (if set to False) or if it should be delayed to the time of first use (when set to True)
- to_der(point_encoding='uncompressed', curve_parameters_encoding=None)¶
Convert the public key to the DER format.
The format of the key is described in the
from_der()
method. This method supports only “named curve” encoding of keys.- Parameters:
point_encoding (str) – specification of the encoding format of public keys. “uncompressed” is most portable, “compressed” is smallest. “hybrid” is uncommon and unsupported by most implementations, it is as big as “uncompressed”.
curve_parameters_encoding (str) – the encoding for curve parameters to use, by default tries to use
named_curve
encoding, if that is not possible, falls back toexplicit
encoding.
- Returns:
DER encoding of the public key
- Return type:
bytes
- to_pem(point_encoding='uncompressed', curve_parameters_encoding=None)¶
Convert the public key to the PEM format.
The PEM header of the key will be
BEGIN PUBLIC KEY
.The format of the key is described in the
from_der()
method. This method supports only “named curve” encoding of keys.- Parameters:
point_encoding (str) – specification of the encoding format of public keys. “uncompressed” is most portable, “compressed” is smallest. “hybrid” is uncommon and unsupported by most implementations, it is as big as “uncompressed”.
curve_parameters_encoding (str) – the encoding for curve parameters to use, by default tries to use
named_curve
encoding, if that is not possible, falls back toexplicit
encoding.
- Returns:
portable encoding of the public key
- Return type:
bytes
Warning
The PEM is encoded to US-ASCII, it needs to be re-encoded if the system is incompatible (e.g. uses UTF-16)
- to_ssh()¶
Convert the public key to the SSH format.
- Returns:
SSH encoding of the public key
- Return type:
bytes
- to_string(encoding='raw')¶
Convert the public key to a byte string.
The method by default uses the raw encoding (specified by encoding=”raw”. It can also output keys in uncompressed, compressed and hybrid formats.
Remember that the curve identification is not part of the encoding so to decode the point using
from_string()
, curve needs to be specified.Note: while the method is called “to_string”, it’s a misnomer from Python 2 days when character strings and byte strings shared type. On Python 3 the returned type will be bytes.
- Returns:
raw encoding of the public key (public point) on the curve
- Return type:
bytes
- verify(signature, data, hashfunc=None, sigdecode=<function sigdecode_string>, allow_truncate=True)¶
Verify a signature made over provided data.
Will hash data to verify the signature.
By default expects signature in raw encoding. Can also be used to verify signatures in ASN.1 DER encoding by using
ecdsa.util.sigdecode_der()
as the sigdecode parameter.- Parameters:
signature (sigdecode method dependent) – encoding of the signature
data (bytes-like object) – data signed by the signature, will be hashed using hashfunc, if specified, or default hash function
hashfunc (callable) – The default hash function that will be used for verification, needs to implement the same interface as hashlib.sha1
sigdecode (callable) – Callable to define the way the signature needs to be decoded to an object, needs to handle signature as the first parameter, the curve order (an int) as the second and return a tuple with two integers, “r” as the first one and “s” as the second one. See
ecdsa.util.sigdecode_string()
andecdsa.util.sigdecode_der()
for examples.allow_truncate (bool) – if True, the provided digest can have bigger bit-size than the order of the curve, the extra bits (at the end of the digest) will be truncated. Use it when verifying SHA-384 output using NIST256p or in similar situations. Defaults to True.
- Raises:
BadSignatureError – if the signature is invalid or malformed
- Returns:
True if the verification was successful
- Return type:
bool
- verify_digest(signature, digest, sigdecode=<function sigdecode_string>, allow_truncate=False)¶
Verify a signature made over provided hash value.
By default expects signature in raw encoding. Can also be used to verify signatures in ASN.1 DER encoding by using
ecdsa.util.sigdecode_der()
as the sigdecode parameter.- Parameters:
signature (sigdecode method dependent) – encoding of the signature
digest (bytes-like object) – raw hash value that the signature authenticates.
sigdecode (callable) – Callable to define the way the signature needs to be decoded to an object, needs to handle signature as the first parameter, the curve order (an int) as the second and return a tuple with two integers, “r” as the first one and “s” as the second one. See
ecdsa.util.sigdecode_string()
andecdsa.util.sigdecode_der()
for examples.allow_truncate (bool) – if True, the provided digest can have bigger bit-size than the order of the curve, the extra bits (at the end of the digest) will be truncated. Use it when verifying SHA-384 output using NIST256p or in similar situations.
- Raises:
BadSignatureError – if the signature is invalid or malformed
BadDigestError – if the provided digest is too big for the curve associated with this VerifyingKey and allow_truncate was not set
- Returns:
True if the verification was successful
- Return type:
bool
- keycard.commands.aes_cbc_encrypt(key, iv, data, padding=True)¶
- Return type:
bytes
- 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.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.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.generate_pairing_token(passphrase)¶
- Return type:
bytes
- 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.
- Return type:
bytes
- Parameters:
card – The card session object.
slot (StorageSlot) – Where to store the data (PUBLIC, NDEF, CASH)
- Raises:
ValueError – If slot is invalid or data is too long.
- 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)¶
Initializes a Keycard device with PIN, PUK, and pairing secret.
Establishes an ephemeral ECDH key exchange and sends encrypted credentials to the card.
- Return type:
None
- Parameters:
transport – The transport used to send APDU commands to the card.
card_public_key (bytes) – The card’s ECC public key, usually retrieved via select().
pin (bytes) – The personal identification number (PIN) as bytes.
puk (bytes) – The personal unblocking key (PUK) as bytes.
pairing_secret (bytes) – A 32-byte shared secret or a passphrase that will be converted into one.
- Raises:
NotSelectedError – If no card public key is provided.
ValueError – If the encrypted data exceeds a single APDU length.
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 – 64-byte BIP39 seed (only for key_type=BIP39_SEED).
- 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, pairing_index, pairing_key)¶
Opens a secure session with the Keycard using ECDH and a pairing key.
This function performs an ephemeral ECDH key exchange with the card, sends the ephemeral public key, and receives cryptographic material from the card to derive a secure session.
- Return type:
- Parameters:
transport – The transport used to communicate with the card.
card_public_key (bytes) – The ECC public key of the card, retrieved via select().
pairing_index (int) – The index of the previously established pairing slot.
pairing_key (bytes) – The shared 32-byte pairing key.
- Returns:
A newly established secure session with the card.
- Return type:
- Raises:
NotSelectedError – If no card public key is provided.
APDUError – If the card returns a failure status word.
- keycard.commands.pair(card, shared_secret)¶
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.
- 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.parse(challenge, data)¶
- Return type:
bytes
- keycard.commands.remove_key(card)¶
Removes the key from the card, returning it to an uninitialized state.
- Return type:
None
- keycard.commands.require_initialized(func)¶
- Return type:
Callable
[[ParamSpec
(P
, bound=None
)],TypeVar
(R
)]
- keycard.commands.require_pin_verified(func)¶
- Return type:
Callable
[[ParamSpec
(P
, bound=None
)],TypeVar
(R
)]
- keycard.commands.require_secure_channel(func)¶
- Return type:
Callable
[[ParamSpec
(P
, bound=None
)],TypeVar
(R
)]
- keycard.commands.require_selected(func)¶
- Return type:
Callable
[[ParamSpec
(P
, bound=None
)],TypeVar
(R
)]
- 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.sigdecode_der(sig_der, order)¶
Decoder for DER format of ECDSA signatures.
DER format of signature is one that uses the ASN.1 DER rules to encode it as a sequence of two integers:
Ecdsa-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER }
It’s expected that this function will be used as as the
sigdecode=
parameter to theecdsa.keys.VerifyingKey.verify()
method.- Parameters:
sig_der (bytes like object) – encoded signature
order (int) – order of the curve over which the signature was computed
- Raises:
UnexpectedDER – when the encoding of signature is invalid
- Returns:
tuple with decoded
r
ands
values of signature- Return type:
tuple of ints
- keycard.commands.sign(card, digest, p1=DerivationOption.CURRENT, p2=SigningAlgorithm.ECDSA_SECP256K1, derivation_path=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.
- 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 - 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
p2 (SigningAlgorithm) – Signing algorithm (e.g. ECDSA_SECP256K1).
derivation_path (Optional[str]) – String-formatted BIP32 path (e.g. “m/44’/60’/0’/0/0”). Required if p1 uses derivation. The source (master/parent/current) is inferred from the path prefix.
- 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 is not 32 bytes or 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.
- Return type:
None
- Parameters:
card – The card session object.
data (bytes) – The data to store (max 127 bytes).
slot (StorageSlot) – Where to store the data (PUBLIC, NDEF, CASH)
- Raises:
ValueError – If slot is invalid or 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.urandom(size, /)¶
Return a bytes object containing random bytes suitable for cryptographic use.
- 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.