keycard.secure_channel package¶
Submodules¶
keycard.secure_channel.base module¶
- class keycard.secure_channel.base.SecureChannel(*args, **kwargs)¶
Bases:
ProtocolAn open encrypted session with the card.
- property is_open: bool¶
- unwrap(response)¶
Verifies and decrypts a response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Protects a command for sending.
- Return type:
bytes- Returns:
The complete command APDU.
- Return type:
bytes
- keycard.secure_channel.base.channel_version(app_version)¶
Returns the secure channel version used by an applet version.
- Return type:
- Parameters:
app_version (tuple[int, int]) – Applet major and minor version.
- Returns:
V2 from applet 4.0, V1 before.
- Return type:
keycard.secure_channel.v1 module¶
- class keycard.secure_channel.v1.SecureChannelV1(enc_key, mac_key, iv, authenticated=False, previous_iv=None)¶
Bases:
objectSecure Channel V1 (applet 3.x): AES-CBC encryption with AES-CBC-MAC, keyed from a pairing.
- 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
- previous_iv¶
The IV the last command was encrypted with.
- Type:
Optional[bytes]
- authenticated: bool = False¶
- enc_key: bytes¶
- classmethod from_handshake(shared_secret, pairing_key, salt, seed_iv)¶
Derives the session keys from the handshake.
- 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:
- A channel initialized with derived encryption
and MAC keys, and the provided IV.
- Return type:
- property is_open: bool¶
- iv: bytes¶
- mac_key: bytes¶
- previous_iv: bytes | None = None¶
- unwrap(response)¶
Verifies and decrypts a response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word.
- 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.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Protects a command for sending.
- Return type:
bytes- Returns:
The complete command APDU.
- Return type:
bytes
- 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.
- keycard.secure_channel.v1.cbc_decrypt(key, iv, data)¶
Decrypts AES-CBC data and removes the padding.
- Return type:
bytes- Raises:
ValueError – If the padding is invalid.
- keycard.secure_channel.v1.cbc_encrypt(key, iv, data)¶
Pads and encrypts data with AES-CBC.
- Return type:
bytes- Returns:
The ciphertext.
- Return type:
bytes
- keycard.secure_channel.v1.cbc_mac(key, data)¶
AES-CBC-MAC with a zero IV over block-aligned data.
- Return type:
bytes- Returns:
The 16-byte MAC.
- Return type:
bytes
- Raises:
ValueError – If the data is not a multiple of the block size.
- keycard.secure_channel.v1.one_shot_encrypt(card_public_key, plaintext)¶
Encrypts data once to the card’s public key, as Secure Channel V1 INIT requires: an ephemeral ECDH key, then AES-CBC under the shared secret.
- Return type:
bytes- Returns:
Ephemeral public key length and key, IV, then ciphertext.
- Return type:
bytes
keycard.secure_channel.v2 module¶
- class keycard.secure_channel.v2.SecureChannelV2(key_h2c, key_c2h)¶
Bases:
objectSecure Channel V2 (applet 4.x): AES-128-CCM with keys from an ECDHE handshake authenticated by the card’s Identity Key.
- close()¶
- Return type:
None
- classmethod from_handshake(salt, shared_x)¶
Derives the session keys from the handshake.
- Return type:
- Parameters:
salt (bytes) – The 32-byte HKDF salt sent by the client.
shared_x (bytes) – X coordinate of the ECDH shared point.
- Returns:
An open channel.
- Return type:
- property is_open: bool¶
- unwrap(response)¶
Verifies and decrypts a SECURED APDU response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word. A failure of the channel itself also closes it.
InvalidResponseError – If the response does not verify; the channel is closed.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Encrypts a command as a SECURED APDU.
- Return type:
bytes- Returns:
The complete SECURED APDU.
- Return type:
bytes
- Raises:
InvalidStateError – If the channel is closed.
ValueError – If the command is too long for the channel.
- keycard.secure_channel.v2.transcript_digest(salt, client_public_key, card_public_key)¶
SHA-256 of the handshake transcript the card signs.
- Return type:
bytes- Returns:
SHA-256(“sc_v2_ccm” || salt || client key || card key).
- Return type:
bytes
Module contents¶
- class keycard.secure_channel.SecureChannel(*args, **kwargs)¶
Bases:
ProtocolAn open encrypted session with the card.
- property is_open: bool¶
- unwrap(response)¶
Verifies and decrypts a response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Protects a command for sending.
- Return type:
bytes- Returns:
The complete command APDU.
- Return type:
bytes
- class keycard.secure_channel.SecureChannelV1(enc_key, mac_key, iv, authenticated=False, previous_iv=None)¶
Bases:
objectSecure Channel V1 (applet 3.x): AES-CBC encryption with AES-CBC-MAC, keyed from a pairing.
- 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
- previous_iv¶
The IV the last command was encrypted with.
- Type:
Optional[bytes]
- authenticated: bool = False¶
- enc_key: bytes¶
- classmethod from_handshake(shared_secret, pairing_key, salt, seed_iv)¶
Derives the session keys from the handshake.
- 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:
- A channel initialized with derived encryption
and MAC keys, and the provided IV.
- Return type:
- property is_open: bool¶
- iv: bytes¶
- mac_key: bytes¶
- previous_iv: bytes | None = None¶
- unwrap(response)¶
Verifies and decrypts a response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word.
- 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.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Protects a command for sending.
- Return type:
bytes- Returns:
The complete command APDU.
- Return type:
bytes
- 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.secure_channel.SecureChannelV2(key_h2c, key_c2h)¶
Bases:
objectSecure Channel V2 (applet 4.x): AES-128-CCM with keys from an ECDHE handshake authenticated by the card’s Identity Key.
- close()¶
- Return type:
None
- classmethod from_handshake(salt, shared_x)¶
Derives the session keys from the handshake.
- Return type:
- Parameters:
salt (bytes) – The 32-byte HKDF salt sent by the client.
shared_x (bytes) – X coordinate of the ECDH shared point.
- Returns:
An open channel.
- Return type:
- property is_open: bool¶
- unwrap(response)¶
Verifies and decrypts a SECURED APDU response.
- Return type:
bytes- Returns:
The response data.
- Return type:
bytes
- Raises:
APDUError – If the card returned a failure status word. A failure of the channel itself also closes it.
InvalidResponseError – If the response does not verify; the channel is closed.
- property version: SecureChannelVersion¶
- wrap(ins, p1, p2, data)¶
Encrypts a command as a SECURED APDU.
- Return type:
bytes- Returns:
The complete SECURED APDU.
- Return type:
bytes
- Raises:
InvalidStateError – If the channel is closed.
ValueError – If the command is too long for the channel.
- keycard.secure_channel.channel_version(app_version)¶
Returns the secure channel version used by an applet version.
- Return type:
- Parameters:
app_version (tuple[int, int]) – Applet major and minor version.
- Returns:
V2 from applet 4.0, V1 before.
- Return type: