Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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)
Exemplo n.º 5
0
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
    })
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
    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()
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
    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'