cryptnoxpy

This is a library for communicating with Cryptnox cards

See the README.md for API details and general information.

Subpackages

Submodules

Package Contents

Classes

Card

Object that contains information about the card that is in the reader.

Connection

Connection to the reader.

Derivation

Predefined values to use for parameters as Derivation.

KeyType

Predefined values to use for parameters as KeyType.

SlotIndex

Predefined values to use for parameters as SlotIndex.

AuthType

Predefined values for authentication type.

SeedSource

Predefined values for how seed was created

Attributes

__version__

class cryptnoxpy.Card(connection: cryptnoxpy.connection.Connection, data: List[int] = None, debug: bool = False)

Object that contains information about the card that is in the reader.

Parameters
  • connection (Connection) – Connection to use for card initialization

  • debug (bool) – Show debug information to the user.

Variables
  • applet_version (List[int]) – Version of the applet on the card.

  • serial_number (int) – Serial number of card.

  • session_public_key (str) – Public key of the session.

  • initialized (bool) – The card has been initialized with secrets.

Raises

CardTypeException – The card in the reader is not a Cryptnox card

_ALGORITHM
PUK_LENGTH = 15
property select_apdu List[int]
Returns

Value to add to select command to select the applet on the card

Return type

List[int]

property type int
Returns

Card type

Return type

int

property pin_rule str

Human readable PIN code rule

Returns

Human readable PIN code rule

Return type

str

property puk_rule str

Human readable PUK code rule

Returns

Human readable PUK code rule

Return type

str

property alive(self) bool
Returns

The connection to the card is established and the card hasn’t been changed

Return type

bool

abstract change_pairing_key(self, index: int, pairing_key: bytes, puk: str = '') None

Set the pairing key of the card

Parameters
  • index (int) – Index of the pairing key

  • pairing_key (bytes) – Pairing key to set for the card

  • puk (str) – PUK code of the card

Raises
abstract change_pin(self, new_pin: str) None

Change the current pin code of the card to a new pin code.

The method will set the given pin code as the pin code of the card. For it to work the card first must be opened with the current pin code.

Requires
  • PIN code or challenge-response validated

Parameters

new_pin (str) – The desired PIN code to be set for the card (4-9 digits).

abstract change_puk(self, current_puk: str, new_puk: str) None

Change the current pin code of the card to a new pin code.

The method will set the given pin code as the pin code of the card. For it to work the card first must be opened with the current pin code.

Parameters
  • current_puk (str) – The current PUK code of the card

  • new_puk (str) – The desired PUK code to be set for the card

check_init(self) None

Check if the initialization has been done on the card.

It can be useful to check if the card is initialized before doing anything else, like asking for pin code from the user.

Raises

InitializationException – The card is not initialized

abstract derive(self, key_type: cryptnoxpy.enums.KeyType = KeyType.K1, path: str = '')

Derive key on path and make it the current key in the card

Requires
  • PIN code or challenge-response validated

  • Seed must exist

Parameters
  • key_type (KeyType) – Key type to do derive on

  • path (str) – Path on which to do derivation

abstract dual_seed_public_key(self, pin: str = '') bytes

Get the public key from the card for dual initialization of the cards

Requires
  • PIN code or challenge-response validated

Parameters

pin (str) – PIN code of card if it was opened with a PIN check

Returns

Public key and signature that can be sent into the other card

Return type

bytes

Raises

DataException – The received data is invalid

abstract dual_seed_load(self, data: bytes, pin: str = '') None

Load public key and signature from the other card into the card to generate same seed.

Requires
  • PIN code or challenge-response validated

Parameters
  • pin (str) – PIN code of card if it was opened with a PIN check

  • data (bytes) – Public key and signature of public key from the other card

property extended_public_key(self) bool
Returns

Extended public key turned on

Return type

bool

abstract generate_random_number(self, size: int) bytes

Generate random number on the car and return it.

Parameters

size (int) – Output data size in bytes (between 16 and 64, mod 4)

Returns

Random number generated by the chip

Return type

bytes

Raises

DataValidationException – size in not a number between 16 and 64 or is not divisible by 4

abstract generate_seed(self, pin: str = '') bytes

Generate a seed directly on the card.

Requires
  • PIN code or challenge-response validated

Parameters

pin (str, optional) – PIN code of the card. Can be empty if card is opened with challenge-response validation

Returns

Primary node “m” UID (hash of public key)

Return type

bytes

Raises
abstract get_public_key(self, derivation: cryptnoxpy.enums.Derivation, key_type: cryptnoxpy.enums.KeyType = KeyType.K1, path: str = '', compressed: bool = True) str

Get the public key from the card.

Requires
  • PIN code or challenge-response validated, except for PIN-less path

  • Seed must exist

Parameters
  • derivation (Derivation) – Derivation to use.

  • key_type (KeyType) – Key type to use

  • path (str) –

  • compressed (bool) – The returned value is in compressed format.

Returns

The public key for the given path in hexadecimal string format

Return type

str

Raises
abstract history(self, index: int = 0) NamedTuple

Get history of hashes the card has signed regardless of any parameters given to sign

Requires
  • PIN code or challenge-response validated

Parameters

index (int) – Index of entry in history

Returns

Return entry containing signing_counter, representing index of sign call, and hashed_data, the data that was signed

Return type

NamedTuple

property info(self) Dict[str, Any]

Get relevant information about the card.

Returns

Dictionary containing information for the card

Return type

Dict[str, Any]

abstract init(self, name: str, email: str, pin: str, puk: str, pairing_secret: bytes) bytes

Initialize the Cryptnox card.

Initialize the Cryptnox card with the owners name and email address. Set the PIN and PUK codes for authenticating with the card to be able to use it.

Parameters
  • name (str) – Name of the card owner

  • email (str) – Email of the card owner

  • pin (str) – PIN code that will be used to open the card

  • puk (str) – PUK code that will be used to open the card

  • pairing_secret (bytes) – Pairing secret to use with the card

Returns

Pairing secret

Return type

bytes

Raises

InitializationException – There was an issue with initialization

property initialized(self) bool
Returns

Whether the card is initialized

Return type

bool

abstract load_seed(self, seed: bytes, pin: str = '') None

Load the given seed into the Cryptnox card.

Requires
  • PIN code or challenge-response validated

Parameters
  • seed (bytes) – Seed to initialize the card with

  • pin (str, optional) – PIN code of the card. Can be empty if card is opened with challenge-response validation

Raises

KeyGenerationException – Data is not correct

property open(self) bool
Returns

Whether the user has authenticated using the PIN code or challenge-response validation

Return type

bool

property pin_authentication(self) bool
Returns

Whether the PIN code can be used for authentication

Return type

bool

property pinless_enabled(self) bool
Returns

Return whether the card has a pinless path

Return type

bool

abstract reset(self, puk: str) None

Reset the card and return it to factory settings.

Parameters

puk – PUK code associated with the card

property seed_source(self) cryptnoxpy.enums.SeedSource
Returns

How the seed was generated

Return type

SeedSource

abstract set_pin_authentication(self, status: bool, puk: str) None

Turn on/off authentication with the PIN code. Other methods can still be used.

Parameters
  • status (bool) – Status of PIN authentication

  • puk (str) – PUK code associated with the card

Raises
abstract set_pinless_path(self, path: bytes, puk: str) None

Enable working with the card without a PIN on path.

Parameters
  • path (bytes) – Path to be available without a PIN code

  • puk (str) – PUK code of the card

Raises
abstract set_extended_public_key(self, status: bool, puk: str) None

Turn on/off extended public key output.

Requires
  • Seed must be loaded

Parameters
  • status (bool) – Status of PIN authentication

  • puk (str) – PUK code associated with the card

Raises
abstract sign(self, data: bytes, derivation: cryptnoxpy.enums.Derivation, key_type: cryptnoxpy.enums.KeyType = KeyType.K1, path: str = '', pin: str = '', filter_eos: bool = False) bytes

Sign the message using given derivation.

Requires
  • PIN code provided, authenticate with user key by signing same message or PIN-less path used

  • Seed must be loaded

Parameters
  • data (bytes) – Data to sign

  • derivation (Derivation) – Derivation to use.

  • key_type (KeyType, optional) – Key type to use. Defaults to K1

  • path (str, optional) – Path of the key. If empty use main key

  • pin (str, optional) – PIN code of the card

  • filter_eos (str, optional) – Filter signature so it is valid for EOS network, might take longer. Defaults to False

Returns

The signature generated by the card in DER common format.

Return type

bytes

Raises

DataException – Invalid data received during signature

property signing_counter(self) int
Returns

Counter of how many times the card has been used to sign

Return type

int

unblock_pin(self, puk: str, new_pin: str) None

Verifies the user using the PUK code and sets a new PIN code on the card.

Method should be used when the user has forgotten this/hers PIN code. By entering the PUK code the user verifies his/hers identity and can set the new PIN code on the card. Can be used only if the card is locked.

Requires
  • User PIN must be locked

  • PIN code authentication must be enabled

Parameters
  • puk (str) – PUK code for verification of the user, before changing the PIN code.

  • new_pin (str) – The desired PIN code to be set for the card (4-9 digits).

Raises
property user_data(self) bytes
Returns

Read user data that was written into the card.

Return type

bytes

abstract user_key_add(self, slot: cryptnoxpy.enums.SlotIndex, data_info: str, public_key: bytes, puk_code: str, cred_id: bytes = b'') None

Add user public key into the card for user authentication

Parameters
  • slot (int) – Slot to write the public key to 1 - EC256R1 2 - RSA key, 2048 bits, public exponent must be 65537 3 - FIDO key

  • data_info (bytes) – 64 bytes of user data

  • public_key (bytes) – Public key of the secure element to be used for authentication

  • puk_code (str) – PUK code of the card

  • cred_id (bytes, optional) – Cred id. Used for FIDO2 authentication

Raises

DataValidationException – Invalid input data

abstract user_key_delete(self, slot: cryptnoxpy.enums.SlotIndex, puk_code: str) None

Delete the user key from slot and free up for insertion

Parameters
  • slot (SlotIndex) – Slot to remove the key from

  • puk_code (str) – PUK code of the card

Raises

DataValidationException – Invalid input data

abstract user_key_info(self, slot: cryptnoxpy.enums.SlotIndex) Tuple[str, str]

Get the description and public key of the user key

Requires
  • PIN code or challenge-response validated

Parameters

slot (SlotIndex) – Index of slot for which to fetch the description

Returns

Description and public key in slot

Return type

tuple[str, str]

abstract user_key_enabled(self, slot_index: cryptnoxpy.enums.SlotIndex) bool

Check if user key is present in given slot

Parameters

slot_index (SlotIndex) – Slot index to check for

Returns

Whether the user key for slot is present

Return type

bool

abstract user_key_challenge_response_nonce(self) bytes

Get 32 bytes random value from the card that is used to open the card with a user key

Take nonce value from the card. Sign it with a third party application, like TPM. Send the signature back into the card using user_key_challenge_response_open()

Returns

32 bytes random value used as nonce

Return type

bytes

abstract user_key_challenge_response_open(self, slot: cryptnoxpy.enums.SlotIndex, signature: bytes) bool

Send the nonce signature to the card to open it for operations, like it was opened by a PIN code

Parameters
  • slot (SlotIndex) – Slot to use to open the card

  • signature (bytes) – Signature generated by a third party like TPM.

Returns

Whether the challenge response authentication succeeded

Return type

bool

Raises

DataValidationException – invalid input data

abstract user_key_signature_open(self, slot: cryptnoxpy.enums.SlotIndex, message: bytes, signature: bytes) bool

Used for opening the card to sign the given message

Parameters
  • slot (SlotIndex) – Slot to use to open the card

  • message (bytes) – Message that will be sent to sign operation

  • signature (bytes) – Signature generated by a third party, like TPM, on the same message

Returns

Whether the challenge response authentication succeeded

Return type

bool

Raises

DataValidationException – invalid input data

property valid_key(self) bool

Check if the card has a valid key

Returns

Whether the card has a valid key.

Return type

bool

abstract static valid_pin(pin: str, pin_name: str = 'pin') str

Check if provided pin is valid

Parameters
  • pin (str) – The pin to check if valid

  • pin_name (str) – Value used in DataValidationException for pin name

Return str

Provided pin in str format if valid

Raises

DataValidationException – Provided pin is not valid

abstract static valid_puk(puk: str, puk_name: str = 'puk') str

Check if provided puk is valid

Parameters
  • puk (str) – The puk to check if valid

  • puk_name (str, optional) – Value used in DataValidationException for puk name. Defaults to: puk

Return str

Provided puk in str format if valid

Raises

DataValidationException – Provided puk is not valid

abstract verify_pin(self, pin: str) None

Check PIN code and open the card for operations that are protected.

The method is sending the PIN code to the card to open it for other operations. If there is an issue an exception will be raised.

Parameters

pin (str) – PIN code to check against the card.

Raises
property _owner(self) User

Get the available information about the owner of the card from the card

When the card is initialized the owner name and email address are stored on the card. This method will read and return them.

Returns

A dictionary containing the owner name and email address

Return type

Dict[str, str]

Raises
  • CryptnoxCard.PinException – PIN code wasn’t validated.

  • CryptnoxCard.SecureChannelException – Secure channel not opened.

classmethod __subclasshook__(cls, c)

Abstract classes can override this to customize issubclass().

This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it overrides the normal algorithm (and the outcome is cached).

__repr__(self)

Return repr(self).

class cryptnoxpy.Connection(index: int = 0, debug: bool = False)

Bases: contextlib.ContextDecorator

Connection to the reader.

Sends and receives messages from the card using the reader.

Parameters
  • index (int) – Index of the reader to initialize the connection with

  • debug (bool) – Show debug information during requests

Variables

self.card (Card) – Information about the card.

_init_reader(self, index)
__del__(self)
send_apdu(self, apdu: List[int]) Tuple[List[int], int, int]

Send data to the card in plain format

Parameters

apdu (int) – list of the APDU header

Return bytes

Result of the query that was sent to the card

Return type

bytes

Raises

ConnectionException – Issue in the connection

send_encrypted(self, apdu: List[int], data: bytes, receive_long: bool = False) bytes

Send data to the card in encrypted format

Parameters
  • apdu (int) – list of the APDU header

  • data – bytes of the data payload (in clear, will be encrypted)

  • receive_long (bool) –

Return bytes

Result of the query that was sent to the card

Return type

bytes

Raises

CryptnoxException – General exceptions

static _check_response_code(code1: int, code2: int) None
_decode(self, rep: bytes, mac_value: bytes) bytes
_encrypt(self, apdu: List[int], data: bytes, receive_long: bool) Tuple[List[int], Union[int, bytes]]
_open_secure_channel(self, pairing_secret: bytes = b'', pairing_key_index: int = 0) None
class cryptnoxpy.Derivation

Bases: enum.IntEnum

Predefined values to use for parameters as Derivation.

CURRENT_KEY = 0
DERIVE = 1
DERIVE_AND_MAKE_CURRENT = 2
PINLESS_PATH = 3
class cryptnoxpy.KeyType

Bases: enum.IntEnum

Predefined values to use for parameters as KeyType.

K1 = 0
R1 = 16
class cryptnoxpy.SlotIndex

Bases: enum.IntEnum

Predefined values to use for parameters as SlotIndex.

EC256R1 = 1
RSA = 2
FIDO = 3
class cryptnoxpy.AuthType

Bases: enum.Enum

Predefined values for authentication type.

NO_AUTH = 0
PIN = 1
USER_KEY = 2
__bool__(self)
class cryptnoxpy.SeedSource

Bases: enum.Enum

Predefined values for how seed was created

NO_SEED = 0
SINGLE
EXTENDED
EXTERNAL
INTERNAL
DUAL
exception cryptnoxpy.CryptnoxException

Bases: Exception

Base exception for the class exceptions.

exception cryptnoxpy.CardClosedException

Bases: Exception

The card wasn’t opened with PIN code or challenge-response

exception cryptnoxpy.CardException

Bases: CryptnoxException

No card was detected in the card reader.

exception cryptnoxpy.CardTypeException

Bases: CryptnoxException

The detected card is not supported by this library

exception cryptnoxpy.CertificateException

Bases: CryptnoxException

There was an issue with the certification

exception cryptnoxpy.ConnectionException

Bases: CryptnoxException

An issue occurred in the communication with the reader

exception cryptnoxpy.DataException

Bases: CryptnoxException

The reader returned an empty message.

exception cryptnoxpy.DataValidationException

Bases: CryptnoxException

The sent data is not valid.

exception cryptnoxpy.DerivationSelectionException

Bases: CryptnoxException

Not a valid derivation selection.

exception cryptnoxpy.EOSKeyError

Bases: CryptnoxException

The signature wasn’t compatible with EOS standard after 10 tries

exception cryptnoxpy.FirmwareException

Bases: CryptnoxException

There is an issue with the firmware on the card

exception cryptnoxpy.GenuineCheckException

Bases: CryptnoxException

The detected card is not a genuine Cryptnox product.

exception cryptnoxpy.GenericException(status: bytes)

Bases: CryptnoxException

Generic exception that can mean multiple things depending on the call to the card

Process stats and throw a specific Exception from it.

exception cryptnoxpy.InitializationException

Bases: CryptnoxException

The card hasn’t been initialized.

exception cryptnoxpy.KeyAlreadyGenerated

Bases: CryptnoxException

Key can not be generated twice.

exception cryptnoxpy.SeedException

Bases: CryptnoxException

Keys weren’t found on the card.

exception cryptnoxpy.KeyGenerationException

Bases: CryptnoxException

Error in key generation.

exception cryptnoxpy.PinAuthenticationException

Bases: CryptnoxException

Error in turning off PIN authentication. There is no user key in the card

exception cryptnoxpy.PinException(number_of_retries: int, message: str = 'Wrong pin')

Bases: CryptnoxException

Sent PIN code is not valid.

Parameters
  • number_of_retries (int) – Number of retries to send the PIN code before the card is locked.

  • message (str) – Optional message

exception cryptnoxpy.PukException(number_of_retries: int = 0, message: str = 'Wrong PUK')

Bases: CryptnoxException

Sent PUK code is not valid.

Parameters
  • number_of_retries (int) – Number of retries to send the PIN code before the card is locked.

  • message (str) – Optional message

exception cryptnoxpy.ReadPublicKeyException

Bases: CryptnoxException

Data received during public key reading is not valid.

exception cryptnoxpy.ReaderException

Bases: CryptnoxException

Card reader wasn’t found attached to the device.

exception cryptnoxpy.SecureChannelException

Bases: CryptnoxException

Secure channel couldn’t be established.

exception cryptnoxpy.SoftLock

Bases: CryptnoxException

The card is soft locked, and requires power cycle before it can be opened

exception cryptnoxpy.CardNotBlocked

Bases: CryptnoxException

Trying to unlock unblocked card

cryptnoxpy.__version__ = 1.0.4