Exemple #1
0
def test_create_set_response(benchmark):
    battleshipMessage = MessageFactory(
        "battleship", "1.0",
        MessageFactory.sha512("battleship".encode("utf-8"))[0:6], None)
    context = create_context("secp256k1")
    publicKey = battleshipMessage.get_public_key()
    address = battleshipMessage.namespaces[0] + MessageFactory.sha256(
        publicKey.encode("utf-8"))
    benchmark(MessageFactory.create_set_response, battleshipMessage, [address])
    return
Exemple #2
0
def test_create_set_request(benchmark):
    battleshipMessage = MessageFactory(
        "battleship", "1.0",
        MessageFactory.sha512("battleship".encode("utf-8"))[0:6], None)
    context = create_context("secp256k1")
    publicKey = battleshipMessage.get_public_key()
    address = battleshipMessage.namespaces[0] + MessageFactory.sha256(
        publicKey.encode("utf-8"))
    data = ValidatorMap().SerializeToString()
    benchmark(MessageFactory.create_set_request, battleshipMessage,
              {address: data})
    return
class SettingsMessageFactory:
    def __init__(self, signer=None):
        self._factory = MessageFactory(
            family_name="bgx_settings",
            family_version="1.0",
            namespace="000000",
            signer=signer)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        key_parts = key.split('.', maxsplit=_MAX_KEY_PARTS - 1)
        key_parts.extend([''] * (_MAX_KEY_PARTS - len(key_parts)))

        def _short_hash(in_str):
            return self._factory.sha256(in_str.encode())[:16]

        return self._factory.namespace + \
            ''.join(_short_hash(x) for x in key_parts)

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, setting, payload):
        inputs = [
            self._key_to_address('sawtooth.settings.vote.proposals'),
            self._key_to_address('sawtooth.settings.vote.authorized_keys'),
            self._key_to_address('sawtooth.settings.vote.approval_threshold'),
            self._key_to_address(setting)
        ]

        outputs = [
            self._key_to_address('sawtooth.settings.vote.proposals'),
            self._key_to_address(setting)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_proposal_transaction(self, setting, value, nonce):
        proposal = SettingProposal(setting=setting, value=value, nonce=nonce)
        payload = SettingsPayload(action=SettingsPayload.PROPOSE,
                                  data=proposal.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_vote_proposal(self, proposal_id, setting, vote):
        vote = SettingVote(proposal_id=proposal_id, vote=vote)
        payload = SettingsPayload(action=SettingsPayload.VOTE,
                                  data=vote.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_get_request(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_set_response(addresses)

    def create_add_event_request(self, key):
        return self._factory.create_add_event_request(
            "settings/update",
            [("updated", key)])

    def create_add_event_response(self):
        return self._factory.create_add_event_response()
INTKEY_NAMESPACE = MessageFactory.sha512('intkey'.encode())[:6]
XO_NAMESPACE = MessageFactory.sha512('xo'.encode())[:6]


# pylint: disable=invalid-name
class Families(enum.Enum):
    INTKEY = 1
    XO = 2


FAMILY_CONFIG = {
    Families.INTKEY: {
        'family_name': 'intkey',
        'family_version': '1.0',
        'namespace': MessageFactory.sha256('intkey'.encode())[:6]
    },
    Families.XO: {
        'family_name': 'xo',
        'family_version': '1.0',
        'namespace': MessageFactory.sha256('xo'.encode())[:6]
    },
}


def make_intkey_payload(unique_value):
    return {'Verb': 'set', 'Name': unique_value, 'Value': 1000}


def make_intkey_address(unique_value):
    return INTKEY_NAMESPACE + MessageFactory.sha512(
INTKEY_NAMESPACE = MessageFactory.sha512('intkey'.encode())[:6]
XO_NAMESPACE = MessageFactory.sha512('xo'.encode())[:6]


# pylint: disable=invalid-name
class Families(enum.Enum):
    INTKEY = 1
    XO = 2


FAMILY_CONFIG = {
    Families.INTKEY: {
        'family_name': 'intkey',
        'family_version': '1.0',
        'namespace': MessageFactory.sha256('intkey'.encode())[:6]
    },
    Families.XO: {
        'family_name': 'xo',
        'family_version': '1.0',
        'namespace': MessageFactory.sha256('xo'.encode())[:6]
    },
}


def make_intkey_payload(unique_value):
    return {'Verb': 'set', 'Name': unique_value, 'Value': 1000}


def make_intkey_address(unique_value):
    return INTKEY_NAMESPACE + MessageFactory.sha512(
Exemple #6
0
class UnitMessageFactory(object):
    def __init__(self, signer=None):
        self._factory = MessageFactory(
            family_name="hashblock_units",
            family_version="0.1.0",
            namespace=[MessageFactory.sha512('units'.encode("utf-8"))[0:6]],
            signer=signer)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        key_parts = key.split('.', maxsplit=_MAX_KEY_PARTS - 1)
        key_parts.extend([''] * (_MAX_KEY_PARTS - len(key_parts)))

        def _short_hash(in_str):
            return self._factory.sha256(in_str.encode())[:16]

        return self._factory.namespace + \
            ''.join(_short_hash(x) for x in key_parts)

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, code, payload):
        inputs = [
            self._key_to_address('hashblock.units.vote.proposals'),
            self._key_to_address('hashblock.units.vote.authorized_keys'),
            self._key_to_address('hashblock.units.vote.approval_threshold'),
            self._key_to_address(code)
        ]

        outputs = [
            self._key_to_address('hashblock.units.vote.proposals'),
            self._key_to_address(code)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_proposal_transaction(self, code, value, nonce):
        proposal = UnitProposal(code=code, value=value, nonce=nonce)
        payload = UnitPayload(action=UnitPayload.PROPOSE,
                              data=proposal.SerializeToString())

        return self._create_tp_process_request(code, payload)

    def create_vote_proposal(self, proposal_id, code, vote):
        vote = UnitVote(proposal_id=proposal_id, vote=vote)
        payload = UnitPayload(action=UnitPayload.VOTE,
                              data=vote.SerializeToString())

        return self._create_tp_process_request(code, payload)

    def create_get_request(self, code):
        addresses = [self._key_to_address(code)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, code, value=None):
        address = self._key_to_address(code)

        if value is not None:
            entry = Unit.Entry(key=code, value=value)
            data = Unit(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, code, value=None):
        address = self._key_to_address(code)

        if value is not None:
            entry = Unit.Entry(key=code, value=value)
            data = Unit(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, code):
        addresses = [self._key_to_address(code)]
        return self._factory.create_set_response(addresses)

    def create_add_event_request(self, key):
        return self._factory.create_add_event_request("units/update",
                                                      [("updated", key)])

    def create_add_event_response(self):
        return self._factory.create_add_event_response()
Exemple #7
0
class ConfigMessageFactory(object):
    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(encoding="application/protobuf",
                                       family_name="sawtooth_config",
                                       family_version="1.0",
                                       namespace="000000",
                                       private=private,
                                       public=public)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, setting, payload):
        inputs = [
            self._key_to_address('sawtooth.config.authorization_type'),
            self._key_to_address('sawtooth.config.vote.proposals'),
            self._key_to_address('sawtooth.config.vote.authorized_keys'),
            self._key_to_address('sawtooth.config.vote.approval_threshold'),
            self._key_to_address(setting)
        ]

        outputs = [
            self._key_to_address('sawtooth.config.vote.proposals'),
            self._key_to_address(setting)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_proposal_transaction(self, setting, value, nonce):
        proposal = ConfigProposal(setting=setting, value=value, nonce=nonce)
        payload = ConfigPayload(action=ConfigPayload.PROPOSE,
                                data=proposal.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_vote_proposal(self, proposal_id, setting, vote):
        vote = ConfigVote(proposal_id=proposal_id, vote=vote)
        payload = ConfigPayload(action=ConfigPayload.VOTE,
                                data=vote.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_get_request(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_set_response(addresses)
Exemple #8
0
class ValidatorRegistryMessageFactory(object):
    # The basename and enclave measurement values we will put into the enclave
    # quote in the attestation verification report.
    __VALID_BASENAME__ = \
        bytes.fromhex(
            'b785c58b77152cbe7fd55ee3851c4990'
            '00000000000000000000000000000000')
    __VALID_ENCLAVE_MEASUREMENT__ = \
        bytes.fromhex(
            'c99f21955e38dbb03d2ca838d3af6e43'
            'ef438926ed02db4cc729380c8c7a174e')

    __REPORT_PRIVATE_KEY_PEM__ = \
        '-----BEGIN PRIVATE KEY-----\n' \
        'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsy/NmLwZP6Uj0\n' \
        'p5mIiefgK8VOK7KJ34g3h0/X6aFOd/Ff4j+e23wtQpkxsjVHWLM5SjElGhfpVDhL\n' \
        '1WAMsQI9bpCWR4sjV6p7gOJhv34nkA2Grj5eSHCAJRQXCl+pJ9dYIeKaNoaxkdtq\n' \
        '+Xme//ohtkkv/ZjMTfsjMl0RLXokJ+YhSuTpNSovRaCtZfLB5MihVJuV3Qzb2ROh\n' \
        'KQxcuyPy9tBtOIrBWJaFiXOLRxAijs+ICyzrqUBbRfoAztkljIBx9KNItHiC4zPv\n' \
        'o6DxpGSO2yMQSSrs13PkfyGWVZSgenEYOouEz07X+H5B29PPuW5mCl4nkoH3a9gv\n' \
        'rI6VLEx9AgMBAAECggEAImfFge4RCq4/eX85gcc7pRXyBjuLJAqe+7d0fWAmXxJg\n' \
        'vB+3XTEEi5p8GDoMg7U0kk6kdGe6pRnAz9CffEduU78FCPcbzCCzcD3cVWwkeUok\n' \
        'd1GQV4OC6vD3DBNjsrGdHg45KU18CjUphCZCQhdjvXynG+gZmWxZecuYXkg4zqPT\n' \
        'LwOkcdWBPhJ9CbjtiYOtKDZbhcbdfnb2fkxmvnAoz1OWNfVFXh+x7651FrmL2Pga\n' \
        'xGz5XoxFYYT6DWW1fL6GNuVrd97wkcYUcjazMgunuUMC+6XFxqK+BoqnxeaxnsSt\n' \
        'G2r0sdVaCyK1sU41ftbEQsc5oYeQ3v5frGZL+BgrYQKBgQDgZnjqnVI/B+9iarx1\n' \
        'MjAFyhurcKvFvlBtGKUg9Q62V6wI4VZvPnzA2zEaR1J0cZPB1lCcMsFACpuQF2Mr\n' \
        '3VDyJbnpSG9q05POBtfLjGQdXKtGb8cfXY2SwjzLH/tvxHm3SP+RxvLICQcLX2/y\n' \
        'GTJ+mY9C6Hs6jIVLOnMWkRWamQKBgQDFITE3Qs3Y0ZwkKfGQMKuqJLRw29Tyzw0n\n' \
        'XKaVmO/pEzYcXZMPBrFhGvdmNcJLo2fcsmGZnmit8RP4ChwHUlD11dH1Ffqw9FWc\n' \
        '387i0chlE5FhQPirSM8sWFVmjt2sxC4qFWJoAD/COQtKHgEaVKVc4sH/yRostL1C\n' \
        'r+7aWuqzhQKBgQDcuC5LJr8VPGrbtPz1kY3mw+r/cG2krRNSm6Egj6oO9KFEgtCP\n' \
        'zzjKQU9E985EtsqNKI5VdR7cLRLiYf6r0J6j7zO0IAlnXADP768miUqYDuRw/dUw\n' \
        'JsbwCZneefDI+Mp325d1/egjla2WJCNqUBp4p/Zf62f6KOmbGzzEf6RuUQKBgG2y\n' \
        'E8YRiaTOt5m0MXUwcEZk2Hg5DF31c/dkalqy2UYU57aPJ8djzQ8hR2x8G9ulWaWJ\n' \
        'KiCm8s9gaOFNFt3II785NfWxPmh7/qwmKuUzIdWFNxAsbHQ8NvURTqyccaSzIpFO\n' \
        'hw0inlhBEBQ1cB2r3r06fgQNb2BTT0Itzrd5gkNVAoGBAJcMgeKdBMukT8dKxb4R\n' \
        '1PgQtFlR3COu2+B00pDyUpROFhHYLw/KlUv5TKrH1k3+E0KM+winVUIcZHlmFyuy\n' \
        'Ilquaova1YSFXP5cpD+PKtxRV76Qlqt6o+aPywm81licdOAXotT4JyJhrgz9ISnn\n' \
        'J13KkHoAZ9qd0rX7s37czb3O\n' \
        '-----END PRIVATE KEY-----'

    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(
            family_name="sawtooth_validator_registry",
            family_version="1.0",
            namespace="6a4372",
            private=private,
            public=public
        )
        self.public_key_hash = hashlib.sha256(public.encode()).hexdigest()
        self._report_private_key = \
            serialization.load_pem_private_key(
                self.__REPORT_PRIVATE_KEY_PEM__.encode(),
                password=None,
                backend=backends.default_backend())

        # First we need to create a public/private key pair for the PoET
        # enclave to use.
        self._poet_private_key = \
            "1f70fa2518077ad18483f48e77882d11983b537fa5f7cf158684d2c670fe4f1f"
        self.poet_public_key = \
            signing.generate_public_key(self._poet_private_key)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    # Utility function for creating proof data as we need to be
    # able to update signatures when verification report changes
    # Returns a serialized proof data
    def create_proof_data(self, verification_report, evidence_payload):
        verification_report_json = json.dumps(verification_report)
        signature = \
            self._report_private_key.sign(
                verification_report_json.encode(),
                padding.PKCS1v15(),
                hashes.SHA256())
        proof_data_dict = OrderedDict([
            ('evidence_payload', evidence_payload),
            ('verification_report', verification_report_json),
            ('signature', base64.b64encode(signature).decode())]
        )

        return json.dumps(proof_data_dict)

    # Currently this is done in the enclave
    def create_signup_info(self, originator_public_key_hash, nonce,
                           pse_manifest_status='OK'):
        # currently not used
        # _active_wait_timer = None

        # We are going to fake out the sealing the signup data.
        signup_data = {
            'poet_public_key': self.poet_public_key,
            'poet_private_key': self._poet_private_key
        }

        # Build up a fake SGX quote containing:
        # 1. The basename
        # 2. The report body that contains:
        #    a. The enclave measurement
        #    b. The report data SHA256(SHA256(OPK)|PPK)
        sgx_basename = \
            sgx_structs.SgxBasename(name=self.__VALID_BASENAME__)
        sgx_measurement = \
            sgx_structs.SgxMeasurement(
                m=self.__VALID_ENCLAVE_MEASUREMENT__)

        hash_input = \
            '{0}{1}'.format(
                originator_public_key_hash.upper(),
                self.poet_public_key.upper()).encode()
        report_data = hashlib.sha256(hash_input).digest()

        sgx_report_data = sgx_structs.SgxReportData(d=report_data)
        sgx_report_body = \
            sgx_structs.SgxReportBody(
                mr_enclave=sgx_measurement,
                report_data=sgx_report_data)

        sgx_quote = \
            sgx_structs.SgxQuote(
                basename=sgx_basename,
                report_body=sgx_report_body)

        # Create a fake PSE manifest.  A base64 encoding of the
        # originator public key hash should suffice.
        pse_manifest = \
            base64.b64encode(originator_public_key_hash.encode())

        timestamp = '2017-02-16T15:21:24.437048'

        # Fake our "proof" data.
        verification_report = OrderedDict([
            ('epidPseudonym', originator_public_key_hash),
            ('id', base64.b64encode(
                hashlib.sha256(
                    timestamp.encode()).hexdigest().encode()).decode()),
            ('isvEnclaveQuoteStatus', 'OK'),
            ('isvEnclaveQuoteBody',
                base64.b64encode(sgx_quote.serialize_to_bytes()).decode()),
            ('pseManifestStatus', pse_manifest_status),
            ('pseManifestHash',
                hashlib.sha256(base64.b64decode(pse_manifest)).hexdigest()),
            ('nonce', nonce),
            ('timestamp', timestamp)
        ])

        proof_data = \
            self.create_proof_data(
                verification_report=verification_report,
                evidence_payload={
                    'pse_manifest': pse_manifest.decode()
                })

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash,
                nonce=nonce)

    def create_tp_process_request(self, validator_id, payload):
        inputs = [
            self._key_to_address('validator_list')
        ]

        outputs = [
            self._key_to_address('validator_list'),
            self._key_to_address(validator_id)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [], False)

    def create_get_request_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_get_request(addresses)

    def create_set_request_validator_info(
            self, validator_name, transaction_id, signup_info=None):
        if signup_info is None:
            signup_info = self.create_signup_info(self.public_key_hash, "000")
        data = ValidatorInfo(
            name=validator_name,
            id=self.public_key,
            signup_info=signup_info,
            transaction_id=transaction_id
        ).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_set_response(addresses)

    def create_del_request_validator_info(self):
        data = b''
        address = self._key_to_address(self.public_key)
        return self._factory.create_set_request({address: data})

    def create_del_response_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_set_response(addresses)

    def create_get_request_validator_map(self):
        address = self._key_to_address("validator_map")
        addresses = [address]
        return self._factory.create_get_request(addresses)

    def create_get_empty_response_validator_map(self):
        address = self._key_to_address("validator_map")
        data = ValidatorMap().SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_get_response_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.public_key_hash,
                                  value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.public_key_hash,
                                  value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_map(self):
        addresses = [self._key_to_address("validator_map")]
        return self._factory.create_set_response(addresses)

    def create_get_request_report_key_pem(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8e97a7d614626e4500e3b0c44298fc1c14'])

    def create_get_response_report_key_pem(self, pem=None):
        setting = Setting()
        if pem is not None:
            entry = Setting.Entry(key='sawtooth.poet.report_public_key_pem',
                                  value=pem)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e97a7d614626e4500e3b0c44298fc1c14': data})

    def create_get_response_simulator_report_key_pem(self):
        pem = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMvzZi8GT+lI9KeZiInn
4CvFTiuyid+IN4dP1+mhTnfxX+I/ntt8LUKZMbI1R1izOUoxJRoX6VQ4S9VgDLEC
PW6QlkeLI1eqe4DiYb9+J5ANhq4+XkhwgCUUFwpfqSfXWCHimjaGsZHbavl5nv/6
IbZJL/2YzE37IzJdES16JCfmIUrk6TUqL0WgrWXyweTIoVSbld0M29kToSkMXLsj
8vbQbTiKwViWhYlzi0cQIo7PiAss66lAW0X6AM7ZJYyAcfSjSLR4guMz76Og8aRk
jtsjEEkq7Ndz5H8hllWUoHpxGDqLhM9O1/h+QdvTz7luZgpeJ5KB92vYL6yOlSxM
fQIDAQAB
-----END PUBLIC KEY-----'''

        return self.create_get_response_report_key_pem(pem=pem)

    def create_get_request_enclave_measurements(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8e39ccaeec28506829e3b0c44298fc1c14'])

    def create_get_response_enclave_measurements(self, measurements=None):
        setting = Setting()
        if measurements is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_measurements',
                                  value=measurements)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e39ccaeec28506829e3b0c44298fc1c14': data})

    def create_get_response_simulator_enclave_measurements(self):
        return \
            self.create_get_response_enclave_measurements(
                measurements='c99f21955e38dbb03d2ca838d3af6e43'
                             'ef438926ed02db4cc729380c8c7a174e')

    def create_get_request_enclave_basenames(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8ebec3b47bc008b27de3b0c44298fc1c14'])

    def create_get_response_enclave_basenames(self, basenames=None):
        setting = Setting()
        if basenames is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_basenames',
                                  value=basenames)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8ebec3b47bc008b27de3b0c44298fc1c14': data})

    def create_get_response_simulator_enclave_basenames(self):
        return \
            self.create_get_response_enclave_basenames(
                basenames='b785c58b77152cbe7fd55ee3851c4990'
                          '00000000000000000000000000000000')
class ValidatorRegistryMessageFactory(object):
    # The basename and enclave measurement values we will put into the enclave
    # quote in the attestation verification report.
    __VALID_BASENAME__ = \
        bytes.fromhex(
            'b785c58b77152cbe7fd55ee3851c4990'
            '00000000000000000000000000000000')
    __VALID_ENCLAVE_MEASUREMENT__ = \
        bytes.fromhex(
            'c99f21955e38dbb03d2ca838d3af6e43'
            'ef438926ed02db4cc729380c8c7a174e')

    __REPORT_PRIVATE_KEY_PEM__ = \
        '-----BEGIN PRIVATE KEY-----\n' \
        'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsy/NmLwZP6Uj0\n' \
        'p5mIiefgK8VOK7KJ34g3h0/X6aFOd/Ff4j+e23wtQpkxsjVHWLM5SjElGhfpVDhL\n' \
        '1WAMsQI9bpCWR4sjV6p7gOJhv34nkA2Grj5eSHCAJRQXCl+pJ9dYIeKaNoaxkdtq\n' \
        '+Xme//ohtkkv/ZjMTfsjMl0RLXokJ+YhSuTpNSovRaCtZfLB5MihVJuV3Qzb2ROh\n' \
        'KQxcuyPy9tBtOIrBWJaFiXOLRxAijs+ICyzrqUBbRfoAztkljIBx9KNItHiC4zPv\n' \
        'o6DxpGSO2yMQSSrs13PkfyGWVZSgenEYOouEz07X+H5B29PPuW5mCl4nkoH3a9gv\n' \
        'rI6VLEx9AgMBAAECggEAImfFge4RCq4/eX85gcc7pRXyBjuLJAqe+7d0fWAmXxJg\n' \
        'vB+3XTEEi5p8GDoMg7U0kk6kdGe6pRnAz9CffEduU78FCPcbzCCzcD3cVWwkeUok\n' \
        'd1GQV4OC6vD3DBNjsrGdHg45KU18CjUphCZCQhdjvXynG+gZmWxZecuYXkg4zqPT\n' \
        'LwOkcdWBPhJ9CbjtiYOtKDZbhcbdfnb2fkxmvnAoz1OWNfVFXh+x7651FrmL2Pga\n' \
        'xGz5XoxFYYT6DWW1fL6GNuVrd97wkcYUcjazMgunuUMC+6XFxqK+BoqnxeaxnsSt\n' \
        'G2r0sdVaCyK1sU41ftbEQsc5oYeQ3v5frGZL+BgrYQKBgQDgZnjqnVI/B+9iarx1\n' \
        'MjAFyhurcKvFvlBtGKUg9Q62V6wI4VZvPnzA2zEaR1J0cZPB1lCcMsFACpuQF2Mr\n' \
        '3VDyJbnpSG9q05POBtfLjGQdXKtGb8cfXY2SwjzLH/tvxHm3SP+RxvLICQcLX2/y\n' \
        'GTJ+mY9C6Hs6jIVLOnMWkRWamQKBgQDFITE3Qs3Y0ZwkKfGQMKuqJLRw29Tyzw0n\n' \
        'XKaVmO/pEzYcXZMPBrFhGvdmNcJLo2fcsmGZnmit8RP4ChwHUlD11dH1Ffqw9FWc\n' \
        '387i0chlE5FhQPirSM8sWFVmjt2sxC4qFWJoAD/COQtKHgEaVKVc4sH/yRostL1C\n' \
        'r+7aWuqzhQKBgQDcuC5LJr8VPGrbtPz1kY3mw+r/cG2krRNSm6Egj6oO9KFEgtCP\n' \
        'zzjKQU9E985EtsqNKI5VdR7cLRLiYf6r0J6j7zO0IAlnXADP768miUqYDuRw/dUw\n' \
        'JsbwCZneefDI+Mp325d1/egjla2WJCNqUBp4p/Zf62f6KOmbGzzEf6RuUQKBgG2y\n' \
        'E8YRiaTOt5m0MXUwcEZk2Hg5DF31c/dkalqy2UYU57aPJ8djzQ8hR2x8G9ulWaWJ\n' \
        'KiCm8s9gaOFNFt3II785NfWxPmh7/qwmKuUzIdWFNxAsbHQ8NvURTqyccaSzIpFO\n' \
        'hw0inlhBEBQ1cB2r3r06fgQNb2BTT0Itzrd5gkNVAoGBAJcMgeKdBMukT8dKxb4R\n' \
        '1PgQtFlR3COu2+B00pDyUpROFhHYLw/KlUv5TKrH1k3+E0KM+winVUIcZHlmFyuy\n' \
        'Ilquaova1YSFXP5cpD+PKtxRV76Qlqt6o+aPywm81licdOAXotT4JyJhrgz9ISnn\n' \
        'J13KkHoAZ9qd0rX7s37czb3O\n' \
        '-----END PRIVATE KEY-----'

    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(
            encoding="application/protobuf",
            family_name="sawtooth_validator_registry",
            family_version="1.0",
            namespace="6a4372",
            private=private,
            public=public
        )
        self.pubkey_hash = hashlib.sha256(public.encode()).hexdigest()
        self._report_private_key = \
            serialization.load_pem_private_key(
                self.__REPORT_PRIVATE_KEY_PEM__.encode(),
                password=None,
                backend=backends.default_backend())

        # First we need to create a public/private key pair for the PoET
        # enclave to use.
        self._poet_private_key = \
            "1f70fa2518077ad18483f48e77882d11983b537fa5f7cf158684d2c670fe4f1f"
        self.poet_public_key = \
            signing.generate_pubkey(self._poet_private_key)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    # Utility function for creating proof data as we need to be
    # able to update signatures when verification report changes
    # Returns a serialized proof data
    def create_proof_data(self, verification_report, evidence_payload):
        verification_report_json = json.dumps(verification_report)
        signature = \
            self._report_private_key.sign(
                verification_report_json.encode(),
                padding.PKCS1v15(),
                hashes.SHA256())
        proof_data_dict = OrderedDict([
            ('evidence_payload', evidence_payload),
            ('verification_report', verification_report_json),
            ('signature', base64.b64encode(signature).decode())]
        )

        return json.dumps(proof_data_dict)

    # Currently this is done in the enclave
    def create_signup_info(self, originator_public_key_hash, nonce):
        # currently not used
        # _active_wait_timer = None

        # We are going to fake out the sealing the signup data.
        signup_data = {
            'poet_public_key': self.poet_public_key,
            'poet_private_key': self._poet_private_key
        }

        # Build up a fake SGX quote containing:
        # 1. The basename
        # 2. The report body that contains:
        #    a. The enclave measurement
        #    b. The report data SHA256(SHA256(OPK)|PPK)
        sgx_basename = \
            sgx_structs.SgxBasename(name=self.__VALID_BASENAME__)
        sgx_measurement = \
            sgx_structs.SgxMeasurement(
                m=self.__VALID_ENCLAVE_MEASUREMENT__)

        hash_input = \
            '{0}{1}'.format(
                originator_public_key_hash.upper(),
                self.poet_public_key.upper()).encode()
        report_data = hashlib.sha256(hash_input).digest()

        sgx_report_data = sgx_structs.SgxReportData(d=report_data)
        sgx_report_body = \
            sgx_structs.SgxReportBody(
                mr_enclave=sgx_measurement,
                report_data=sgx_report_data)

        sgx_quote = \
            sgx_structs.SgxQuote(
                basename=sgx_basename,
                report_body=sgx_report_body)

        # Create a fake PSE manifest.  A base64 encoding of the
        # originator public key hash should suffice.
        pse_manifest = \
            base64.b64encode(originator_public_key_hash.encode())

        timestamp = '2017-02-16T15:21:24.437048'

        # Fake our "proof" data.
        verification_report = OrderedDict([
            ('epidPseudonym', originator_public_key_hash),
            ('id', base64.b64encode(
                hashlib.sha256(
                    timestamp.encode()).hexdigest().encode()).decode()),
            ('isvEnclaveQuoteStatus', 'OK'),
            ('isvEnclaveQuoteBody',
                base64.b64encode(sgx_quote.serialize_to_bytes()).decode()),
            ('pseManifestStatus', 'OK'),
            ('pseManifestHash',
                hashlib.sha256(base64.b64decode(pse_manifest)).hexdigest()),
            ('nonce', nonce),
            ('timestamp', timestamp)
        ])

        proof_data = \
            self.create_proof_data(
                verification_report=verification_report,
                evidence_payload={
                    'pse_manifest': pse_manifest.decode()
                })

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash,
                nonce=nonce)

    def create_tp_process_request(self, validator_id, payload):
        inputs = [
            self._key_to_address('validator_list')
        ]

        outputs = [
            self._key_to_address('validator_list'),
            self._key_to_address(validator_id)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [], False)

    def create_get_request_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_get_request(addresses)

    def create_get_response_validator_info(self, validator_name):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(
            registered="registered",
            name=validator_name,
            id=self.public_key,
            signup_info=signup_info,
            transaction_id="0103c991863cae73630fe0a9b8988ad35840a3994ad010cd4c"
                           "60f17ca70b2054115bd5bdb0233f745826a61db0d83a32365f"
                           "e4026b39a731b0e457a5f09be194"
        ).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_info(self, validator_name, reg):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(
            registered=reg,
            name=validator_name,
            id=self.public_key,
            signup_info=signup_info,
            transaction_id="0103c991863cae73630fe0a9b8988ad35840a3994ad010cd4c"
                           "60f17ca70b2054115bd5bdb0233f745826a61db0d83a32365f"
                           "e4026b39a731b0e457a5f09be194"
        ).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_set_response(addresses)

    def create_get_request_validator_map(self):
        address = self._key_to_address("validator_map")
        addresses = [address]
        return self._factory.create_get_request(addresses)

    def create_get_empty_response_validator_map(self):
        address = self._key_to_address("validator_map")
        data = ValidatorMap().SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_get_response_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_map(self):
        addresses = [self._key_to_address("validator_map")]
        return self._factory.create_set_response(addresses)

    def create_get_request_report_key_pem(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8e97a7d614626e4500e3b0c44298fc1c14'])

    def create_get_response_report_key_pem(self, pem=None):
        setting = Setting()
        if pem is not None:
            entry = Setting.Entry(key='sawtooth.poet.report_public_key_pem',
                                  value=pem)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e97a7d614626e4500e3b0c44298fc1c14': data})

    def create_get_response_simulator_report_key_pem(self):
        pem = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMvzZi8GT+lI9KeZiInn
4CvFTiuyid+IN4dP1+mhTnfxX+I/ntt8LUKZMbI1R1izOUoxJRoX6VQ4S9VgDLEC
PW6QlkeLI1eqe4DiYb9+J5ANhq4+XkhwgCUUFwpfqSfXWCHimjaGsZHbavl5nv/6
IbZJL/2YzE37IzJdES16JCfmIUrk6TUqL0WgrWXyweTIoVSbld0M29kToSkMXLsj
8vbQbTiKwViWhYlzi0cQIo7PiAss66lAW0X6AM7ZJYyAcfSjSLR4guMz76Og8aRk
jtsjEEkq7Ndz5H8hllWUoHpxGDqLhM9O1/h+QdvTz7luZgpeJ5KB92vYL6yOlSxM
fQIDAQAB
-----END PUBLIC KEY-----'''

        return self.create_get_response_report_key_pem(pem=pem)

    def create_get_request_enclave_measurements(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8e39ccaeec28506829e3b0c44298fc1c14'])

    def create_get_response_enclave_measurements(self, measurements=None):
        setting = Setting()
        if measurements is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_measurements',
                                  value=measurements)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e39ccaeec28506829e3b0c44298fc1c14': data})

    def create_get_response_simulator_enclave_measurements(self):
        return \
            self.create_get_response_enclave_measurements(
                measurements='c99f21955e38dbb03d2ca838d3af6e43'
                             'ef438926ed02db4cc729380c8c7a174e')

    def create_get_request_enclave_basenames(self):
        return \
            self._factory.create_get_request(
                ['000000a87cb5eafdcca6a87ccc804f5546a'
                 'b8ebec3b47bc008b27de3b0c44298fc1c14'])

    def create_get_response_enclave_basenames(self, basenames=None):
        setting = Setting()
        if basenames is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_basenames',
                                  value=basenames)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8ebec3b47bc008b27de3b0c44298fc1c14': data})

    def create_get_response_simulator_enclave_basenames(self):
        return \
            self.create_get_response_enclave_basenames(
                basenames='b785c58b77152cbe7fd55ee3851c4990'
                          '00000000000000000000000000000000')
class SettingsMessageFactory:
    def __init__(self, signer=None):
        self._factory = MessageFactory(
            family_name="sawtooth_settings",
            family_version="1.0",
            namespace="000000",
            signer=signer)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        key_parts = key.split('.', maxsplit=_MAX_KEY_PARTS - 1)
        key_parts.extend([''] * (_MAX_KEY_PARTS - len(key_parts)))

        def _short_hash(in_str):
            return self._factory.sha256(in_str.encode())[:16]

        return self._factory.namespace + \
            ''.join(_short_hash(x) for x in key_parts)

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, setting, payload):
        inputs = [
            self._key_to_address('sawtooth.settings.vote.proposals'),
            self._key_to_address('sawtooth.settings.vote.authorized_keys'),
            self._key_to_address('sawtooth.settings.vote.approval_threshold'),
            self._key_to_address(setting)
        ]

        outputs = [
            self._key_to_address('sawtooth.settings.vote.proposals'),
            self._key_to_address(setting)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_proposal_transaction(self, setting, value, nonce):
        proposal = SettingProposal(setting=setting, value=value, nonce=nonce)
        payload = SettingsPayload(action=SettingsPayload.PROPOSE,
                                  data=proposal.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_vote_proposal(self, proposal_id, setting, vote):
        vote = SettingVote(proposal_id=proposal_id, vote=vote)
        payload = SettingsPayload(action=SettingsPayload.VOTE,
                                  data=vote.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_get_request(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_set_response(addresses)

    def create_add_event_request(self, key):
        return self._factory.create_add_event_request(
            "settings/update",
            [("updated", key)])

    def create_add_event_response(self):
        return self._factory.create_add_event_response()
class EventMessageFactory(object):
    def __init__(self, signer=None):
        self._factory = MessageFactory(
            family_name=FAMILY_NAME,
            family_version="0.1.0",
            namespace=[EVENTS_ADDRESS_PREFIX],
            signer=signer)

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        key_parts = key.split('.', maxsplit=_MAX_KEY_PARTS - 1)
        key_parts.extend([''] * (_MAX_KEY_PARTS - len(key_parts)))

        def _short_hash(in_str):
            return self._factory.sha256(in_str.encode())[:16]

        return self._factory.namespace + \
            ''.join(_short_hash(x) for x in key_parts)

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, code, payload):
        inputs = [
            self._key_to_address('hashblock.events.initiate'),
            self._key_to_address('hashblock.events.reciprocate'),
            self._key_to_address(code)
        ]

        outputs = [
            self._key_to_address('hashblock.events.initiate'),
            self._key_to_address('hashblock.events.reciprocate'),
            self._key_to_address(code)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_initiate_transaction(
        self, code, version, plus,
            minus, quantity, nonce):
        initiate = InitiateEvent(
            version=version, plus=plus,
            minus=minus, nonce=nonce)
        payload = EventPayload(
            action=EventPayload.INITIATE_EVENT,
            data=initiate.SerializeToString())

        return self._create_tp_process_request(code, payload)

    def create_reciprocate_transaction(self, proposal_id, code, vote):
        vote = ReciprocateEvent(proposal_id=proposal_id, vote=vote)
        payload = EventPayload(
            action=EventPayload.RECIPROCATE_EVENT,
            data=vote.SerializeToString())

        return self._create_tp_process_request(code, payload)

    def create_get_request(self, code):
        addresses = [self._key_to_address(code)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, code, value=None):
        address = self._key_to_address(code)

        if value is not None:
            entry = Unit.Entry(key=code, value=value)
            data = Unit(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, code, value=None):
        address = self._key_to_address(code)

        if value is not None:
            entry = Unit.Entry(key=code, value=value)
            data = Unit(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, code):
        addresses = [self._key_to_address(code)]
        return self._factory.create_set_response(addresses)

    def create_add_event_request(self, key):
        return self._factory.create_add_event_request(
            "events/update",
            [("updated", key)])

    def create_add_event_response(self):
        return self._factory.create_add_event_response()
class ValidatorRegistryMessageFactory(object):
    __REPORT_PRIVATE_KEY_PEM__ = \
        '-----BEGIN PRIVATE KEY-----\n' \
        'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsy/NmLwZP6Uj0\n' \
        'p5mIiefgK8VOK7KJ34g3h0/X6aFOd/Ff4j+e23wtQpkxsjVHWLM5SjElGhfpVDhL\n' \
        '1WAMsQI9bpCWR4sjV6p7gOJhv34nkA2Grj5eSHCAJRQXCl+pJ9dYIeKaNoaxkdtq\n' \
        '+Xme//ohtkkv/ZjMTfsjMl0RLXokJ+YhSuTpNSovRaCtZfLB5MihVJuV3Qzb2ROh\n' \
        'KQxcuyPy9tBtOIrBWJaFiXOLRxAijs+ICyzrqUBbRfoAztkljIBx9KNItHiC4zPv\n' \
        'o6DxpGSO2yMQSSrs13PkfyGWVZSgenEYOouEz07X+H5B29PPuW5mCl4nkoH3a9gv\n' \
        'rI6VLEx9AgMBAAECggEAImfFge4RCq4/eX85gcc7pRXyBjuLJAqe+7d0fWAmXxJg\n' \
        'vB+3XTEEi5p8GDoMg7U0kk6kdGe6pRnAz9CffEduU78FCPcbzCCzcD3cVWwkeUok\n' \
        'd1GQV4OC6vD3DBNjsrGdHg45KU18CjUphCZCQhdjvXynG+gZmWxZecuYXkg4zqPT\n' \
        'LwOkcdWBPhJ9CbjtiYOtKDZbhcbdfnb2fkxmvnAoz1OWNfVFXh+x7651FrmL2Pga\n' \
        'xGz5XoxFYYT6DWW1fL6GNuVrd97wkcYUcjazMgunuUMC+6XFxqK+BoqnxeaxnsSt\n' \
        'G2r0sdVaCyK1sU41ftbEQsc5oYeQ3v5frGZL+BgrYQKBgQDgZnjqnVI/B+9iarx1\n' \
        'MjAFyhurcKvFvlBtGKUg9Q62V6wI4VZvPnzA2zEaR1J0cZPB1lCcMsFACpuQF2Mr\n' \
        '3VDyJbnpSG9q05POBtfLjGQdXKtGb8cfXY2SwjzLH/tvxHm3SP+RxvLICQcLX2/y\n' \
        'GTJ+mY9C6Hs6jIVLOnMWkRWamQKBgQDFITE3Qs3Y0ZwkKfGQMKuqJLRw29Tyzw0n\n' \
        'XKaVmO/pEzYcXZMPBrFhGvdmNcJLo2fcsmGZnmit8RP4ChwHUlD11dH1Ffqw9FWc\n' \
        '387i0chlE5FhQPirSM8sWFVmjt2sxC4qFWJoAD/COQtKHgEaVKVc4sH/yRostL1C\n' \
        'r+7aWuqzhQKBgQDcuC5LJr8VPGrbtPz1kY3mw+r/cG2krRNSm6Egj6oO9KFEgtCP\n' \
        'zzjKQU9E985EtsqNKI5VdR7cLRLiYf6r0J6j7zO0IAlnXADP768miUqYDuRw/dUw\n' \
        'JsbwCZneefDI+Mp325d1/egjla2WJCNqUBp4p/Zf62f6KOmbGzzEf6RuUQKBgG2y\n' \
        'E8YRiaTOt5m0MXUwcEZk2Hg5DF31c/dkalqy2UYU57aPJ8djzQ8hR2x8G9ulWaWJ\n' \
        'KiCm8s9gaOFNFt3II785NfWxPmh7/qwmKuUzIdWFNxAsbHQ8NvURTqyccaSzIpFO\n' \
        'hw0inlhBEBQ1cB2r3r06fgQNb2BTT0Itzrd5gkNVAoGBAJcMgeKdBMukT8dKxb4R\n' \
        '1PgQtFlR3COu2+B00pDyUpROFhHYLw/KlUv5TKrH1k3+E0KM+winVUIcZHlmFyuy\n' \
        'Ilquaova1YSFXP5cpD+PKtxRV76Qlqt6o+aPywm81licdOAXotT4JyJhrgz9ISnn\n' \
        'J13KkHoAZ9qd0rX7s37czb3O\n' \
        '-----END PRIVATE KEY-----'

    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(
            encoding="application/protobuf",
            family_name="sawtooth_validator_registry",
            family_version="1.0",
            namespace="6a4372",
            private=private,
            public=public)
        self.pubkey_hash = hashlib.sha256(public.encode()).hexdigest()
        self._report_private_key = \
            serialization.load_pem_private_key(
                self.__REPORT_PRIVATE_KEY_PEM__.encode(),
                password=None,
                backend=backends.default_backend())

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    # Utility function for creating proof data as we need to be
    # able to update signatures when verification report changes
    # Returns a serialized proof data
    def create_proof_data(self, verification_report, evidence_payload):
        verification_report_json = json.dumps(verification_report)
        signature = \
            self._report_private_key.sign(
                verification_report_json.encode(),
                padding.PKCS1v15(),
                hashes.SHA256())
        proof_data_dict = {
            'evidence_payload': evidence_payload,
            'verification_report': verification_report_json,
            'signature': base64.b64encode(signature).decode()
        }

        return json.dumps(proof_data_dict)

    # Currently this is done in the enclave
    def create_signup_info(self, originator_public_key_hash,
                           most_recent_wait_certificate_id):
        # First we need to create a public/private key pair for the PoET
        # enclave to use.
        poet_private_key = \
            "1f70fa2518077ad18483f48e77882d11983b537fa5f7cf158684d2c670fe4f1f"
        poet_public_key = \
            signing.generate_pubkey(poet_private_key)
        # currently not used
        # _active_wait_timer = None

        # We are going to fake out the sealing the signup data.
        signup_data = {
            'poet_public_key': signing.encode_pubkey(poet_public_key, 'hex'),
            'poet_private_key': signing.encode_privkey(poet_private_key, 'hex')
        }

        # Create a fake report
        report_data = '{0}{1}'.format(
            originator_public_key_hash.upper(),
            signing.encode_pubkey(poet_public_key, 'hex').upper())
        quote = {
            'report_body':
            hashlib.sha256(json.dumps(report_data).encode()).hexdigest()
        }

        # Create a fake PSE manifest.  A base64 encoding of the
        # originator public key hash should suffice.
        pse_manifest = \
            base64.b64encode(originator_public_key_hash.encode())

        timestamp = '2017-02-16T15:21:24.437048'

        # Fake our "proof" data.
        verification_report = {
            'epidPseudonym':
            originator_public_key_hash,
            'id':
            base64.b64encode(
                hashlib.sha256(
                    timestamp.encode()).hexdigest().encode()).decode(),
            'isvEnclaveQuoteStatus':
            'OK',
            'isvEnclaveQuoteBody':
            base64.b64encode(json.dumps(quote).encode()).decode(),
            'pseManifestStatus':
            'OK',
            'pseManifestHash':
            base64.b64encode(
                hashlib.sha256(pse_manifest).hexdigest().encode()).decode(),
            'nonce':
            most_recent_wait_certificate_id,
            'timestamp':
            timestamp
        }

        proof_data = \
            self.create_proof_data(
                verification_report=verification_report,
                evidence_payload={
                    'pse_manifest': pse_manifest.decode()
                })

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash)

    def create_tp_process_request(self, validator_id, payload):
        inputs = [self._key_to_address('validator_list')]

        outputs = [
            self._key_to_address('validator_list'),
            self._key_to_address(validator_id)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_get_request_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_get_request(addresses)

    def create_get_response_validator_info(self, validator_name):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(registered="registered",
                             name=validator_name,
                             id=self.public_key,
                             signup_info=signup_info,
                             block_num=0).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_info(self, validator_name, reg):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(registered=reg,
                             name=validator_name,
                             id=self.public_key,
                             signup_info=signup_info,
                             block_num=0).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_set_response(addresses)

    def create_get_request_validator_map(self):
        address = self._key_to_address("validator_map")
        addresses = [address]
        return self._factory.create_get_request(addresses)

    def create_get_empty_resposne_validator_map(self):
        address = self._key_to_address("validator_map")
        data = ValidatorMap().SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_get_response_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_map(self):
        addresses = [self._key_to_address("validator_map")]
        return self._factory.create_set_response(addresses)
Exemple #13
0
class ValidatorRegistryMessageFactory(object):
    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(
            encoding="application/protobuf",
            family_name="sawtooth_validator_registry",
            family_version="1.0",
            namespace="6a4372",
            private=private,
            public=public)
        self.pubkey_hash = hashlib.sha256(public.encode()).hexdigest()

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    # Currently this is done in the enclave
    def create_signup_info(self, originator_public_key_hash,
                           most_recent_wait_certificate_id):
        # First we need to create a public/private key pair for the PoET
        # enclave to use.
        _poet_private_key = \
            "1f70fa2518077ad18483f48e77882d11983b537fa5f7cf158684d2c670fe4f1f"
        _poet_public_key = \
            signing.generate_pubkey(_poet_private_key)
        # currently not used
        # _active_wait_timer = None

        _report_private_key = \
            signing.encode_privkey(
                signing.decode_privkey(
                    '5Jz5Kaiy3kCiHE537uXcQnJuiNJshf2bZZn43CrALMGoCd3zRuo',
                    'wif'), 'hex')

        # We are going to fake out the sealing the signup data.
        signup_data = {
            'poet_public_key': signing.encode_pubkey(_poet_public_key, 'hex'),
            'poet_private_key': signing.encode_privkey(_poet_private_key,
                                                       'hex')
        }

        # Create a fake report
        report_data = '{0}{1}'.format(
            originator_public_key_hash.upper(),
            signing.encode_pubkey(_poet_public_key, 'hex').upper())
        quote = {
            'report_body':
            hashlib.sha256(json.dumps(report_data).encode()).hexdigest()
        }

        # Fake our "proof" data.
        verification_report = {
            'id':
            base64.b64encode(
                bytes(
                    hashlib.sha256(b'2017-02-16T15:21:24.437048').hexdigest().
                    encode())).decode(),
            'isvEnclaveQuoteStatus':
            'OK',
            'isvEnclaveQuoteBody':
            base64.b64encode(json.dumps(quote).encode()).decode(),
            'pseManifestStatus':
            'OK',
            'pseManifestHash':
            base64.b64encode(
                hashlib.sha256(
                    bytes(
                        b'Do you believe in '
                        b'manifest destiny?')).hexdigest().encode()).decode(),
            'nonce':
            most_recent_wait_certificate_id
        }

        proof_data_dict = {
            'verification_report':
            json.dumps(verification_report),
            'signature':
            signing.sign(json.dumps(verification_report), _report_private_key)
        }
        proof_data = json.dumps(proof_data_dict)

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash)

    def create_tp_process_request(self, validator_id, payload):
        inputs = [self._key_to_address('validator_list')]

        outputs = [
            self._key_to_address('validator_list'),
            self._key_to_address(validator_id)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_get_request_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_get_request(addresses)

    def create_get_response_validator_info(self, validator_name):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(registered="registered",
                             name=validator_name,
                             id=self.public_key,
                             signup_info=signup_info,
                             block_num=0).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_info(self, validator_name, reg):
        signup_info = self.create_signup_info(self.pubkey_hash, "000")
        data = ValidatorInfo(registered=reg,
                             name=validator_name,
                             id=self.public_key,
                             signup_info=signup_info,
                             block_num=0).SerializeToString()

        address = self._key_to_address(self.public_key)
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_info(self):
        addresses = [self._key_to_address(self.public_key)]
        return self._factory.create_set_response(addresses)

    def create_get_request_validator_map(self):
        address = self._key_to_address("validator_map")
        addresses = [address]
        return self._factory.create_get_request(addresses)

    def create_get_empty_resposne_validator_map(self):
        address = self._key_to_address("validator_map")
        data = ValidatorMap().SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_get_response_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_get_response({address: data})

    def create_set_request_validator_map(self):
        address = self._key_to_address("validator_map")
        validator_map = ValidatorMap()
        validator_map.entries.add(key=self.pubkey_hash, value=self.public_key)
        data = validator_map.SerializeToString()
        return self._factory.create_set_request({address: data})

    def create_set_response_validator_map(self):
        addresses = [self._key_to_address("validator_map")]
        return self._factory.create_set_response(addresses)
class ConfigMessageFactory(object):

    def __init__(self, private=None, public=None):
        self._factory = MessageFactory(
            encoding="application/protobuf",
            family_name="sawtooth_config",
            family_version="1.0",
            namespace="000000",
            private=private,
            public=public
        )

    @property
    def public_key(self):
        return self._factory.get_public_key()

    def _key_to_address(self, key):
        return self._factory.namespace + \
            self._factory.sha256(key.encode("utf-8"))

    def create_tp_register(self):
        return self._factory.create_tp_register()

    def create_tp_response(self, status):
        return self._factory.create_tp_response(status)

    def _create_tp_process_request(self, setting, payload):
        inputs = [
            self._key_to_address('sawtooth.config.authorization_type'),
            self._key_to_address('sawtooth.config.vote.proposals'),
            self._key_to_address('sawtooth.config.vote.authorized_keys'),
            self._key_to_address('sawtooth.config.vote.approval_threshold'),
            self._key_to_address(setting)
        ]

        outputs = [
            self._key_to_address('sawtooth.config.vote.proposals'),
            self._key_to_address(setting)
        ]

        return self._factory.create_tp_process_request(
            payload.SerializeToString(), inputs, outputs, [])

    def create_proposal_transaction(self, setting, value, nonce):
        proposal = ConfigProposal(setting=setting, value=value, nonce=nonce)
        payload = ConfigPayload(action=ConfigPayload.PROPOSE,
                                data=proposal.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_vote_proposal(self, proposal_id, setting, vote):
        vote = ConfigVote(proposal_id=proposal_id, vote=vote)
        payload = ConfigPayload(action=ConfigPayload.VOTE,
                                data=vote.SerializeToString())

        return self._create_tp_process_request(setting, payload)

    def create_get_request(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_get_request(addresses)

    def create_get_response(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_get_response({address: data})

    def create_set_request(self, setting, value=None):
        address = self._key_to_address(setting)

        if value is not None:
            entry = Setting.Entry(key=setting, value=value)
            data = Setting(entries=[entry]).SerializeToString()
        else:
            data = None

        return self._factory.create_set_request({address: data})

    def create_set_response(self, setting):
        addresses = [self._key_to_address(setting)]
        return self._factory.create_set_response(addresses)