mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-14 03:59:30 +00:00
81 lines
2.5 KiB
Python
81 lines
2.5 KiB
Python
from typing import Optional, Union
|
|
|
|
from .. import constants
|
|
from ..card_interface import CardInterface
|
|
from ..constants import DerivationOption, KeyExportOption, DerivationSource
|
|
from ..parsing import tlv
|
|
from ..parsing.exported_key import ExportedKey
|
|
from ..parsing.keypath import KeyPath
|
|
from ..preconditions import require_pin_verified
|
|
|
|
|
|
@require_pin_verified
|
|
def export_key(
|
|
card: CardInterface,
|
|
derivation_option: constants.DerivationOption,
|
|
public_only: bool,
|
|
keypath: Optional[Union[str, bytes, bytearray]] = None,
|
|
make_current: bool = False,
|
|
source: DerivationSource = DerivationSource.MASTER
|
|
) -> ExportedKey:
|
|
"""
|
|
Export a key (public or private) from the card using an optional keypath.
|
|
|
|
If derivation_option == CURRENT, keypath can be omitted or empty.
|
|
|
|
Args:
|
|
card: The card object
|
|
derivation_option: e.g. DERIVE, CURRENT, DERIVE_AND_MAKE_CURRENT
|
|
public_only: If True, export only public key
|
|
keypath: BIP32-style string or packed bytes, or None if CURRENT
|
|
make_current: Whether to update the card's current path
|
|
source: MASTER (0x00), PARENT (0x40), CURRENT (0x80)
|
|
|
|
Returns:
|
|
dict with optional 'public_key', 'private_key', 'chain_code'
|
|
"""
|
|
if keypath is None:
|
|
if derivation_option != constants.DerivationOption.CURRENT:
|
|
raise ValueError(
|
|
"Keypath required unless using CURRENT derivation")
|
|
data = b""
|
|
elif isinstance(keypath, str):
|
|
data = KeyPath(keypath).data
|
|
elif isinstance(keypath, (bytes, bytearray)):
|
|
if len(keypath) % 4 != 0:
|
|
raise ValueError("Byte keypath must be a multiple of 4")
|
|
data = bytes(keypath)
|
|
else:
|
|
raise TypeError("Keypath must be a string or bytes")
|
|
|
|
if make_current:
|
|
p1 = DerivationOption.DERIVE_AND_MAKE_CURRENT
|
|
else:
|
|
p1 = derivation_option
|
|
p1 |= source
|
|
|
|
if public_only:
|
|
p2 = KeyExportOption.PUBLIC_ONLY
|
|
else:
|
|
p2 = KeyExportOption.PRIVATE_AND_PUBLIC
|
|
|
|
response = card.send_secure_apdu(
|
|
ins=constants.INS_EXPORT_KEY,
|
|
p1=p1,
|
|
p2=p2,
|
|
data=data
|
|
)
|
|
|
|
outer = tlv.parse_tlv(response)
|
|
tpl = outer.get(0xA1)
|
|
if not tpl:
|
|
raise ValueError("Missing keypair template (tag 0xA1)")
|
|
|
|
inner = tlv.parse_tlv(tpl[0])
|
|
|
|
return ExportedKey(
|
|
public_key=inner.get(0x80, [None])[0],
|
|
private_key=inner.get(0x81, [None])[0],
|
|
chain_code=inner.get(0x82, [None])[0],
|
|
)
|