def sign_message(self, message, keypath): self.device.check_mitm() keypath = keypath.replace('h', '\'') keypath = keypath.replace('H', '\'') try: ok = self.device.send_recv(CCProtocolPacker.sign_message( message.encode(), keypath, AF_CLASSIC), timeout=None) assert ok == None if self.device.is_simulator: self.device.send_recv(CCProtocolPacker.sim_keypress(b'y')) except CCProtoError as e: raise ValueError(str(e)) while 1: time.sleep(0.250) done = self.device.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None) if done == None: continue break if len(done) != 2: raise ValueError('Failed: %r' % done) addr, raw = done sig = str(base64.b64encode(raw), 'ascii').replace('\n', '') return {"signature": sig}
async def sign_text_msg(self, msg, subpath, addr_fmt): # send text and path to sign with; no policy check msg = msg.encode('ascii') async with self.sign_lock: try: await self.send_recv( CCProtocolPacker.sign_message(msg, subpath, addr_fmt)) while 1: await asyncio.sleep(0.250) done = await self.send_recv( CCProtocolPacker.get_signed_msg(), timeout=None) if done == None: continue break except CCUserRefused: raise RuntimeError("Coldcard refused request based on policy.") if len(done) != 2: logging.error('Coldcard failed: %r' % done) raise RuntimeError(done) addr, sig = done return sig, addr
def sign_message(message, path, verbose=True, just_sig=False, wrap=False, segwit=False): "Sign a short text message" dev = ColdcardDevice(sn=force_serial) if wrap: addr_fmt = AF_P2WPKH_P2SH elif segwit: addr_fmt = AF_P2WPKH else: addr_fmt = AF_CLASSIC # NOTE: initial version of firmware not expected to do segwit stuff right, since # standard very much still in flux, see: <https://github.com/bitcoin/bitcoin/issues/10542> # not enforcing policy here on msg contents, so we can define that on product message = message.encode('ascii') if not isinstance(message, bytes) else message ok = dev.send_recv(CCProtocolPacker.sign_message(message, path, addr_fmt), timeout=None) assert ok == None print("Waiting for OK on the Coldcard...", end='', file=sys.stderr) sys.stderr.flush() while 1: time.sleep(0.250) done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None) if done == None: continue break print("\r \r", end='', file=sys.stderr) sys.stderr.flush() if len(done) != 2: click.echo('Failed: %r' % done) sys.exit(1) addr, raw = done sig = str(b64encode(raw), 'ascii').replace('\n', '') if just_sig: click.echo(str(sig)) elif verbose: click.echo( '-----BEGIN SIGNED MESSAGE-----\n{msg}\n-----BEGIN ' 'SIGNATURE-----\n{addr}\n{sig}\n-----END SIGNED MESSAGE-----'. format(msg=message.decode('ascii'), addr=addr, sig=sig)) else: click.echo('%s\n%s\n%s' % (message.decode('ascii'), addr, sig))
def sign_message_poll(self): # poll device... if user has approved, will get tuple: (addr, sig) else None return self.dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None)