From 524a06099c3f379b5612458f4ee9f9f0acf5cd0f Mon Sep 17 00:00:00 2001 From: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> Date: Thu, 14 May 2026 12:57:36 -0400 Subject: [PATCH] python comments --- docs/LEZ testnet v0.1 tutorials/keycard.md | 8 +- .../keycard_applets/LEE_keycard.cap | Bin 0 -> 102136 bytes keycard_wallet/keycard_applets/math.cap | Bin 0 -> 4874 bytes keycard_wallet/python/keycard_wallet.py | 122 ++++++++++++++++++ keycard_wallet/src/python_path.rs | 7 +- wallet/src/cli/account.rs | 2 +- wallet_with_keycard.sh | 4 +- 7 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 keycard_wallet/keycard_applets/LEE_keycard.cap create mode 100644 keycard_wallet/keycard_applets/math.cap create mode 100644 keycard_wallet/python/keycard_wallet.py diff --git a/docs/LEZ testnet v0.1 tutorials/keycard.md b/docs/LEZ testnet v0.1 tutorials/keycard.md index 78ce8441..460b70f2 100644 --- a/docs/LEZ testnet v0.1 tutorials/keycard.md +++ b/docs/LEZ testnet v0.1 tutorials/keycard.md @@ -12,12 +12,12 @@ Installation: 1. Install math applet on your keycard; this process only needs to be done once. In the root of repo: ``` - cd python/keycard_applets + cd keycard_wallet/keycard_applets java -jar gp.jar --key c212e073ff8b4bbfaff4de8ab655221f --load math.cap ``` 2. Install `keycard-desktop` from [github](https://github.com/choppu/keycard-desktop) - Keycard Desktop is used to install the LEE key protocol to a blank keycard. - - Select (Re)Install Applet and upload the key binary (`python/keycard_applets/LEE_keycard.cap`). + - Select (Re)Install Applet and upload the key binary (`keycard_wallet/keycard_applets/LEE_keycard.cap`). ![keycard-desktop.png](keycard-desktop.png) ## Wallet with Keycard @@ -25,13 +25,13 @@ Keycard functionality is available to Wallet CLI by setting up the following Pyt ```bash # Install appropriate version of `keycard-py`. -git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git python/keycard-py +git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git keycard_wallet/python/keycard-py # Set up virtual environment. python3 -m venv venv source venv/bin/activate pip install pyscard mnemonic ecdsa pyaes -pip install -e python/keycard-py +pip install -e keycard_wallet/python/keycard-py ``` **Important**: Keycard wallet commands only work within the virtual environment. diff --git a/keycard_wallet/keycard_applets/LEE_keycard.cap b/keycard_wallet/keycard_applets/LEE_keycard.cap new file mode 100644 index 0000000000000000000000000000000000000000..b44835c455a351bbd8b8a2888ec5d4c9f444f38b GIT binary patch literal 102136 zcmeFad0<^t)i=EN*=M>#?maid?Y$Xq+NMo9q)j@dgwot5X&aj+AxVc&Xp*M4ZQ2Z% zB!x5;NLrvkTMCGe45G}Ucqv0gP-IY0Ktw@Q1QAgmR8%HWne+YDKIdj=E6?-&^L>B3 zZ_<;q_Pq95Yp=ETI{Tb9tPyHDGfk7FwO(^3oA8s)RJOLdIXbtdZsokS(Yl(I)lJRC zYgc~yG-F@9dTsyp^R0{DdgkrCfiAz&(pLZU+9&>X=%Xu#eqTH9+U$jQuU+(7Wybf@ zMn7`z^VAjm==I1I8^7oO=&l#vdMNdg8=rfB<{c|vShsH*f9HG6{8v}};itxZZR_`4 za-;vwZ(8^A$KO3;=X3v+civlfC5{#Hc{e?E^%dV)e@nv)u970pm1lRafBTc@ihcL) zTXOix`Ad2$vR;_~>brltb~)d6eQe+NuQ+(>)>|LxS)F~|%g_A#oJT!Rrro;E^YEYc ze*2+?m)-2m`pNE>FZ^lz$p@Z3?=8=({a?Or)tB#``{sRrd8A_Com~ai7u?Ui_{aZx zW=hR_uG{W>W!cRa7T5jjm%qrp`r?|#KezY3>;CuRDKv^YH1{=mVMYfsWtb{?AXI8~NQYMjrkBqnFj>KYM6Sk z;?#!4OPgQ1^wOh`J>E33w$r!%-$!!)`qzO+vVt%4JX9Tf-u3$S${Q{k6t}*0$C=)N zUv5=Dz2M@xv%dDdH*4>>@04j*JnTO-@2BzeUpu?3_b

q5Zbko_g==XU+cZviE(T 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 z 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 literal 0 HcmV?d00001 diff --git a/keycard_wallet/keycard_applets/math.cap b/keycard_wallet/keycard_applets/math.cap new file mode 100644 index 0000000000000000000000000000000000000000..b9c0e99f7cb534501781bbfeada8f9fd09a6acf3 GIT binary patch literal 4874 zcmcgve{d9c6@TB&-mm1Agxp=iVSZ{FEl7y&oYL?iZIk zOw!IkrMjZ`P8aoO&Voa!2q)jFKXjPDQ3bmG2I-Tjzsg|}=iv-`>yWDoy zVD>L|=k0#K@4NeX@B4o3KCdT_w}R1V1oO8?w!!BPEAY_1p|h!eWRP5Xg=Qk-tJR7S08Nm3_UY>WY3G^25$W9_`|O(E;-logE8aGjr}9t z;-eMEFO1x{_|t!MJ3cL5wqc#O>vzjtZ?Af3!oP2{@#&7$@BgLZXH%!99H);x^MpHG zXZ_{1me+sy$|G;DI$zzj?~3dDAG$Am+5O!jd&k}3!h5drduvXQ{(R8Y^ycXKr$70` zx_{-NCz`(}wr(pOe6RV?zxB%#AHVhbt7X+wchziqwXbL5WBs$eSDx*u^QPZ9vh&G3 zZEuuan2dgPO5b-Vy12!6skQ&o<=XI;9o4R4XVtyyJ{mso<{kg)J6^T++5?CGcJ#H; z&cU(A9*m8DWyzfH;t=Od)KXe zvez_y?(BoXiGP-QJqF`VXU*Y<8Gt(vz>AK|2QY%QcDyI6J{o*cBnze?+U?|xT5EBd>e?N2ceU9UR8AcJ12d-r9*OekCcP_hF zgQAG)HHdVFlc7K=o*W{n98`k?3BV2|V1+Ko2NM|JKJEtc@Zi)t9DC}qNXrg4 zMicR5ie&L%&+ZNUz!)nyzY8O}ant$^Z(O-0@AZ==JK_^HBF$|E*^2AqF|=|l<&DQ9 zBuR&R(dqX9=pTYSBo2v3VoEUw4^Ep)5uT_{iL=mPQPf+@VBve-!+h8P|xkAa4!z zw#5U89*@!fO&EdzI-SjCD^vpi^;%^oNhQ)^(+z{O!IuvPhQZ9#F;M%Hj&J!9ji>=> zJ|nn81A$~Xf%!w47QlUoNJ)bF0tOgvSw|DbFeny)g~lAi@W_ty7zRpq%rj`gKqB+g z+h*j`X=O$E;~w{TlL4z348fYE#Yr?T`YAxhB>bihW^@RtZwoMEEYS2gH z!KPpk3LQNzpKq2BhKa!SxPTWsdV7KSaL^Wt0rLazCl2qIrZM1S(lka>0&7o4q`NQe zm+o6bK`6+9BQQEjIyrP9nHAl@BO#N^+^~dTH6%XZN&!06gsVmlJ)2K%&#YP)&I<4m z3x{qbhg$N`lhS~P!pxEmiZUEMEX)iHP@GvZBAoQFDH{(IHw*DBmQI@_wEXr6T_lO5 zuL13J#qAMVDG9B@O1ub#ws2?-gKS=5*1W>3d4*Z?3Ov3^mKStc8wymM$(Te1P>T*R z!xCj0y?m(a=nGi5iT+O+QAT%ws{fgp-yTQY72w2z0$^hc0WOrg=JC)@pIu#`BT@0 zp)6v7>T#h4ls-83(GXJvhkhJV3ehdYL9UcVbdxyQJj#f`M9K^>lb9lv&_%v@IvEHx zhowy^ZAX>COvz(_rDps&Dl)@zy42I90V@&E*bRdL(Mwtw!3P2^Da)LfS zPQ2p}An2A(0{ayXI4KJC60-m!jy`_U0~m)3aE7ul|1&TD2w@1svaGD!&f9c0z1?6l z+DylQlcA*Yk}UxQ*PD4I3x_XDYb3&grRQXngtdk4}V^9^aUKz{>n5cnx|Hj%7$Iq_w7@(T!W&#T2U%BRkvBu3aHGw{+ro& z5^}CT20FEhRI`>yDz-{a5^_!#a!wb}VHu|jIj0MfTgmByl2_>H*@)muMjB*-7^cJ80Il3S|k5HoW=mDR0`8eQG9$mqMYpwD(NYFKr%BEw$L04ujHYFu@X zA>*bo)aEmWs^d_DtJ@42{LdP|RZWK)T-|EO;10~I`81as4>hj3;gE5MHQ*}S4>h*B xJ&>^-SoY`BIoB+xVb#A&GHe_hwOha{e*mPPC$C3GUmvVV0z7~o8ln#){1=8l7BBz+ literal 0 HcmV?d00001 diff --git a/keycard_wallet/python/keycard_wallet.py b/keycard_wallet/python/keycard_wallet.py new file mode 100644 index 00000000..767c1aba --- /dev/null +++ b/keycard_wallet/python/keycard_wallet.py @@ -0,0 +1,122 @@ +from smartcard.System import readers +from keycard.exceptions import APDUError, TransportError +from ecdsa import VerifyingKey, SECP256k1 + +from keycard.keycard import KeyCard + +from mnemonic import Mnemonic +from keycard import constants + +import keycard + +DEFAULT_PAIRING_PASSWORD = "KeycardDefaultPairing" + +class KeycardWallet: + def __init__(self): + self.card = KeyCard() + + def _is_smart_card_reader_detected(self) -> bool: + try: + return len(readers()) > 0 + except Exception: + return False + + def _is_keycard_detected(self) -> bool: + try: + KeyCard().select() + return True + except (TransportError, APDUError, Exception): + # No readers, no card, or card doesn't respond. + return False + + def is_unpaired_keycard_available(self) -> bool: + if not self._is_smart_card_reader_detected(): + return False + elif not self._is_keycard_detected(): + return False + return True + + def setup_communication(self, pin: str, password = DEFAULT_PAIRING_PASSWORD) -> bool: + self.card.select() + + if not self.card.is_initialized: + raise RuntimeError(f"Error setting up communication: uninitialized keycard") + + pairing_index, pairing_key = self.card.pair(password) + self.pairing_index = pairing_index + + try: + self.card.open_secure_channel(pairing_index, pairing_key) + self.card.verify_pin(pin) + except Exception as e: + try: + self.card.unpair(pairing_index) + except Exception: + pass + raise RuntimeError(f"Error setting up communication: {e}") from e + + return True + + def load_mnemonic(self, mnemonic: str) -> bool: + try: + # Convert mnemonic to seed + mnemo = Mnemonic("english") + seed = mnemo.to_seed(mnemonic) + + # Load the LEE seed onto the card + result = self.card.load_key( + key_type = constants.LoadKeyType.LEE_SEED, + lee_seed = seed + ) + return True + except Exception as e: + raise RuntimeError(f"Error loading mnemonic: {e}") from e + + def disconnect(self) -> bool: + try: + if not self.card.is_secure_channel_open: + return False + + self.card.unpair(self.pairing_index) + + return True + except Exception as e: + raise RuntimeError(f"Error during disconnect: {e}") from e + + def get_public_key_for_path(self, path: str = "m/44'/60'/0'/0/0") -> bytes | None: + try: + if not self.card.is_secure_channel_open or not self.card.is_pin_verified: + return None + + public_key = self.card.export_key( + derivation_option = constants.DerivationOption.DERIVE, + public_only = True, + keypath = path + ) + + public_key = public_key.public_key + public_key = VerifyingKey.from_string(public_key[1:], curve=SECP256k1) + public_key = public_key.to_string("compressed")[1:] + + return public_key + + except Exception as e: + raise RuntimeError(f"Error getting public key: {e}") from e + + + def sign_message_for_path(self, message: bytes, path: str = "m/44'/60'/0'/0/0") -> bytes | None: + try: + if not self.card.is_secure_channel_open or not self.card.is_pin_verified: + return None + + signature = self.card.sign_with_path( + digest = message, + path = path, + algorithm = constants.SigningAlgorithm.SCHNORR_BIP340, + make_current = False + ) + + return signature.signature + + except Exception as e: + raise RuntimeError(f"Error signing message: {e}") from e \ No newline at end of file diff --git a/keycard_wallet/src/python_path.rs b/keycard_wallet/src/python_path.rs index b7159295..8251f7a3 100644 --- a/keycard_wallet/src/python_path.rs +++ b/keycard_wallet/src/python_path.rs @@ -12,8 +12,11 @@ pub fn add_python_path(py: Python<'_>) -> PyResult<()> { .unwrap_or_else(|| current_dir.clone()); let mut paths_to_add: Vec = vec![ - python_base.join("python"), - python_base.join("python").join("keycard-py"), + python_base.join("keycard_wallet").join("python"), + python_base + .join("keycard_wallet") + .join("python") + .join("keycard-py"), ]; // If a virtualenv is active, add its site-packages so that dependencies diff --git a/wallet/src/cli/account.rs b/wallet/src/cli/account.rs index 5ed99d90..4943aae1 100644 --- a/wallet/src/cli/account.rs +++ b/wallet/src/cli/account.rs @@ -236,7 +236,7 @@ impl WalletSubcommand for AccountSubcommand { let account_id: nssa::AccountId = account_id_str.parse()?; // Add account id to the display for keycard users. - log::info!("Account Id: {resolved}"); + println!("Account Id: {resolved}"); if let Some(label) = wallet_core.storage.labels.get(&account_id_str) { println!("Label: {label}"); diff --git a/wallet_with_keycard.sh b/wallet_with_keycard.sh index a0b4de46..c5331a12 100644 --- a/wallet_with_keycard.sh +++ b/wallet_with_keycard.sh @@ -1,10 +1,10 @@ cargo install --path wallet --force # Install appropriate version of `keycard-py`. -git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git python/keycard-py +git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git keycard_wallet/python/keycard-py # Set up virtual environment. python3 -m venv venv source venv/bin/activate pip install pyscard mnemonic ecdsa pyaes -pip install -e python/keycard-py \ No newline at end of file +pip install -e keycard_wallet/python/keycard-py \ No newline at end of file