diff --git a/README.rst b/README.rst
index c184576..1b00068 100644
--- a/README.rst
+++ b/README.rst
@@ -5,19 +5,11 @@ Cryptnox Pro
.. image:: https://img.shields.io/pypi/v/cryptnoxpro
:target: https://pypi.org/project/cryptnoxpro
-
-**Warning: This is a beta release of the software.
-It is released for development purposes.
-Use at your own risk.**
-
A command line user interface to manage and use of `Cryptnox Smart cards `_.
This provides basic wallets for `Bitcoin `_ and
`Ethereum `_.
-It is able to execute `cleos `_ commands and use
-the keys on the card for signing.
-
To buy NFC enabled cards that are supported by this application go to:
`https://www.cryptnox.com/ `_
diff --git a/cryptnoxpro/command/helper/ui.py b/cryptnoxpro/command/helper/ui.py
index 7812363..5467c72 100644
--- a/cryptnoxpro/command/helper/ui.py
+++ b/cryptnoxpro/command/helper/ui.py
@@ -14,6 +14,7 @@
from tabulate import tabulate
from . import security
+from cryptnoxpro.config import MAX_PASSPHRASE_LENGTH
InitData = namedtuple("InitData", ["name", "email", "pin", "puk"])
@@ -201,3 +202,61 @@ def _verify_input(card: cryptnoxpy.Card, method, text, verify_text,
print(error)
return value
+
+
+def get_bip39_passphrase(confirm_required: bool = True) -> str:
+ print()
+ print_warning("BIP39 PASSPHRASE FEATURE")
+ print("A BIP39 passphrase is an optional extra password that provides additional security.")
+ print("Different passphrases create completely different wallets from the same mnemonic.")
+ print()
+ print("IMPORTANT WARNINGS:")
+ print(" • If you forget your passphrase, your funds are PERMANENTLY LOST")
+ print(" • Passphrases are case-sensitive and spaces matter")
+ print(" • There is NO way to recover funds without the exact passphrase")
+ print(" • Press ENTER to skip passphrase (standard BIP39 with empty passphrase)")
+ print()
+
+ use_passphrase = confirm("Do you want to use a BIP39 passphrase?")
+
+ if not use_passphrase:
+ return ""
+
+ print()
+ print("Enter your BIP39 passphrase:")
+ print("(Any UTF-8 characters are valid, but avoid unusual characters you might forget)")
+
+ if confirm_required:
+ passphrase = _verify_passphrase_input()
+ else:
+ passphrase = getpass("Passphrase: ")
+
+ if len(passphrase) > MAX_PASSPHRASE_LENGTH:
+ print("ERROR: Passphrase must be at most 100 characters. Please try again.")
+ raise ExitException("Passphrase exceeds 100 characters")
+
+ print()
+ print("Please write down your passphrase and store it securely.")
+ print("Without this exact passphrase, you CANNOT access your wallet.")
+ print()
+
+ if not confirm("Have you securely stored your passphrase?"):
+ raise ExitException("User needs to store passphrase securely")
+
+ return passphrase
+
+
+def _verify_passphrase_input() -> str:
+ while True:
+ passphrase = getpass("Passphrase: ")
+ if len(passphrase) > MAX_PASSPHRASE_LENGTH:
+ print("ERROR: Passphrase must be at most 100 characters. Please try again.")
+ print()
+ continue
+ verify_passphrase = getpass("Confirm passphrase: ")
+
+ if passphrase == verify_passphrase:
+ return passphrase
+
+ print("ERROR: Passphrases do not match. Please try again.")
+ print()
diff --git a/cryptnoxpro/command/seed.py b/cryptnoxpro/command/seed.py
index ce5640e..975046c 100644
--- a/cryptnoxpro/command/seed.py
+++ b/cryptnoxpro/command/seed.py
@@ -66,7 +66,21 @@ def _execute(self, card) -> int:
return result
@staticmethod
- def _backup(card: cryptnoxpy.Card, pin_code: str = None, seed: bytes = None) -> int:
+ def _backup(card: cryptnoxpy.Card, pin_code: str = None, seed: bytes = None,
+ passphrase: str = '') -> int:
+ """
+ Backup seed to AWS KMS and load onto card with optional BIP39 passphrase.
+
+ Note: The backup service stores only the raw seed entropy, not the passphrase.
+ The passphrase is used only when loading the mnemonic onto the card.
+ Users must remember their passphrase separately.
+
+ :param card: The Cryptnox card
+ :param pin_code: The card PIN code
+ :param seed: Optional pre-generated seed bytes
+ :param passphrase: Optional BIP39 passphrase
+ :return: 0 on success, -1 on error
+ """
pin_code = pin_code or Seed._get_pin_code(card)
credentials_file = Path(get_download_folder()).joinpath('rootkey.csv')
@@ -121,7 +135,7 @@ def _backup(card: cryptnoxpy.Card, pin_code: str = None, seed: bytes = None) ->
print("Seed successfully saved. Writing card.")
mnemonic = cryptos.entropy_to_words(seed)
- Seed._load_mnemonic(card, mnemonic, pin_code)
+ Seed._load_mnemonic(card, mnemonic, pin_code, passphrase=passphrase)
data = list(service.region.items())
data.append(("name", name))
@@ -131,6 +145,13 @@ def _backup(card: cryptnoxpy.Card, pin_code: str = None, seed: bytes = None) ->
backup_file.write_text(tabulate(data))
print(f"\nBackup data also saved to: {backup_file}")
+ if passphrase:
+ print()
+ ui.print_warning("IMPORTANT: BIP39 PASSPHRASE IN USE")
+ print("The backup service stores only the seed entropy, NOT your passphrase.")
+ print("You must remember and store your BIP39 passphrase separately!")
+ print("To restore this wallet, you will need BOTH the backup AND your passphrase.")
+
Seed._remove_credentials(credentials_file, service)
return 0
@@ -162,8 +183,23 @@ def _backup_service(access_key_id: str = '', secret_access_key: str = '') -> Uni
@staticmethod
def _chip(card: cryptnoxpy.Card) -> int:
+ """
+ Generate seed directly in the card's secure chip.
+
+ Note: This method generates the seed entirely on the card's hardware and does not
+ use BIP39 mnemonics. Therefore, BIP39 passphrases do not apply to this seed
+ generation method. The seed cannot be exported or backed up as a mnemonic phrase.
+
+ :param card: The Cryptnox card
+ :return: 0 on success
+ """
pin_code = Seed._get_pin_code(card)
+ print("Generating seed directly in card's secure chip...")
+ print("Note: This seed is generated on-chip and does not use BIP39 mnemonics.")
+ print("BIP39 passphrases do not apply to this generation method.")
+ print()
+
card.generate_seed(pin_code)
print("New key generated in card.")
@@ -191,6 +227,17 @@ def _credentials(credential_file: Path = None) -> Tuple[str, str]:
return access_key_id, secret_access_key
def _dual_seed(self, card: cryptnoxpy.Card) -> int:
+ """
+ Generate the same seed on two cards using secure dual-card generation.
+
+ Note: This method generates seeds using a secure two-card protocol and does not
+ use BIP39 mnemonics. Therefore, BIP39 passphrases do not apply to this seed
+ generation method. The seed is generated securely on both cards and never leaves
+ the hardware.
+
+ :param card: The first Cryptnox card
+ :return: 0 on success, -1 or -2 on error
+ """
try:
card.dual_seed_public_key()
except NotImplementedError as error:
@@ -199,6 +246,11 @@ def _dual_seed(self, card: cryptnoxpy.Card) -> int:
except cryptnoxpy.exceptions.DataValidationException:
pass
+ print("Dual seed generation process starting...")
+ print("Note: This method uses secure on-chip generation and does not use BIP39 mnemonics.")
+ print("BIP39 passphrases do not apply to this generation method.")
+ print()
+
pin_code = Seed._get_pin_code(card)
serial_number = card.serial_number
@@ -287,20 +339,42 @@ def _get_second_card(self, index: int, first_card_serial_number: int) -> cryptno
return card
@staticmethod
- def _load_mnemonic(card: cryptnoxpy.Card, mnemonic: str, pin_code: str) -> None:
+ def _load_mnemonic(card: cryptnoxpy.Card, mnemonic: str, pin_code: str,
+ passphrase: str = '') -> None:
+ """
+ Load mnemonic onto card with optional BIP39 passphrase.
+
+ :param card: The Cryptnox card
+ :param mnemonic: The BIP39 mnemonic phrase (12 or 24 words)
+ :param pin_code: The card PIN code
+ :param passphrase: Optional BIP39 passphrase (13th/25th word)
+ """
if len(mnemonic.split(' ')) not in (12, 24):
raise ValueError('Only mnemonic passphrases of length 12 and 24 are supported')
- seed = cryptos.bip39_mnemonic_to_seed(mnemonic)
+ seed = cryptos.bip39_mnemonic_to_seed(mnemonic, passphrase=passphrase)
card.load_seed(seed, pin_code)
@staticmethod
def _recover(card: cryptnoxpy.Card) -> int:
+ """
+ Recover wallet from BIP39 mnemonic phrase with optional passphrase.
+
+ :param card: The Cryptnox card
+ :return: 0 on success, -1 on error
+ """
pin_code = Seed._get_pin_code(card)
print("\nEnter the mnemonic root to recover (12 or 24 words):")
mnemonic = ui.input_with_exit("> ")
+
try:
- seed = cryptos.bip39_mnemonic_to_seed(mnemonic)
+ passphrase = ui.get_bip39_passphrase(confirm_required=True)
+ except ui.ExitException as error:
+ print(error)
+ return -1
+
+ try:
+ seed = cryptos.bip39_mnemonic_to_seed(mnemonic, passphrase=passphrase)
except Exception as error:
print(error)
return -1
@@ -308,14 +382,16 @@ def _recover(card: cryptnoxpy.Card) -> int:
do_backup = ui.confirm('Do you wish to backup your seed to AWS KMS?')
try:
if do_backup:
- Seed._backup(card, pin_code, seed)
+ Seed._backup(card, pin_code, seed, passphrase=passphrase)
else:
- Seed._load_mnemonic(card, mnemonic, pin_code)
+ Seed._load_mnemonic(card, mnemonic, pin_code, passphrase=passphrase)
except Exception as error:
print(error)
return -1
print("Mnemonic loaded, please keep it safe for backup.")
+ if passphrase:
+ print("You MUST use the same passphrase when restoring this wallet.")
return 0
@@ -331,6 +407,15 @@ def _remove_credentials(credentials_file: Path, service: backup.AWS) -> None:
@staticmethod
def _restore(card: cryptnoxpy.Card) -> int:
+ """
+ Restore seed from AWS KMS backup with optional BIP39 passphrase.
+
+ Note: The backup service stores only the seed entropy. If a BIP39 passphrase
+ was used when creating the wallet, it must be provided again during restore.
+
+ :param card: The Cryptnox card
+ :return: 0 on success, -1 on error
+ """
pin_code = Seed._get_pin_code(card)
credentials_file = Path(get_download_folder()).joinpath('rootkey.csv')
access_key_id, secret_access_key = Seed._credentials(credentials_file)
@@ -357,8 +442,19 @@ def _restore(card: cryptnoxpy.Card) -> int:
print("There was an issue with the retrieved backup in converting it to a mnemonic.")
return -1
- print("Seed successfully retrieved. Writing card.")
- Seed._load_mnemonic(card, mnemonic, pin_code)
+ print("Seed successfully retrieved.")
+ print()
+ print("If you used a BIP39 passphrase when creating this wallet,")
+ print("you must provide the same passphrase now.")
+
+ try:
+ passphrase = ui.get_bip39_passphrase(confirm_required=False)
+ except ui.ExitException as error:
+ print(error)
+ return -1
+
+ print("Writing card.")
+ Seed._load_mnemonic(card, mnemonic, pin_code, passphrase=passphrase)
print("\nMnemonic loaded from backup service.")
Seed._remove_credentials(credentials_file, service)
@@ -367,16 +463,29 @@ def _restore(card: cryptnoxpy.Card) -> int:
@staticmethod
def _upload(card: cryptnoxpy.Card) -> int:
+ """
+ Generate new seed, optionally with BIP39 passphrase, and upload to card.
+
+ :param card: The Cryptnox card
+ :return: 0 on success, -1 on error
+ """
pin_code = Seed._get_pin_code(card)
seed = card.generate_random_number(32)
mnemonic = cryptos.entropy_to_words(seed)
+
+ try:
+ passphrase = ui.get_bip39_passphrase(confirm_required=True)
+ except ui.ExitException as error:
+ print(error)
+ return -1
+
do_backup = ui.confirm('Do you wish to backup your seed to AWS KMS?')
try:
if do_backup:
- Seed._backup(card, pin_code, seed)
+ Seed._backup(card, pin_code, seed, passphrase=passphrase)
else:
- Seed._load_mnemonic(card, mnemonic, pin_code)
+ Seed._load_mnemonic(card, mnemonic, pin_code, passphrase=passphrase)
except Exception as error:
print(error)
return -1
@@ -386,4 +495,15 @@ def _upload(card: cryptnoxpy.Card) -> int:
print("\nMnemonic loaded, please save this root mnemonic for backup.")
+ if passphrase:
+ print()
+ ui.print_warning("IMPORTANT: BIP39 PASSPHRASE IN USE")
+ print("You are using a BIP39 passphrase with this wallet.")
+ print("To restore this wallet, you will need BOTH:")
+ print(" 1. The mnemonic phrase shown above")
+ print(" 2. Your BIP39 passphrase")
+ print()
+ print("Store your passphrase separately and securely!")
+ print("Without the exact passphrase, you CANNOT access your funds.")
+
return 0
diff --git a/cryptnoxpro/config.py b/cryptnoxpro/config.py
index 63323ac..b1eb555 100644
--- a/cryptnoxpro/config.py
+++ b/cryptnoxpro/config.py
@@ -18,6 +18,7 @@
_CONFIGURATION = {}
REMOTE_CONNECTIONS = []
+MAX_PASSPHRASE_LENGTH = 100
def get_default_configuration() -> Dict:
diff --git a/docs/cli.rst b/docs/cli.rst
new file mode 100644
index 0000000..2029365
--- /dev/null
+++ b/docs/cli.rst
@@ -0,0 +1,677 @@
+Command Line Interface
+======================
+
+The ``cryptnox`` command provides a comprehensive CLI for managing Cryptnox cards and performing cryptocurrency operations.
+
+Installation
+------------
+
+After installing the cryptnoxpro package, the ``cryptnox`` command becomes available in your system:
+
+.. code-block:: bash
+
+ pip install cryptnoxpro
+
+Basic Usage
+-----------
+
+.. code-block:: bash
+
+ cryptnox [OPTIONS] COMMAND [ARGS]...
+
+Global Options
+--------------
+
+.. option:: -v, --version
+
+ Show the version and exit.
+
+.. option:: --verbose
+
+ Turn on logging for detailed output.
+
+.. option:: -s, --serial SERIAL
+
+ Serial number of the card to be used for the command.
+
+.. option:: --port PORT
+
+ Define port to enable remote feature.
+
+Commands Overview
+-----------------
+
+Card Management Commands
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+list
+^^^^
+
+List all connected Cryptnox cards.
+
+.. code-block:: bash
+
+ cryptnox list
+
+init
+^^^^
+
+Initialize a Cryptnox card with owner information and PIN/PUK codes.
+
+.. code-block:: bash
+
+ cryptnox init [OPTIONS]
+
+Options:
+ - ``-e, --easy_mode``: Initialize card in easy mode (sets PIN and PUK to all zeros)
+
+reset
+^^^^^
+
+Reset the card to factory defaults.
+
+.. code-block:: bash
+
+ cryptnox reset
+
+**Warning:** This will erase all data on the card.
+
+info
+^^^^
+
+Display default accounts information for the card.
+
+.. code-block:: bash
+
+ cryptnox info
+
+Shows:
+ - Card serial number and type
+ - Ethereum and Bitcoin addresses
+ - Public keys
+ - Derivation information
+
+Seed Management Commands
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+seed backup
+^^^^^^^^^^^
+
+Generate seed in host, backup to AWS KMS, and upload to card.
+
+.. code-block:: bash
+
+ cryptnox seed backup
+
+**Features:**
+ - Generates new 32-byte random seed
+ - Stores encrypted backup in AWS KMS (Hardware Security Module)
+ - Supports BIP39 passphrase (13th/25th word)
+ - Loads seed onto card
+
+seed chip
+^^^^^^^^^
+
+Generate new root key directly in the card's secure chip.
+
+.. code-block:: bash
+
+ cryptnox seed chip
+
+**Note:** The seed never leaves the card and cannot be backed up.
+
+seed dual
+^^^^^^^^^
+
+Generate the same seed on two cards for redundancy.
+
+.. code-block:: bash
+
+ cryptnox seed dual
+
+**Requirements:** Two initialized Cryptnox cards
+
+**Process:**
+ 1. Generate seed on first card
+ 2. Swap cards
+ 3. Load same seed on second card
+ 4. Results in two cards with identical keys
+
+seed recover
+^^^^^^^^^^^^
+
+Recover a wallet from an existing BIP39 mnemonic phrase (12 or 24 words).
+
+.. code-block:: bash
+
+ cryptnox seed recover
+
+**Input Required:**
+ - Existing BIP39 mnemonic (12 or 24 words)
+ - Optional: BIP39 passphrase (13th/25th word)
+
+**Options:**
+ - Backup to AWS KMS
+ - Load directly to card
+
+**Use Cases:**
+ - Restoring existing wallet
+ - Migrating wallet from another device
+ - Recovering from backup mnemonic
+
+**Important:** If the original wallet used a BIP39 passphrase, you **must** provide the same passphrase during recovery.
+
+seed restore
+^^^^^^^^^^^^
+
+Restore seed from AWS KMS backup.
+
+.. code-block:: bash
+
+ cryptnox seed restore
+
+**Requirements:**
+ - AWS access credentials
+ - Backup name/alias in KMS
+
+**Important:** If a BIP39 passphrase was used when creating the backup, you must provide the same passphrase during restore.
+
+seed upload
+^^^^^^^^^^^
+
+Generate new random seed, upload to card, and display BIP39 mnemonic for backup.
+
+.. code-block:: bash
+
+ cryptnox seed upload
+
+**Features:**
+ - Generates new 32-byte random seed using card's hardware RNG
+ - Converts to BIP39 mnemonic (12 or 24 words)
+ - Optional: Add BIP39 passphrase (13th/25th word) for extra security
+ - Displays mnemonic for manual backup
+ - Optional: Backup to AWS KMS
+
+**Output:** The generated mnemonic phrase (save it securely!)
+
+**Important:** If you use a BIP39 passphrase, you **must** remember it. It cannot be recovered.
+
+Security Commands
+~~~~~~~~~~~~~~~~~
+
+change_pin
+^^^^^^^^^^
+
+Change the PIN code of the card.
+
+.. code-block:: bash
+
+ cryptnox change_pin
+
+**Requirements:** Current PIN code
+
+change_puk
+^^^^^^^^^^
+
+Change the PUK (PIN Unblocking Key) code of the card.
+
+.. code-block:: bash
+
+ cryptnox change_puk
+
+**Requirements:** Current PUK code
+
+unlock_pin
+^^^^^^^^^^
+
+Unlock a card with blocked PIN using the PUK code and set a new PIN.
+
+.. code-block:: bash
+
+ cryptnox unlock_pin
+
+**Requirements:** PUK code
+
+**Note:** PIN becomes blocked after multiple failed attempts.
+
+Card Configuration
+~~~~~~~~~~~~~~~~~~
+
+card_conf
+^^^^^^^^^
+
+Show or modify card configuration settings.
+
+.. code-block:: bash
+
+ cryptnox card_conf [KEY] [VALUE]
+
+**Available Settings:**
+
+- ``pinless``: Enable/disable PIN-less path
+- ``pin``: Enable/disable PIN authentication
+
+**Values:** ``yes`` or ``no``
+
+**Examples:**
+
+.. code-block:: bash
+
+ # Show current configuration
+ cryptnox card_conf
+
+ # Enable PIN-less path
+ cryptnox card_conf pinless yes
+
+ # Disable PIN-less path
+ cryptnox card_conf pinless no
+
+Bitcoin Commands
+~~~~~~~~~~~~~~~~
+
+btc send
+^^^^^^^^
+
+Send Bitcoin to an address.
+
+.. code-block:: bash
+
+ cryptnox btc send ADDRESS AMOUNT [OPTIONS]
+
+**Arguments:**
+ - ``ADDRESS``: Bitcoin address (P2PKH, P2SH, or Bech32)
+ - ``AMOUNT``: Amount in BTC
+
+**Options:**
+ - ``-n, --network {mainnet,testnet}``: Network to use
+ - ``-f, --fees SATOSHIS``: Transaction fees in satoshis per byte
+
+**Example:**
+
+.. code-block:: bash
+
+ cryptnox btc send 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa 0.001 -n mainnet -f 10
+
+btc config
+^^^^^^^^^^
+
+View or modify Bitcoin configuration.
+
+.. code-block:: bash
+
+ cryptnox btc config [KEY] [VALUE]
+
+**Settings:**
+ - ``network``: mainnet or testnet
+ - ``derivation``: Key derivation method
+
+Ethereum Commands
+~~~~~~~~~~~~~~~~~
+
+eth send
+^^^^^^^^
+
+Send Ether (ETH) to an address.
+
+.. code-block:: bash
+
+ cryptnox eth send ADDRESS AMOUNT [OPTIONS]
+
+**Arguments:**
+ - ``ADDRESS``: Ethereum address (0x...)
+ - ``AMOUNT``: Amount in ETH
+
+**Options:**
+ - ``-n, --network {mainnet,sepolia,goerli}``: Network to use
+ - ``--price GWEI``: Gas price in Gwei
+ - ``--limit GAS``: Gas limit
+
+**Example:**
+
+.. code-block:: bash
+
+ cryptnox eth send 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.1 -n mainnet --price 20
+
+eth config
+^^^^^^^^^^
+
+View or modify Ethereum configuration.
+
+.. code-block:: bash
+
+ cryptnox eth config [KEY] [VALUE]
+
+**Settings:**
+ - ``network``: mainnet, sepolia, or other networks
+ - ``derivation``: Key derivation method
+ - ``api_key``: Etherscan/Infura API key
+ - ``endpoint``: RPC endpoint
+
+ERC Token Commands
+~~~~~~~~~~~~~~~~~~
+
+eth erc20 init
+^^^^^^^^^^^^^^
+
+Initialize ERC-20 token contract for transactions.
+
+.. code-block:: bash
+
+ cryptnox eth erc20 init CONTRACT_ADDRESS [OPTIONS]
+
+eth erc20 info
+^^^^^^^^^^^^^^
+
+Display information about configured ERC-20 tokens.
+
+.. code-block:: bash
+
+ cryptnox eth erc20 info
+
+eth erc20 send
+^^^^^^^^^^^^^^
+
+Send ERC-20 tokens.
+
+.. code-block:: bash
+
+ cryptnox eth erc20 send TOKEN_ADDRESS RECIPIENT_ADDRESS AMOUNT [OPTIONS]
+
+transfer
+^^^^^^^^
+
+Transfer ERC-20 or ERC-721 tokens.
+
+.. code-block:: bash
+
+ cryptnox transfer ADDRESS AMOUNT [OPTIONS]
+
+**Options:**
+ - ``--price GWEI``: Gas price
+ - ``--limit GAS``: Gas limit
+
+Configuration Commands
+~~~~~~~~~~~~~~~~~~~~~~
+
+config
+^^^^^^
+
+List or modify blockchain configurations.
+
+.. code-block:: bash
+
+ cryptnox config [SECTION] [KEY] [VALUE]
+
+**Examples:**
+
+.. code-block:: bash
+
+ # Show all configuration
+ cryptnox config
+
+ # Show Ethereum configuration
+ cryptnox config eth
+
+ # Set Ethereum network
+ cryptnox config eth network mainnet
+
+ # Set Bitcoin derivation
+ cryptnox config btc derivation DERIVE
+
+History and Information
+~~~~~~~~~~~~~~~~~~~~~~~
+
+history
+^^^^^^^
+
+List performed signatures and transactions.
+
+.. code-block:: bash
+
+ cryptnox history [PAGE]
+
+**Arguments:**
+ - ``PAGE``: Page number to display (default: 1)
+
+**Note:** Shows up to 148 entries, 25 per page.
+
+Advanced Commands
+~~~~~~~~~~~~~~~~~
+
+get_xpub
+^^^^^^^^
+
+Get extended public key (xpub) for hierarchical deterministic wallets.
+
+.. code-block:: bash
+
+ cryptnox get_xpub [OPTIONS]
+
+**Options:**
+ - Derivation path
+ - Key type
+
+get_clearpubkey
+^^^^^^^^^^^^^^^
+
+Get clear (uncompressed) public key from the card.
+
+.. code-block:: bash
+
+ cryptnox get_clearpubkey [OPTIONS]
+
+decrypt
+^^^^^^^
+
+Decrypt data using the card's private key.
+
+.. code-block:: bash
+
+ cryptnox decrypt [OPTIONS]
+
+User Key Management
+~~~~~~~~~~~~~~~~~~~
+
+user_key list
+^^^^^^^^^^^^^
+
+List all configured user keys for authentication.
+
+.. code-block:: bash
+
+ cryptnox user_key list
+
+user_key add
+^^^^^^^^^^^^
+
+Add a new user key for authentication (AWS KMS, PIV card, Windows Hello).
+
+.. code-block:: bash
+
+ cryptnox user_key add TYPE [DESCRIPTION]
+
+**Available Types:**
+ - ``aws_kms``: AWS Key Management Service
+ - ``piv``: PIV-compatible smart card
+ - ``hello``: Windows Hello (biometric)
+
+**Example:**
+
+.. code-block:: bash
+
+ cryptnox user_key add aws_kms "My AWS Key"
+
+user_key delete
+^^^^^^^^^^^^^^^
+
+Delete a user key.
+
+.. code-block:: bash
+
+ cryptnox user_key delete TYPE
+
+Server Mode
+~~~~~~~~~~~
+
+server
+^^^^^^
+
+Start a server or establish connection to a remote server.
+
+.. code-block:: bash
+
+ cryptnox server [OPTIONS]
+
+**Options:**
+ - ``--port PORT``: Server port (default: 5050)
+ - ``--host HOST``: Server host (default: 0.0.0.0)
+
+**Use Case:** Remote card access over network
+
+Interactive Mode
+----------------
+
+Launch interactive CLI mode:
+
+.. code-block:: bash
+
+ cryptnox
+
+In interactive mode, you can:
+ - Execute commands without repeating ``cryptnox``
+ - Use ``use`` command to switch between multiple cards
+ - Use ``exit`` to quit
+
+**Example Session:**
+
+.. code-block:: text
+
+ $ cryptnox
+ Cryptnox Pro 2.9.1
+
+ > list
+ [Shows available cards]
+
+ > info
+ [Shows card information]
+
+ > exit
+
+BIP39 Passphrase Support
+-------------------------
+
+The ``seed recover`` and ``seed upload`` commands support BIP39 passphrases (also known as the 13th/25th word).
+
+What is a BIP39 Passphrase?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BIP39 passphrase is an optional additional word that enhances security:
+ - Acts as a "second factor" for your seed
+ - Creates a completely different wallet from the same mnemonic
+ - Must be remembered separately (not stored with the mnemonic)
+ - Cannot be recovered if forgotten
+
+Using BIP39 Passphrase
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**During seed upload (new wallet):**
+
+.. code-block:: bash
+
+ cryptnox seed upload
+
+The command will prompt:
+
+.. code-block:: text
+
+ Do you want to use a BIP39 passphrase? [y/N]
+
+If you choose ``yes``:
+ - Enter your desired passphrase
+ - Confirm the passphrase
+ - **Remember it!** You'll need it for recovery
+
+**During seed recover (existing wallet):**
+
+.. code-block:: bash
+
+ cryptnox seed recover
+
+If your wallet was created with a passphrase, you **must** provide the same passphrase when recovering.
+
+**Important Notes:**
+ - ⚠️ The passphrase is **NOT** backed up by AWS KMS
+ - ⚠️ If you forget your passphrase, your funds are **permanently lost**
+ - ✅ Same mnemonic + different passphrase = completely different wallet
+ - ✅ Passphrase can be any UTF-8 string (including spaces and special characters)
+
+Exit Codes
+----------
+
+The CLI returns the following exit codes:
+
+- ``0``: Success
+- ``-1``: Error occurred
+- ``-2``: Card error or card not found
+
+Error Handling
+--------------
+
+When errors occur:
+ - Detailed error messages are displayed
+ - Errors are logged to: ``~/.local/share/cryptnoxpro/error.log`` (Linux/macOS) or ``%LOCALAPPDATA%\\cryptnox\\cryptnoxpro\\error.log`` (Windows)
+ - You can report errors to help improve the application
+
+Examples
+--------
+
+**Initialize a new card:**
+
+.. code-block:: bash
+
+ cryptnox init
+
+**Generate and backup a seed:**
+
+.. code-block:: bash
+
+ cryptnox seed backup
+
+**Recover from existing mnemonic:**
+
+.. code-block:: bash
+
+ cryptnox seed recover
+
+**Send Bitcoin:**
+
+.. code-block:: bash
+
+ cryptnox btc send 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa 0.001 -n testnet
+
+**Send Ethereum:**
+
+.. code-block:: bash
+
+ cryptnox eth send 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.1 -n mainnet
+
+**View card info:**
+
+.. code-block:: bash
+
+ cryptnox info
+
+**Change PIN:**
+
+.. code-block:: bash
+
+ cryptnox change_pin
+
+See Also
+--------
+
+- :doc:`overview` - Overview of CryptnoxPro
+- :mod:`cryptnoxpro.command.seed` - Seed command implementation details
+- :doc:`cryptnoxpro.command` - All command implementations
+- :doc:`modules` - Complete API Reference
+
diff --git a/docs/conf.py b/docs/conf.py
index 950892a..0dfd197 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -8,6 +8,7 @@
import os
import sys
+
sys.path.insert(0, os.path.abspath(".."))
project = 'cryptnoxpro'
@@ -25,33 +26,79 @@
"sphinx.ext.viewcode",
]
+# Disable autosummary generation to prevent hangs
+autosummary_generate = False
+
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+# autodoc_mock_imports - Sphinx will create mock imports for these modules
+# This is safer than manual sys.modules mocking and prevents hangs
autodoc_mock_imports = [
- 'winsdk',
+ # Cryptnox
'cryptnoxpy',
- 'boto3',
- 'botocore',
- 'cryptography',
+ # Input/Output
'stdiomask',
'tabulate',
- 'requests',
+ # AWS
+ 'boto3',
+ 'botocore',
+ 'botocore.exceptions',
+ 'botocore.client',
+ 'botocore.config',
+ # Web3 and Ethereum
'web3',
- 'eth_typing',
+ 'web3.eth',
+ 'web3.contract',
+ 'web3.middleware',
'eth_account',
+ 'eth_account._utils',
+ 'eth_account._utils.legacy_transactions',
'eth_account.transactions',
'eth_account.account',
- 'eth_account._utils',
'eth_account.datastructures',
- 'pydantic',
- 'pydantic_core',
'eth_utils',
+ 'eth_utils.curried',
+ 'eth_typing',
+ 'eth_keys',
+ 'eth_rlp',
+ 'eth_abi',
+ 'eth_hash',
'hexbytes',
- 'enums',
- 'config'
+ 'ecdsa',
+ 'rlp',
+ # Validation
+ 'pydantic',
+ 'pydantic_core',
+ # Smart card
+ 'pyscard',
+ 'smartcard',
+ 'smartcard.CardConnection',
+ 'smartcard.System',
+ 'smartcard.Exceptions',
+ 'smartcard.CardType',
+ 'smartcard.CardRequest',
+ 'smartcard.util',
+ 'smartcard.scard',
+ # Utilities
+ 'cytoolz',
+ 'toolz',
+ 'winsdk',
+ 'base58',
]
+# Autodoc configuration
+autodoc_default_options = {
+ 'members': True,
+ 'member-order': 'bysource',
+ 'special-members': '__init__',
+ 'undoc-members': True,
+ 'exclude-members': '__weakref__'
+}
+
+# Set autodoc to not fail on import errors
+autoclass_content = 'both'
+
# Handle ambiguous cross-references
nitpicky = False
nitpick_ignore = [
diff --git a/docs/cryptnoxpro.command.card.rst b/docs/cryptnoxpro.command.card.rst
index 678bdf6..2084c6d 100644
--- a/docs/cryptnoxpro.command.card.rst
+++ b/docs/cryptnoxpro.command.card.rst
@@ -28,3 +28,17 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command.card`` package provides card management functionality and exports:
+
+.. py:currentmodule:: cryptnoxpro.command.card
+
+.. py:class:: Info
+ :no-index:
+
+ Command class for displaying card information. See :class:`cryptnoxpro.command.card.info.Info` for details.
+
+.. py:class:: Initialize
+ :no-index:
+
+ Command class for initializing cards. See :class:`cryptnoxpro.command.card.initialize.Initialize` for details.
+
diff --git a/docs/cryptnoxpro.command.erc_token.rst b/docs/cryptnoxpro.command.erc_token.rst
index b05d892..1717487 100644
--- a/docs/cryptnoxpro.command.erc_token.rst
+++ b/docs/cryptnoxpro.command.erc_token.rst
@@ -36,3 +36,17 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command.erc_token`` package provides ERC token management and exports:
+
+.. py:currentmodule:: cryptnoxpro.command.erc_token
+
+.. py:class:: Info
+ :no-index:
+
+ Command class for displaying ERC token information. See :class:`cryptnoxpro.command.erc_token.info.Info` for details.
+
+.. py:class:: Initialize
+ :no-index:
+
+ Command class for initializing ERC tokens. See :class:`cryptnoxpro.command.erc_token.initialize.Initialize` for details.
+
diff --git a/docs/cryptnoxpro.command.helper.rst b/docs/cryptnoxpro.command.helper.rst
index c8949ba..f0434e5 100644
--- a/docs/cryptnoxpro.command.helper.rst
+++ b/docs/cryptnoxpro.command.helper.rst
@@ -84,3 +84,7 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command.helper`` package provides utility functions and helper modules for command implementations.
+This package contains shared functionality used across multiple commands, including user interface components,
+security helpers, configuration management, and backup utilities.
+
diff --git a/docs/cryptnoxpro.command.options.rst b/docs/cryptnoxpro.command.options.rst
index af4453c..232bcfb 100644
--- a/docs/cryptnoxpro.command.options.rst
+++ b/docs/cryptnoxpro.command.options.rst
@@ -36,3 +36,12 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command.options`` package provides command-line argument parsing and exports:
+
+.. py:currentmodule:: cryptnoxpro.command.options
+
+.. py:function:: add(subparsers, command_class)
+ :no-index:
+
+ Add command-line options for a command class. See :func:`cryptnoxpro.command.options.options.add` for details.
+
diff --git a/docs/cryptnoxpro.command.rst b/docs/cryptnoxpro.command.rst
index 42008a3..f04e52f 100644
--- a/docs/cryptnoxpro.command.rst
+++ b/docs/cryptnoxpro.command.rst
@@ -200,3 +200,6 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command`` package provides command-line interface commands for interacting with Cryptnox cards.
+This package contains all command implementations that can be executed from the CLI.
+
diff --git a/docs/cryptnoxpro.command.user_keys.rst b/docs/cryptnoxpro.command.user_keys.rst
index cc089ce..94133ff 100644
--- a/docs/cryptnoxpro.command.user_keys.rst
+++ b/docs/cryptnoxpro.command.user_keys.rst
@@ -38,3 +38,27 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.command.user_keys`` package provides authentication functionality and exports:
+
+.. py:currentmodule:: cryptnoxpro.command.user_keys
+
+.. py:function:: add(data)
+ :no-index:
+
+ Add a new authentication method. See :func:`cryptnoxpro.command.user_keys.authentication.add` for details.
+
+.. py:function:: authenticate(data)
+ :no-index:
+
+ Authenticate using a configured method. See :func:`cryptnoxpro.command.user_keys.authentication.authenticate` for details.
+
+.. py:function:: delete(data)
+ :no-index:
+
+ Delete an authentication method. See :func:`cryptnoxpro.command.user_keys.authentication.delete` for details.
+
+.. py:function:: get(data)
+ :no-index:
+
+ Get information about authentication methods. See :func:`cryptnoxpro.command.user_keys.authentication.get` for details.
+
diff --git a/docs/cryptnoxpro.lib.cryptos.coins.rst b/docs/cryptnoxpro.lib.cryptos.coins.rst
index 6699707..a19a6b9 100644
--- a/docs/cryptnoxpro.lib.cryptos.coins.rst
+++ b/docs/cryptnoxpro.lib.cryptos.coins.rst
@@ -28,3 +28,12 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.lib.cryptos.coins`` package provides cryptocurrency coin implementations and exports:
+
+.. py:currentmodule:: cryptnoxpro.lib.cryptos.coins
+
+.. py:class:: Bitcoin
+ :no-index:
+
+ Bitcoin cryptocurrency implementation. See :class:`cryptnoxpro.lib.cryptos.coins.bitcoin.Bitcoin` for details.
+
diff --git a/docs/cryptnoxpro.lib.cryptos.rst b/docs/cryptnoxpro.lib.cryptos.rst
index e042543..b7a8289 100644
--- a/docs/cryptnoxpro.lib.cryptos.rst
+++ b/docs/cryptnoxpro.lib.cryptos.rst
@@ -140,3 +140,19 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.lib.cryptos`` package provides cryptocurrency utilities and re-exports functionality from:
+
+* :mod:`cryptnoxpro.lib.cryptos.blocks` - Block-related utilities
+* :mod:`cryptnoxpro.lib.cryptos.composite` - Composite key handling
+* :mod:`cryptnoxpro.lib.cryptos.deterministic` - Deterministic wallet functions
+* :mod:`cryptnoxpro.lib.cryptos.main` - Main crypto operations
+* :mod:`cryptnoxpro.lib.cryptos.mnemonic` - Mnemonic phrase handling
+* :mod:`cryptnoxpro.lib.cryptos.specials` - Special cryptocurrency operations
+* :mod:`cryptnoxpro.lib.cryptos.stealth` - Stealth address support
+* :mod:`cryptnoxpro.lib.cryptos.transaction` - Transaction handling
+* :mod:`cryptnoxpro.lib.cryptos.coins` - Coin implementations
+* :mod:`cryptnoxpro.lib.cryptos.keystore` - Key storage utilities
+* :mod:`cryptnoxpro.lib.cryptos.wallet` - Wallet functionality
+
+All public members from these modules are available directly from ``cryptnoxpro.lib.cryptos``.
+
diff --git a/docs/cryptnoxpro.lib.rst b/docs/cryptnoxpro.lib.rst
index ed15d2d..541ae76 100644
--- a/docs/cryptnoxpro.lib.rst
+++ b/docs/cryptnoxpro.lib.rst
@@ -17,3 +17,6 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.lib`` package provides library functionality for cryptocurrency operations.
+The main subpackage is :mod:`cryptnoxpro.lib.cryptos` which contains comprehensive cryptocurrency utilities.
+
diff --git a/docs/cryptnoxpro.rst b/docs/cryptnoxpro.rst
index 20f3b56..7407f2d 100644
--- a/docs/cryptnoxpro.rst
+++ b/docs/cryptnoxpro.rst
@@ -54,3 +54,11 @@ Module contents
:undoc-members:
:show-inheritance:
+The main ``cryptnoxpro`` package exports:
+
+.. py:data:: __version__
+ :type: str
+ :value: "2.9.1"
+
+ Current version of the CryptnoxPro package.
+
diff --git a/docs/cryptnoxpro.wallet.eth.rst b/docs/cryptnoxpro.wallet.eth.rst
index 51b3c9e..7537fed 100644
--- a/docs/cryptnoxpro.wallet.eth.rst
+++ b/docs/cryptnoxpro.wallet.eth.rst
@@ -28,3 +28,27 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.wallet.eth`` package provides Ethereum wallet utilities and exports:
+
+.. py:currentmodule:: cryptnoxpro.wallet.eth
+
+.. py:function:: address(public_key)
+ :no-index:
+
+ Generate an Ethereum address from a public key. See :func:`cryptnoxpro.wallet.eth.api.address` for details.
+
+.. py:class:: Api
+ :no-index:
+
+ Ethereum API interface. See :class:`cryptnoxpro.wallet.eth.api.Api` for details.
+
+.. py:function:: checksum_address(address_str)
+ :no-index:
+
+ Convert an address to checksummed format. See :func:`cryptnoxpro.wallet.eth.api.checksum_address` for details.
+
+.. py:class:: EthValidator
+ :no-index:
+
+ Ethereum address and transaction validator. See :class:`cryptnoxpro.wallet.eth.api.EthValidator` for details.
+
diff --git a/docs/cryptnoxpro.wallet.rst b/docs/cryptnoxpro.wallet.rst
index f930f56..843535b 100644
--- a/docs/cryptnoxpro.wallet.rst
+++ b/docs/cryptnoxpro.wallet.rst
@@ -36,3 +36,6 @@ Module contents
:undoc-members:
:show-inheritance:
+The ``cryptnoxpro.wallet`` package provides wallet functionality for various cryptocurrencies.
+It includes Bitcoin wallet operations, Ethereum wallet utilities, and validation functions.
+
diff --git a/docs/index.rst b/docs/index.rst
index 49fb59a..ea6d915 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -8,6 +8,7 @@ Welcome to the technical documentation of Cryptnoxpro.
:caption: Contents:
overview
+ cli
modules
license
diff --git a/setup.cfg b/setup.cfg
index 016cff5..5ff49fd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -8,7 +8,6 @@ keywords =
cryptography
bitcoin
ethereum
- cleos
cryptocurrency
wallet
license = GPLv3+