### Setup New Card with Satochip CLI Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Initialize a new Satochip card with a given label using the common-initial-setup command. ```commandline python3 satochip_cli.py common-initial-setup --label my-card-label ``` -------------------------------- ### Get Satochip CLI Help Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Display the help message for the satochip_cli, showing available commands and options. ```commandline python3 satochip_cli.py ``` -------------------------------- ### Install Pysatochip Source: https://github.com/toporin/pysatochip/blob/master/README-CLI.md Install the package with CLI support via pip or from source. ```commandline python3 -m pip install pysatochip[CLI] ``` ```commandline python3 setup.py install[CLI] ``` -------------------------------- ### Access CLI Help Source: https://github.com/toporin/pysatochip/blob/master/README-CLI.md Use the --help flag to list available commands or get details on specific commands. ```commandline python3 satochip-cli --help ``` ```commandline python3 satochip-cli satochip-sign-message --help ``` -------------------------------- ### Perform Initial Device Setup Source: https://context7.com/toporin/pysatochip/llms.txt Configures a new device with PINs, PUKs, and memory allocation. This operation is destructive and should only be performed on new or factory-reset devices. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Setup parameters pin_tries = 5 # Number of PIN attempts before lockout puk_tries = 5 # Number of PUK attempts before permanent lock pin = "12345678" # 4-16 character PIN puk = "123456789012" # PUK for PIN recovery memsize = 32768 # Memory size for objects memsize2 = 32768 # Secondary memory # Perform setup (only once per device) response, sw1, sw2 = cc.card_setup( pin_tries0=pin_tries, ublk_tries0=puk_tries, pin0=pin, ublk0=puk, pin_tries1=pin_tries, ublk1=puk_tries, pin1=pin, ublk1=puk, memsize=memsize, memsize2=memsize2, create_object_ACL=0x01, create_key_ACL=0x01, create_pin_ACL=0x01 ) if sw1 == 0x90 and sw2 == 0x00: print("Device setup completed successfully!") else: print(f"Setup failed with error: {hex(sw1*256 + sw2)}") ``` -------------------------------- ### Perform Satocash Operations Source: https://github.com/toporin/pysatochip/blob/master/README-CLI.md Commands for card setup, status checks, balance retrieval, and token management. ```commandline python3 satochip_cli.py --verbose common-initial-setup --label "my label" ``` ```commandline python3 satochip_cli.py --verbose satocash-get-status ``` ```commandline python3 satochip_cli.py --verbose satocash-get-balances --unit "sat" ``` ```commandline python3 satochip_cli.py --verbose satocash-import-tokenv4 --tokenv4 "..." ``` ```commandline python3 satochip_cli.py --verbose satocash-export-tokenv4 --unit "sat" --amount "10" ``` -------------------------------- ### Get Public Key from Keyslot with Satochip CLI Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Retrieve the public key corresponding to a private key stored in a specific keyslot on the Satochip. ```commandline python3 satochip_cli.py satochip-get-pubkey-from-keyslot --keyslot 0 ``` -------------------------------- ### Manage Nostr Keys and Signing Source: https://github.com/toporin/pysatochip/blob/master/README-CLI.md Import keys, retrieve public keys, and sign Nostr events using a hardware card. ```commandline python3 satochip_cli.py --verbose satochip-import-privkey --keyslot 0 --privkey aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 ``` ```commandline python3 satochip_cli.py --verbose satochip-get-pubkey-from-keyslot --keyslot 0 ``` ```commandline python3 satochip_cli.py --verbose satochip-sign-nostr-event --keyslot 0 --message "Hello, world" --kind 1 --broadcast ``` ```commandline python3 satochip_cli.py --verbose satochip-import-unencrypted-mnemonic ``` ```commandline python3 satochip_cli.py --verbose satochip-sign-nostr-event --path "m/44'/0'/0'/0/0" --message "Hello, world" --kind 1 --broadcast ``` -------------------------------- ### Initialize CardConnector Source: https://context7.com/toporin/pysatochip/llms.txt Establishes a connection to a Satochip device and retrieves status information. Requires a compatible smartcard reader and the pyscard library. ```python from pysatochip.CardConnector import CardConnector import logging # Initialize connector with optional logging level and card filter cc = CardConnector( client=None, # Optional client for callbacks loglevel=logging.WARNING, # Logging level card_filter="satochip" # Filter: "satochip", "seedkeeper", "satodime", "satocash", or None for all ) # Check if card is present if cc.card_present: print("Card detected!") # Get card status response, sw1, sw2, status = cc.card_get_status() print(f"Protocol version: {status['protocol_major_version']}.{status['protocol_minor_version']}") print(f"Setup done: {status['setup_done']}") print(f"Is seeded: {status.get('is_seeded', False)}") print(f"Needs 2FA: {status.get('needs2FA', False)}") print(f"PIN tries remaining: {status.get('PIN0_remaining_tries', 'N/A')}") # Disconnect when done cc.card_disconnect() ``` -------------------------------- ### Import Private Key with Satochip CLI Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Import a secp256k1 private key into a specified keyslot on the Satochip. The private key must be provided in hexadecimal format. ```commandline python3 satochip_cli.py --verbose satochip-import-privkey --keyslot 0 --privkey aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 ``` -------------------------------- ### Use Command Line Interface Source: https://context7.com/toporin/pysatochip/llms.txt Execute common card operations directly from the terminal. ```bash # Install with CLI support pip install pysatochip[CLI] # Get help satochip-cli --help # Get card status satochip-cli --verbose common-card-get-status # Setup a new card satochip-cli --verbose common-initial-setup --label "My Wallet" # Import a BIP39 mnemonic satochip-cli --verbose satochip-import-unencrypted-mnemonic # Get xpub for a derivation path satochip-cli --verbose satochip-get-xpub --path "m/44'/0'/0'" --xtype standard # Sign a message satochip-cli --verbose satochip-sign-message --path "m/44'/0'/0'/0/0" --message "Hello World" # Import a private key to specific slot (for Nostr) satochip-cli --verbose satochip-import-privkey --keyslot 0 --privkey ``` -------------------------------- ### Satodime operations via CLI Source: https://context7.com/toporin/pysatochip/llms.txt Retrieves device status or seals a key in a specific keyslot. ```bash satochip-cli --verbose satodime-get-status ``` ```bash satochip-cli --verbose satodime-seal-key --keyslot 0 ``` -------------------------------- ### Sign Hash with Schnorr using Satochip CLI Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Sign a hash using the Schnorr signature algorithm with a private key stored in a specified keyslot on the Satochip. ```commandline python3 satochip_cli.py satochip-sign-schnorr-hash --hash 796962c8f2a7b8540f818cbe37d2894b1ab4b71bccddced12e2a4dc11d8802c3 --keyslot 0 ``` -------------------------------- ### Satocash operations via CLI Source: https://context7.com/toporin/pysatochip/llms.txt Retrieves Satocash status or account balances in a specified unit. ```bash satochip-cli --verbose satocash-get-status ``` ```bash satochip-cli --verbose satocash-get-balances --unit "sat" ``` -------------------------------- ### Sign Nostr Event with Satochip CLI Source: https://github.com/toporin/pysatochip/blob/master/CHANGELOG.md Use the satochip_cli to sign a Nostr event. Ensure the message, kind, and keyslot are correctly specified. ```commandline python3 satochip_cli.py --verbose satochip-sign-nostr-event --keyslot 0 --message "Hello, world" --kind 1 --broadcast ``` -------------------------------- ### Establish Secure Channel Communication Source: https://context7.com/toporin/pysatochip/llms.txt Check for and initiate encrypted communication channels with compatible devices. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Check if secure channel is needed response, sw1, sw2, status = cc.card_get_status() if status.get('needs_secure_channel', False): print("Secure channel required") # Initiate secure channel (usually done automatically) peer_pubkey = cc.card_initiate_secure_channel() print(f"Secure channel established with: {peer_pubkey.get_public_key_bytes(True).hex()}") # All subsequent commands are automatically encrypted/decrypted # The CardConnector handles this transparently # Check secure channel status if cc.sc is not None: print("Secure channel is active") ``` -------------------------------- ### Verify Device Authenticity Source: https://context7.com/toporin/pysatochip/llms.txt Validate hardware authenticity using device certificates. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Verify device authenticity is_authentic, txt_ca, txt_subca, txt_device, txt_error = cc.card_verify_authenticity() if is_authentic: print("Device is authentic!") print(f"Root CA: {txt_ca}") print(f"Sub CA: {txt_subca}") print(f"Device cert: {txt_device}") else: print(f"Authenticity check failed: {txt_error}") # Export device certificate (PEM format) cert_pem = cc.card_export_perso_certificate() print(f"Device certificate:\n{cert_pem}") ``` -------------------------------- ### Import BIP32 Seed Source: https://context7.com/toporin/pysatochip/llms.txt Imports a master seed into the hardware device for HD wallet derivation. Note that imported seeds are non-extractable. ```python from pysatochip.CardConnector import CardConnector from hashlib import pbkdf2_hmac cc = CardConnector() ``` -------------------------------- ### Derive BIP32 Extended Keys Source: https://context7.com/toporin/pysatochip/llms.txt Derives BIP32 extended keys (public and private) and xpubs from the imported seed. Supports various derivation paths and xpub types including standard, SegWit, and nested SegWit. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Derive extended public key for a given path path = "m/44'/0'/0'" # BIP44 Bitcoin account 0 # Get pubkey and chaincode pubkey, chaincode = cc.card_bip32_get_extendedkey(path) print(f"Public key: {pubkey.get_public_key_bytes(True).hex()}") print(f"Chaincode: {chaincode.hex()}") # Get xpub in various formats # Supported xtypes: 'standard', 'p2wpkh-p2sh', 'p2wpkh', 'p2wsh-p2sh', 'p2wsh' xpub = cc.card_bip32_get_xpub( path=path, xtype='standard', # xpub format is_mainnet=True ) print(f"xpub: {xpub}") # SegWit native (zpub) zpub = cc.card_bip32_get_xpub( path="m/84'/0'/0'", xtype='p2wpkh', is_mainnet=True ) print(f"zpub: {zpub}") # Get authentikey (unique device identifier) authentikey = cc.card_bip32_get_authentikey() print(f"Authentikey: {authentikey.get_public_key_bytes(True).hex()}") ``` -------------------------------- ### Schnorr Signing (Taproot) Source: https://context7.com/toporin/pysatochip/llms.txt This section covers Schnorr signing for Taproot transactions using the card_sign_schnorr_hash method, adhering to BIP340/BIP341 standards. It includes steps for key derivation, transaction hashing, optional key tweaking, and the signing process. ```APIDOC ## POST /api/sign_schnorr ### Description Signs a transaction hash using Schnorr signatures for Taproot transactions (BIP340/BIP341). ### Method POST ### Endpoint /api/sign_schnorr ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **keynbr** (integer) - Required - BIP32 key number. - **txhash** (list[int]) - Required - 32-byte transaction hash to sign. - **chalresponse** (list[int] | None) - Optional - 2FA challenge response if enabled. ### Request Example ```json { "keynbr": 255, "txhash": [227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 150, 251, 185, 36, 39, 174, 65, 230, 100, 155, 147, 76, 164, 149, 153, 183, 120, 82, 181, 85], "chalresponse": null } ``` ### Response #### Success Response (200) - **response** (bytes) - 64-byte Schnorr signature. - **sw1** (int) - Status word 1 (should be 0x90). - **sw2** (int) - Status word 2 (should be 0x00). #### Response Example ```json { "response": "1a2b3c4d...", "sw1": 144, "sw2": 0 } ``` #### Error Response (Non-200) - **response** (None) - No signature data. - **sw1** (int) - Status word 1. - **sw2** (int) - Status word 2. #### Error Response Example ```json { "response": null, "sw1": 26, "sw2": 16 } ``` ``` -------------------------------- ### Parse and Sign Bitcoin Transactions Source: https://context7.com/toporin/pysatochip/llms.txt Handles Bitcoin transaction parsing and signing. The transaction must be parsed first to compute the hash on the device, then signed with the appropriate key. Supports SegWit. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Raw transaction bytes (example - simplified) raw_tx = bytes.fromhex( "0100000001" # version "0000000000000000000000000000000000000000000000000000000000000000" # prev txid "00000000" # prev vout "00" # script length "ffffffff" # sequence "01" # output count "0000000000000000" # value "00" # script length "00000000" # locktime ) # Parse transaction (computes tx hash on device) response, sw1, sw2, tx_hash, needs_2fa = cc.card_parse_transaction( transaction=raw_tx, is_segwit=False # Set True for SegWit transactions ) print(f"Transaction hash: {bytes(tx_hash).hex()}") print(f"Requires 2FA: {needs_2fa}") # Derive signing key path = "m/44'/0'/0'/0/0" pubkey, chaincode = cc.card_bip32_get_extendedkey(path) ``` -------------------------------- ### Generate Seed from Mnemonic Source: https://context7.com/toporin/pysatochip/llms.txt Generates a seed from a BIP39 mnemonic phrase and passphrase using PBKDF2-HMAC-SHA512. The generated seed can then be imported into the hardware device. ```python from pysatochip.CardConnector import CardConnector from hashlib import pbkdf2_hmac mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" passphrase = "" seed = pbkdf2_hmac( 'sha512', mnemonic.encode('utf-8'), ('mnemonic' + passphrase).encode('utf-8'), 2048, 64 ) cc = CardConnector() authentikey = cc.card_bip32_import_seed(seed.hex()) if authentikey: print("Seed imported successfully!") print(f"Authentikey (device identifier): {authentikey.get_public_key_bytes(True).hex()}") print(f"Device is now seeded: {cc.is_seeded}") else: print("Seed import failed") # Reset seed (requires PIN and optional 2FA HMAC) # WARNING: This erases the seed permanently! response, sw1, sw2 = cc.card_reset_seed(pin="12345678", hmac=[]) ``` -------------------------------- ### Sign a Nostr event via CLI Source: https://context7.com/toporin/pysatochip/llms.txt Signs a Nostr event using a specific keyslot and message. ```bash satochip-cli --verbose satochip-sign-nostr-event --keyslot 0 --message "Hello Nostr" --kind 1 ``` -------------------------------- ### Configure and Reset Two-Factor Authentication (2FA) Source: https://context7.com/toporin/pysatochip/llms.txt Enables or resets 2FA on the card. When enabled, transactions exceeding a specified amount limit require secondary approval. This involves setting an HMAC secret and optionally encrypting transaction data for a 2FA app. ```python from pysatochip.CardConnector import CardConnector from os import urandom cc = CardConnector() # Generate a 20-byte secret for 2FA hmac_secret = urandom(20) # Enable 2FA with transaction amount limit response, sw1, sw2 = cc.card_set_2FA_key( hmacsha160_key=hmac_secret, amount_limit=100000 # Satoshis - transactions above require 2FA ) if sw1 == 0x90 and sw2 == 0x00: print("2FA enabled successfully!") print(f"Store this secret securely: {hmac_secret.hex()}") print(f"2FA status: {cc.needs_2FA}") else: print(f"2FA setup failed: {hex(sw1*256 + sw2)}") # Encrypt transaction data for 2FA app tx_data = "Transaction details for approval" id_2fa, encrypted_msg = cc.card_crypt_transaction_2FA(tx_data, is_encrypt=True) print(f"2FA ID: {id_2fa}") print(f"Encrypted data: {encrypted_msg}") # Reset 2FA (requires the secret) import hmac import hashlib challenge = b"Reset2FA" # Challenge message chalresponse = hmac.new(hmac_secret, challenge, hashlib.sha1).digest() response, sw1, sw2 = cc.card_reset_2FA_key(chalresponse) ``` -------------------------------- ### Operate Satodime Bearer Tokens Source: https://context7.com/toporin/pysatochip/llms.txt Manage key slots, seal/unseal keys, and handle ownership transfers on Satodime devices. ```python from pysatochip.CardConnector import CardConnector from os import urandom cc = CardConnector(card_filter="satodime") # Get Satodime status response, sw1, sw2, status = cc.satodime_get_status() print(f"Number of key slots: {status['max_num_keys']}") print(f"Key states: {status['satodime_keys_status']}") # Get status of a specific key slot key_nbr = 0 response, sw1, sw2, keyslot = cc.satodime_get_keyslot_status(key_nbr) print(f"Key {key_nbr} status: {keyslot['key_status_txt']}") print(f"Asset type: {keyslot['key_asset_txt']}") print(f"SLIP44: {keyslot['key_slip44_txt']}") # Set key slot metadata (for uninitialized slots) response, sw1, sw2 = cc.satodime_set_keyslot_status_part0( key_nbr=0, RFU1=0, RFU2=0, key_asset=0x01, # 0x01 = Coin key_slip44=[0x80, 0x00, 0x00, 0x00], # Bitcoin mainnet key_contract=[], # For tokens key_tokenid=[] # For NFTs ) # Seal a key (generates private key on device) entropy = urandom(32) # User-provided entropy response, sw1, sw2, pubkey, pubkey_comp = cc.satodime_seal_key( key_nbr=0, entropy_user=entropy ) print(f"Sealed key pubkey: {bytes(pubkey_comp).hex()}") # Get public key of sealed slot response, sw1, sw2, pubkey, pubkey_comp = cc.satodime_get_pubkey(key_nbr=0) print(f"Public key: {bytes(pubkey_comp).hex()}") # Unseal key (reveals private key - ownership transfer) response, sw1, sw2, entropy, privkey = cc.satodime_unseal_key(key_nbr=0) print(f"Private key: {bytes(privkey).hex()}") # Reset slot (after unseal) for reuse response, sw1, sw2 = cc.satodime_reset_key(key_nbr=0) # Transfer ownership (resets unlock secret) response, sw1, sw2 = cc.satodime_initiate_ownership_transfer() ``` -------------------------------- ### Two-Factor Authentication (2FA) Source: https://context7.com/toporin/pysatochip/llms.txt API endpoints for configuring and managing two-factor authentication. Includes methods to set a 2FA key with an amount limit, reset the 2FA key, and encrypt transaction data for 2FA approval. ```APIDOC ## API Endpoints for 2FA Management ### POST /api/set_2FA_key #### Description Configures two-factor authentication (2FA) for the device. Transactions exceeding the specified amount limit will require 2FA approval. #### Parameters - **hmacsha160_key** (bytes) - Required - The 20-byte secret key for HMAC-SHA1 verification. - **amount_limit** (integer) - Required - The transaction amount limit in satoshis. Transactions above this limit require 2FA. #### Request Example ```json { "hmacsha160_key": "a1b2c3d4e5f6...", "amount_limit": 100000 } ``` #### Response Example (Success) ```json { "message": "2FA enabled successfully!", "sw1": 144, "sw2": 0 } ``` ### POST /api/reset_2FA_key #### Description Resets the configured 2FA key. Requires a valid challenge response generated using the current HMAC-SHA1 secret. #### Parameters - **chalresponse** (bytes) - Required - The HMAC-SHA1 digest of the challenge message. #### Request Example ```json { "chalresponse": "abcdef123456..." } ``` #### Response Example (Success) ```json { "message": "2FA reset successfully.", "sw1": 144, "sw2": 0 } ``` ### POST /api/crypt_transaction_2FA #### Description Encrypts transaction data for display and approval on a secondary 2FA device. #### Parameters - **data** (string) - Required - The transaction details to encrypt. - **is_encrypt** (boolean) - Required - Set to true to encrypt. #### Request Example ```json { "data": "Transaction details for approval", "is_encrypt": true } ``` #### Response Example (Success) ```json { "id_2fa": "unique_id_123", "encrypted_msg": "encrypted_data_string", "sw1": 144, "sw2": 0 } ``` ``` -------------------------------- ### Schnorr Signing for Taproot Transactions Source: https://context7.com/toporin/pysatochip/llms.txt Signs a transaction hash using Schnorr signatures (BIP340/BIP341) for Taproot transactions. Requires deriving the Taproot path and optionally tweaking the private key. The output is a 64-byte Schnorr signature. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # Derive key path = "m/86'/0'/0'/0/0" # BIP86 Taproot path pubkey, chaincode = cc.card_bip32_get_extendedkey(path) # Transaction hash to sign (32 bytes) tx_hash = list(bytes.fromhex( "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" )) # Optional: Tweak the private key for Taproot # bypass_flag=True skips tweaking (for script path spending) tweak = list(bytes(32)) # 32-byte tweak value response, sw1, sw2 = cc.card_taproot_tweak_privkey( keynbr=0xFF, tweak=tweak, bypass_flag=False ) # Sign with Schnorr response, sw1, sw2 = cc.card_sign_schnorr_hash( keynbr=0xFF, txhash=tx_hash, chalresponse=None # 2FA if enabled ) if sw1 == 0x90 and sw2 == 0x00: schnorr_sig = bytes(response) print(f"Schnorr signature (64 bytes): {schnorr_sig.hex()}") else: print(f"Schnorr signing failed: {hex(sw1*256 + sw2)}") ``` -------------------------------- ### Sign Transaction Source: https://context7.com/toporin/pysatochip/llms.txt This section details how to sign a transaction using the card_sign_transaction method. It includes parameters for key number, transaction hash, and an optional 2FA challenge response. ```APIDOC ## POST /api/sign_transaction ### Description Signs a transaction using a specified key and transaction hash. Supports optional 2FA challenge response. ### Method POST ### Endpoint /api/sign_transaction ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **keynbr** (integer) - Required - BIP32 key number. - **txhash** (list[int]) - Required - Hash of the transaction to sign. - **chalresponse** (list[int] | None) - Optional - 2FA challenge response if needed. ### Request Example ```json { "keynbr": 255, "txhash": [227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 150, 251, 185, 36, 39, 174, 65, 230, 100, 155, 147, 76, 164, 149, 153, 183, 120, 82, 181, 85], "chalresponse": null } ``` ### Response #### Success Response (200) - **response** (bytes) - DER-encoded signature. - **sw1** (int) - Status word 1 (should be 0x90). - **sw2** (int) - Status word 2 (should be 0x00). #### Response Example ```json { "response": "30450221008a1f...", "sw1": 144, "sw2": 0 } ``` #### Error Response (Non-200) - **response** (None) - No signature data. - **sw1** (int) - Status word 1. - **sw2** (int) - Status word 2. #### Error Response Example ```json { "response": null, "sw1": 26, "sw2": 16 } ``` ``` -------------------------------- ### Verify and Unblock PIN Source: https://context7.com/toporin/pysatochip/llms.txt Handles PIN verification for device access and provides a mechanism to unblock the PIN using a PUK. Requires handling specific exceptions for security states. ```python from pysatochip.CardConnector import ( CardConnector, WrongPinError, PinBlockedError, PinRequiredError ) cc = CardConnector() try: # Verify PIN - can pass PIN directly or use cached value response, sw1, sw2 = cc.card_verify_PIN_simple(pin="12345678") if sw1 == 0x90 and sw2 == 0x00: print("PIN verified successfully!") # PIN is now cached for future operations print(f"PIN cached: {cc.is_pin_set()}") except WrongPinError as e: print(f"Wrong PIN! Attempts remaining: {e.pin_left}") except PinBlockedError: print("PIN is blocked! Use PUK to unblock.") except PinRequiredError: print("No PIN provided and no cached PIN available.") # To unblock a blocked PIN using PUK puk = list("123456789012".encode("utf-8")) response, sw1, sw2 = cc.card_unblock_PIN(pin_nbr=0, ublk=puk) ``` -------------------------------- ### SeedKeeper operations via CLI Source: https://context7.com/toporin/pysatochip/llms.txt Lists stored secrets or generates a new master seed. ```bash satochip-cli --verbose seedkeeper-list-secrets ``` ```bash satochip-cli --verbose seedkeeper-generate-masterseed --label "Backup Seed" ``` -------------------------------- ### Sign Arbitrary Messages Source: https://context7.com/toporin/pysatochip/llms.txt Signs arbitrary messages using keys derived from the BIP32 seed. The function returns a compact signature suitable for verification and address recovery. Supports altcoin prefixes. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector() # First derive the key for the signing path path = "m/44'/0'/0'/0/0" pubkey, chaincode = cc.card_bip32_get_extendedkey(path) # Sign a message message = "Hello, Satochip!" response, sw1, sw2, compact_sig = cc.card_sign_message( keynbr=0xFF, # 0xFF = use BIP32 derived key pubkey=pubkey, # Public key for recovery message=message, # Message to sign (str or bytes) hmac=b'', # 2FA HMAC if enabled altcoin=None # Optional: altcoin message prefix ) if sw1 == 0x90 and sw2 == 0x00: print(f"Signature: {compact_sig.hex()}") # Signature format: [recovery_id(1) | r(32) | s(32)] print(f"Recovery ID: {compact_sig[0]}") print(f"r: {compact_sig[1:33].hex()}") print(f"s: {compact_sig[33:65].hex()}") else: print(f"Signing failed: {hex(sw1*256 + sw2)}") # Sign message for altcoin (different magic prefix) response, sw1, sw2, sig = cc.card_sign_message( keynbr=0xFF, pubkey=pubkey, message="Altcoin message", altcoin="Litecoin Signed Message:\n" ) ``` -------------------------------- ### Sign Transaction with ECDSA Source: https://context7.com/toporin/pysatochip/llms.txt Signs a transaction hash using ECDSA. Ensure the card is initialized and the key is available. The response contains the DER-encoded signature if successful. ```python chalresponse = None # 2FA challenge response if needed response, sw1, sw2 = cc.card_sign_transaction( keynbr=0xFF, # BIP32 key txhash=tx_hash, # Hash from parse step chalresponse=chalresponse ) if sw1 == 0x90 and sw2 == 0x00: # Response contains DER-encoded signature print(f"DER Signature: {bytes(response).hex()}") else: print(f"Signing failed: {hex(sw1*256 + sw2)}") ``` -------------------------------- ### SeedKeeper - List Secret Headers Source: https://context7.com/toporin/pysatochip/llms.txt Retrieves a list of headers for all secrets stored on the SeedKeeper. Each header contains the secret's ID, type, and label, allowing you to enumerate stored secrets. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector(card_filter="seedkeeper") # List all secrets headers = cc.seedkeeper_list_secret_headers() for header in headers: print(f"ID: {header['id']}, Type: {header['type']}, Label: {header['label']}") ``` -------------------------------- ### SeedKeeper - Import Secret Source: https://context7.com/toporin/pysatochip/llms.txt Imports an existing secret into SeedKeeper. The secret must be provided in a dictionary containing a header (with type, export rights, and label) and the secret data itself. Returns the imported secret ID and fingerprint. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector(card_filter="seedkeeper") # Import a secret secret_data = list(bytes.fromhex("aabbccdd" * 8)) # 32 bytes secret_dic = { 'header': cc.make_header( secret_type=0x10, # Masterseed export_rights=0x01, # Plaintext export allowed label="Imported Seed" ), 'secret_list': secret_data } secret_id, fingerprint = cc.seedkeeper_import_secret(secret_dic) print(f"Imported secret ID: {secret_id}") ``` -------------------------------- ### Manage Secrets with SeedKeeper Source: https://context7.com/toporin/pysatochip/llms.txt Operations for exporting and resetting secrets stored on a SeedKeeper device. ```python secret_dict = cc.seedkeeper_export_secret(sid=secret_id) print(f"Exported secret: {secret_dict['secret']}") # Delete a secret response, sw1, sw2, dic = cc.seedkeeper_reset_secret(sid=secret_id) print(f"Secret deleted: {dic['is_reset']}") ``` -------------------------------- ### SeedKeeper - Generate Random Secret Source: https://context7.com/toporin/pysatochip/llms.txt Generates a random secret, such as a password, on the SeedKeeper. Specify the secret type, size, export rights, and label. Optionally, you can provide additional entropy. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector(card_filter="seedkeeper") # Generate a random secret (e.g., password) response, sw1, sw2, dic = cc.seedkeeper_generate_random_secret( stype=0x90, # Type: Password subtype=0x00, size=32, # 32 bytes export_rights=0x01, label="My Password", save_entropy=0x00, # Don't save entropy separately entropy=b"" # Additional entropy (optional) ) print(f"Password ID: {dic['id']}, Fingerprint: {dic['fingerprint']}") ``` -------------------------------- ### SeedKeeper - Generate Master Seed Source: https://context7.com/toporin/pysatochip/llms.txt Generates a master seed on the SeedKeeper device. You can specify the seed size, export rights (plaintext or encrypted), and a label for identification. The output includes the secret ID and a fingerprint. ```python from pysatochip.CardConnector import CardConnector cc = CardConnector(card_filter="seedkeeper") # Get SeedKeeper-specific status response, sw1, sw2, status = cc.seedkeeper_get_status() print(f"Number of secrets: {status['nb_secrets']}") print(f"Free memory: {status['free_memory']} bytes") # Generate a master seed on the device response, sw1, sw2, secret_id, fingerprint = cc.seedkeeper_generate_masterseed( seed_size=64, # 64 bytes = 512 bits export_rights=0x01, # 0x00=forbidden, 0x01=plaintext, 0x02=encrypted only label="My BTC Seed" ) print(f"Generated seed ID: {secret_id}, Fingerprint: {fingerprint}") ``` -------------------------------- ### SeedKeeper - Secret Management Source: https://context7.com/toporin/pysatochip/llms.txt API endpoints for SeedKeeper, a secure storage for secrets like seeds, mnemonics, and passwords. Supports generating, importing, and listing secrets with configurable export rights. ```APIDOC ## SeedKeeper API Endpoints ### GET /api/seedkeeper/status #### Description Retrieves the current status of the SeedKeeper, including the number of stored secrets and available memory. #### Response Example (Success) ```json { "nb_secrets": 5, "free_memory": 10240, "sw1": 144, "sw2": 0 } ``` ### POST /api/seedkeeper/generate_masterseed #### Description Generates a new master seed on the device. Allows configuration of seed size, export rights, and a label. #### Parameters - **seed_size** (integer) - Required - The size of the seed in bytes (e.g., 64 for 512 bits). - **export_rights** (integer) - Required - Defines export permissions (e.g., 0x01 for plaintext). - **label** (string) - Required - A user-defined label for the seed. #### Request Example ```json { "seed_size": 64, "export_rights": 1, "label": "My BTC Seed" } ``` #### Response Example (Success) ```json { "secret_id": "seed_id_abc", "fingerprint": "1234abcd", "sw1": 144, "sw2": 0 } ``` ### POST /api/seedkeeper/generate_random_secret #### Description Generates a random secret of a specified type and size, such as a password or API key. #### Parameters - **stype** (integer) - Required - The type of secret (e.g., 0x90 for Password). - **subtype** (integer) - Optional - Subtype of the secret. - **size** (integer) - Required - The size of the secret in bytes. - **export_rights** (integer) - Required - Defines export permissions. - **label** (string) - Required - A user-defined label for the secret. - **save_entropy** (integer) - Optional - Whether to save entropy separately (0x00=No, 0x01=Yes). - **entropy** (bytes) - Optional - Additional entropy to use for generation. #### Request Example ```json { "stype": 144, "subtype": 0, "size": 32, "export_rights": 1, "label": "My Password", "save_entropy": 0, "entropy": "" } ``` #### Response Example (Success) ```json { "id": "secret_id_xyz", "fingerprint": "abcd1234", "sw1": 144, "sw2": 0 } ``` ### POST /api/seedkeeper/import_secret #### Description Imports an existing secret into the SeedKeeper. Requires a structured dictionary containing header information and the secret data. #### Parameters - **secret_dic** (object) - Required - Dictionary containing secret details: - **header** (object) - Required - Header information: - **secret_type** (integer) - Required - Type of the secret. - **export_rights** (integer) - Required - Export permissions. - **label** (string) - Required - Label for the secret. - **secret_list** (list[int]) - Required - The secret data as a list of bytes. #### Request Example ```json { "secret_dic": { "header": { "secret_type": 16, "export_rights": 1, "label": "Imported Seed" }, "secret_list": [170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221, 170, 187, 204, 221] } } ``` #### Response Example (Success) ```json { "secret_id": "imported_seed_id", "fingerprint": "efgh5678", "sw1": 144, "sw2": 0 } ``` ### GET /api/seedkeeper/list_secret_headers #### Description Retrieves a list of headers for all secrets currently stored in the SeedKeeper. #### Response Example (Success) ```json [ { "id": "seed_id_abc", "type": 16, "label": "My BTC Seed" }, { "id": "secret_id_xyz", "type": 144, "label": "My Password" } ] ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.