def register_id(self, address): idticket = IDTicket( dictionary={ "blockchain_address": address, "public_key": self.__pubkey, "ticket_submission_time": int(time.time()), }) idticket.validate() signature = Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( idticket.serialize(), self.__privkey, self.__pubkey), "pubkey": self.__pubkey, }) signature.validate(idticket) finalticket = FinalIDTicket( dictionary={ "ticket": idticket.to_dict(), "signature": signature.to_dict(), "nonce": str(uuid.uuid4()), }) finalticket.validate(self.__chainwrapper) self.__chainwrapper.store_ticket(finalticket)
def masternode_sign_activation_ticket(self, data, *args, **kwargs): # parse inputs signature_serialized, activationticket_serialized, image_serialized = data signed_actticket = Signature(serialized=signature_serialized) image = ImageData(serialized=image_serialized) activation_ticket = ActivationTicket( serialized=activationticket_serialized) # test image data for validity in a jailed environment converter = JailedImageParser(self.__nodenum, image.image) converter.parse() # validate client's signature on the ticket - so only original client can activate require_true(signed_actticket.pubkey == activation_ticket.author) signed_actticket.validate(activation_ticket) # validate activation ticket activation_ticket.validate(self.__chainwrapper, image) # sign activation ticket ticket_signed_by_mn = Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( activationticket_serialized, self.__priv, self.__pub), "pubkey": self.__pub, }) return ticket_signed_by_mn.serialize()
def __generate_signed_ticket(self, ticket): signed_ticket = Signature(dictionary={ "signature": pastel_id_write_signature_on_data_func(ticket.serialize(), self.__privkey, self.__pubkey), "pubkey": self.__pubkey, }) # make sure we validate correctly signed_ticket.validate(ticket) return signed_ticket
def pack_and_sign(privkey, pubkey, receiver_id, message_body, version=MAX_SUPPORTED_VERSION): if version > MAX_SUPPORTED_VERSION: raise NotImplementedError("Version %s not supported, latest is :%s" % (version, MAX_SUPPORTED_VERSION)) sleep_rand() if version == 1: # pack container container = { "version": version, "sender_id": pubkey, "receiver_id": receiver_id, "data": message_body, # here message_body is already serialized with msgpack "nonce": nacl.utils.random(NONCE_LENGTH), "timestamp": time.time(), "signature": b'', } # make sure types are valid ensure_types_for_v1(container) # serialize container, calculate hash and sign with private key # signature is None as this point as we can't know the signature without calculating it container_serialized = msgpack.packb(container, default=default, use_bin_type=True) signature = pastel_id_write_signature_on_data_func(get_pynode_digest_bytes(container_serialized), privkey, pubkey) # TODO: serializing twice is not the best solution if we want to work with large messages # TODO: AlexD: Actually here we serialize data even 3 times - cause `message_body` comes here already serialized # TODO: but as we cannot sign python dict as is - we have to serialize it to bytestring somehow before signing # TODO: so we cannot avoid double serialization, but can avoid triple one. `message_body` here should come as # TODO: dict, not a binary string. # TODO: On the other hand serialization/deserialization time expenses are nothing compairing to network delays. # fill signature field in and serialize again container["signature"] = signature final = msgpack.packb(container, default=default, use_bin_type=True) if len(final) > NetWorkSettings.RPC_MSG_SIZELIMIT: raise ValueError("raw_message_contents is too large: %s > %s" % (len(final), NetWorkSettings.RPC_MSG_SIZELIMIT)) sleep_rand() return final else: raise NotImplementedError("Version %s is not implemented!" % version)
async def sign_message(request): global public_key str_pk = base64.encodebytes(public_key).decode() data = await request.json() string_data = ordered_json_string_from_dict(data) bytes_data = string_data.encode() signature = pastel_id_write_signature_on_data_func(bytes_data, private_key, public_key) signature_string = base64.encodebytes(signature).decode() # signature_restored = base64.b64decode(signature_string.encode()) # pk_restored = base64.b64decode(str_pk.encode()) # verified = pastel_id_verify_signature_with_public_key_func(bytes_data, signature_restored, pk_restored) return web.json_response({ 'signature': signature_string, 'pastel_id': str_pk })
async def register_trade(self, imagedata_hash, tradetype, watched_address, copies, price, expiration): # move funds to new address if tradetype == "bid": collateral_txid = await self.__chainwrapper.move_funds_to_new_wallet( self.__pubkey, watched_address, copies, price) else: # this is unused in ask tickets collateral_txid = "0000000000000000000000000000000000000000000000000000000000000000" tradeticket = TradeTicket( dictionary={ "public_key": self.__pubkey, "imagedata_hash": imagedata_hash, "type": tradetype, "copies": copies, "price": price, "expiration": expiration, "watched_address": watched_address, "collateral_txid": collateral_txid, }) tradeticket.validate(self.__blockchain, self.__chainwrapper, self.__artregistry) signature = Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( tradeticket.serialize(), self.__privkey, self.__pubkey), "pubkey": self.__pubkey, }) signature.validate(tradeticket) finalticket = FinalTradeTicket( dictionary={ "ticket": tradeticket.to_dict(), "signature": signature.to_dict(), "nonce": str(uuid.uuid4()), }) finalticket.validate(self.__chainwrapper) self.__chainwrapper.store_ticket(finalticket)
def masternode_sign_registration_ticket(self, data, *args, **kwargs): # parse inputs signature_serialized, regticket_serialized = data signed_regticket = Signature(serialized=signature_serialized) regticket = RegistrationTicket(serialized=regticket_serialized) # validate client's signature on the ticket require_true(signed_regticket.pubkey == regticket.author) signed_regticket.validate(regticket) # validate registration ticket regticket.validate(self.__chainwrapper) # sign regticket ticket_signed_by_mn = Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( regticket_serialized, self.__priv, self.__pub), "pubkey": self.__pub, }) return ticket_signed_by_mn.serialize()
def register_transfer(self, recipient_pubkey, imagedata_hash, copies): transferticket = TransferTicket( dictionary={ "public_key": self.__pubkey, "recipient": recipient_pubkey, "imagedata_hash": imagedata_hash, "copies": copies, }) transferticket.validate(self.__chainwrapper, self.__artregistry) # Make sure enough remaining copies are left on our key # We do this here to prevent creating a ticket we know now as invalid. However anything # might happen before this tickets makes it to the network, os this check can't be put in validate() require_true( self.__artregistry.enough_copies_left( transferticket.imagedata_hash, transferticket.public_key, transferticket.copies)) signature = Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( transferticket.serialize(), self.__privkey, self.__pubkey), "pubkey": self.__pubkey, }) signature.validate(transferticket) finalticket = FinalTransferTicket( dictionary={ "ticket": transferticket.to_dict(), "signature": signature.to_dict(), "nonce": str(uuid.uuid4()), }) finalticket.validate(self.__chainwrapper) self.__chainwrapper.store_ticket(finalticket)
def masternode_mn0_confirm(self, data, *args, **kwargs): # parse inputs artist_pk, image_hash, serialized_signature = data sender_id = kwargs.get('sender_id') db.connect(reuse_if_open=True) mn_ticket_logger.info( 'masternode_mn0_confirm: received confirmation from {}'.format( sender_id)) try: # Verify that given upload_code exists # !!!! - regticket with same artists_pk and image_hash may already exists regticket_db_set = Regticket.select().where( Regticket.artist_pk == artist_pk, Regticket.image_hash == image_hash) if len(regticket_db_set) == 0: raise Exception( 'Regticket not found for given artist ID and image hash') if len(regticket_db_set) > 2: regticket_db = regticket_db_set[-1] Regticket.delete().where(Regticket.id < regticket_db.id) else: regticket_db = regticket_db_set[0] if regticket_db.is_valid_mn1 is None: # first confirmation has came regticket_db.is_valid_mn1 = True regticket_db.mn1_pk = sender_id regticket_db.mn1_serialized_signature = serialized_signature regticket_db.save() else: if regticket_db.is_valid_mn2 is None: if regticket_db.mn1_pk == sender_id: raise Exception( 'I already have confirmation from this masternode') # second confirmation has came regticket_db.is_valid_mn2 = True regticket_db.mn2_pk = sender_id regticket_db.mn2_serialized_signature = serialized_signature regticket_db.save() regticket = RegistrationTicket( serialized=regticket_db.regticket) current_block = self.__chainwrapper.get_last_block_number() # verify if confirmation receive for 5 blocks or less from regticket creation. if current_block - regticket.blocknum > 5: regticket_db.status = REGTICKET_STATUS_ERROR error_msg = 'Second confirmation received too late - current block {}, regticket block: {}'. \ format(current_block, regticket.blocknum) regticket_db.error = error_msg raise Exception(error_msg) # Tcreate final ticket final_ticket = generate_final_regticket( regticket, Signature( serialized=regticket_db.artists_signature_ticket), (Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( regticket_db.regticket, self.__priv, self.__pub), "pubkey": self.__pub }), Signature( serialized=regticket_db.mn1_serialized_signature), Signature( serialized=regticket_db.mn2_serialized_signature) )) # write final ticket into blockchain # TODO: process errors txid = self.__chainwrapper.store_ticket(final_ticket) mn_ticket_logger.warn( 'Final ticket is stored, txid: {}'.format(txid)) return txid # TODO: store image into chunkstorage - later, when activation happens # TODO: extract all this into separate function else: raise Exception( 'All 2 confirmations received for a given ticket') except DoesNotExist: mn_ticket_logger.warn( 'Given upload code DOES NOT exists with required public key') raise Exception( 'Given upload code DOES NOT exists with required public key') mn_ticket_logger.info('Confirmation from MN received') return 'Ok'