def parse(cls, der: bytes) -> Signature: return cls(secp256k1.ecdsa_signature_parse_der(der))
def open(self, mode=None): """Opens a secure channel. Mode can be "es" - ephemeral-static or "ee" - ephemeral-ephemenral """ # save mode for later - i.e. reestablish secure channel if mode is None: mode = self.mode else: self.mode = mode # check if we know pubkey already if self.card_pubkey is None: self.get_card_pubkey() # generate ephimerial key secret = get_random_bytes(32) host_prv = secret host_pub = secp256k1.ec_pubkey_create(secret) # ee mode - ask card to create ephimerial key and send it to us if mode == "ee": data = secp256k1.ec_pubkey_serialize(host_pub, secp256k1.EC_UNCOMPRESSED) # get ephimerial pubkey from the card res = self.applet.request(self.OPEN_EE + encode(data)) s = BytesIO(res) data = s.read(65) pub = secp256k1.ec_pubkey_parse(data) secp256k1.ec_pubkey_tweak_mul(pub, secret) shared_secret = hashlib.sha256( secp256k1.ec_pubkey_serialize(pub)[1:33]).digest() shared_fingerprint = self.derive_keys(shared_secret) recv_hmac = s.read(MAC_SIZE) h = hmac.new(self.card_mac_key, digestmod="sha256") h.update(data) expected_hmac = h.digest()[:MAC_SIZE] if expected_hmac != recv_hmac: raise SecureChannelError("Wrong HMAC.") data += recv_hmac raw_sig = s.read() sig = secp256k1.ecdsa_signature_parse_der(raw_sig) # in case card doesn't follow low s rule (but it should) sig = secp256k1.ecdsa_signature_normalize(sig) if not secp256k1.ecdsa_verify(sig, hashlib.sha256(data).digest(), self.card_pubkey): raise SecureChannelError("Signature is invalid.") # se mode - use our ephimerial key with card's static key else: data = secp256k1.ec_pubkey_serialize(host_pub, secp256k1.EC_UNCOMPRESSED) # ugly copy pub = secp256k1.ec_pubkey_parse( secp256k1.ec_pubkey_serialize(self.card_pubkey)) secp256k1.ec_pubkey_tweak_mul(pub, secret) shared_secret = secp256k1.ec_pubkey_serialize(pub)[1:33] res = self.applet.request(self.OPEN_SE + encode(data)) s = BytesIO(res) nonce_card = s.read(32) recv_hmac = s.read(MAC_SIZE) secret_with_nonces = hashlib.sha256(shared_secret + nonce_card).digest() shared_fingerprint = self.derive_keys(secret_with_nonces) data = nonce_card h = hmac.new(self.card_mac_key, digestmod="sha256") h.update(data) expected_hmac = h.digest()[:MAC_SIZE] if expected_hmac != recv_hmac: raise SecureChannelError("Wrong HMAC.") data += recv_hmac sig = secp256k1.ecdsa_signature_parse_der(s.read()) # in case card doesn't follow low s rule (but it should) sig = secp256k1.ecdsa_signature_normalize(sig) if not secp256k1.ecdsa_verify(sig, hashlib.sha256(data).digest(), self.card_pubkey): raise SecureChannelError("Signature is invalid") # reset iv self.iv = 0 self.is_open = True
def read_from(cls, stream): der = stream.read(2) der += stream.read(der[1]) return cls(secp256k1.ecdsa_signature_parse_der(der))
def parse(cls, der): return cls(secp256k1.ecdsa_signature_parse_der(der))