mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-14 20:19:51 +00:00
69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
from ecdsa import SigningKey, VerifyingKey, SECP256k1, ECDH
|
|
|
|
from .. import constants
|
|
from ..card_interface import CardInterface
|
|
from ..exceptions import NotSelectedError
|
|
from ..secure_channel import SecureChannel
|
|
from ..preconditions import require_initialized
|
|
|
|
|
|
@require_initialized
|
|
def open_secure_channel(
|
|
card: CardInterface,
|
|
pairing_index: int,
|
|
pairing_key: bytes
|
|
) -> SecureChannel:
|
|
'''
|
|
Opens a secure session with the Keycard using ECDH and a pairing key.
|
|
|
|
This function performs an ephemeral ECDH key exchange with the card,
|
|
sends the ephemeral public key, and receives cryptographic material
|
|
from the card to derive a secure session.
|
|
|
|
Args:
|
|
transport: The transport used to communicate with the card.
|
|
card_public_key (bytes): The ECC public key of the card, retrieved
|
|
via select().
|
|
pairing_index (int): The index of the previously established
|
|
pairing slot.
|
|
pairing_key (bytes): The shared 32-byte pairing key.
|
|
|
|
Returns:
|
|
SecureChannel: A newly established secure session with the card.
|
|
|
|
Raises:
|
|
NotSelectedError: If no card public key is provided.
|
|
APDUError: If the card returns a failure status word.
|
|
'''
|
|
if not card.card_public_key:
|
|
raise NotSelectedError('Card not selected or missing public key')
|
|
|
|
ephemeral_key = SigningKey.generate(curve=SECP256k1)
|
|
eph_pub_bytes = ephemeral_key.verifying_key.to_string('uncompressed')
|
|
response: bytes = card.send_apdu(
|
|
ins=constants.INS_OPEN_SECURE_CHANNEL,
|
|
p1=pairing_index,
|
|
data=eph_pub_bytes
|
|
)
|
|
|
|
salt = bytes(response[:32])
|
|
seed_iv = bytes(response[32:])
|
|
|
|
public_key = VerifyingKey.from_string(
|
|
card.card_public_key,
|
|
curve=SECP256k1
|
|
)
|
|
ecdh = ECDH(
|
|
curve=SECP256k1,
|
|
private_key=ephemeral_key,
|
|
public_key=public_key
|
|
)
|
|
shared_secret = ecdh.generate_sharedsecret_bytes()
|
|
|
|
return SecureChannel.open(
|
|
shared_secret,
|
|
pairing_key,
|
|
salt,
|
|
seed_iv,
|
|
)
|