def compute_pdo_ccl_signature(private_key, enclave_id, enclave_signature,
                              channel_id, contract_id, creator_public_key_pem,
                              contract_code_hash, message_hash,
                              current_state_hash, previous_state_hash,
                              dependency_list):
    k = crypto.SIG_PrivateKey(private_key)
    message_byte_array = crypto.string_to_byte_array(enclave_id)
    message_byte_array += crypto.base64_to_byte_array(enclave_signature)
    message_byte_array += crypto.string_to_byte_array(channel_id)
    message_byte_array += crypto.string_to_byte_array(contract_id)
    message_byte_array += crypto.string_to_byte_array(creator_public_key_pem)
    message_byte_array += crypto.base64_to_byte_array(contract_code_hash)
    message_byte_array += crypto.base64_to_byte_array(message_hash)
    message_byte_array += crypto.base64_to_byte_array(current_state_hash)
    #in ccl initialize, previous state hash and dependencies are supposed to be empty
    if previous_state_hash:
        message_byte_array += crypto.base64_to_byte_array(previous_state_hash)
    for d in dependency_list:
        message_byte_array += crypto.string_to_byte_array(d.contract_id)
        message_byte_array += crypto.string_to_byte_array(d.state_hash)
    signature = k.SignMessage(message_byte_array)
    encoded_signature = crypto.byte_array_to_base64(signature)
    logger.debug("signed message string: " +
                 crypto.byte_array_to_base64(message_byte_array))
    logger.debug("signed message hash: " + crypto.byte_array_to_hex(
        crypto.compute_message_hash(message_byte_array)))
    logger.debug("signature: %s", encoded_signature)
    return encoded_signature
def from_transaction_signature_to_id(transaction_signature):
    """function to transform a hex transaction signature (or transaction identifier)
    into a base64 id which is used (for instance) for a contract id
    """
    id = crypto.byte_array_to_base64(
        crypto.compute_message_hash(
            crypto.hex_to_byte_array(transaction_signature)))
    return id
Exemple #3
0
    def __encryption_key__(password):
        """create an AES encryption/decryption key from the password
        """
        try:
            password = password.encode('utf-8')
        except AttributeError:
            pass

        return crypto.compute_message_hash(password)[:16]
    def compute_hash(self, encoding = 'raw') :
        # the code hash is a combination of the hash of the actual code,
        # and the hash of the nonce.
        # this makes it possible to use the nonce to verify the identity
        # of the actual code (think MRENCLAVE).
        code_hash = crypto.compute_message_hash(crypto.string_to_byte_array(self.code + self.name))
        nonce_hash = crypto.compute_message_hash(crypto.string_to_byte_array(self.nonce))
        message = code_hash + nonce_hash

        code_hash = crypto.compute_message_hash(message)
        if encoding == 'raw' :
            return code_hash
        elif encoding == 'hex' :
            return crypto.byte_array_to_hex(code_hash)
        elif encoding == 'b64' :
            return crypto.byte_array_to_base64(code_hash)
        else :
            raise ValueError('unknown hash encoding; {}'.format(encoding))
Exemple #5
0
 def compute_hash(self, encoding = 'raw') :
     serialized = self.__serialize_for_hashing()
     code_hash = crypto.compute_message_hash(crypto.string_to_byte_array(serialized))
     if encoding == 'raw' :
         return code_hash
     elif encoding == 'hex' :
         return crypto.byte_array_to_hex(code_hash)
     elif encoding == 'b64' :
         return crypto.byte_array_to_base64(code_hash)
     else :
         raise ValueError('unknown hash encoding; {}'.format(encoding))
Exemple #6
0
 def make_channel_keys(self, ledger_type=os.environ.get('PDO_LEDGER_TYPE')):
     if ledger_type == 'sawtooth':
         self.channel_keys = keys.TransactionKeys()
         self.channel_id = self.channel_keys.txn_public
     elif ledger_type == 'ccf':
         self.channel_keys = crypto.random_bit_string(64)  # byte array
         self.channel_id = crypto.byte_array_to_base64(
             crypto.compute_message_hash(self.channel_keys))
     else:
         raise Exception(
             "Invalid Ledger Type. Must be either sawtooth or ccf.")
Exemple #7
0
    def compute_hash(encrypted_state, encoding='raw'):
        """ compute the hash of the encrypted state
        """
        state_byte_array = crypto.base64_to_byte_array(encrypted_state)
        state_hash = crypto.compute_message_hash(state_byte_array)
        if encoding == 'raw':
            return state_hash
        elif encoding == 'b64':
            return crypto.byte_array_to_base64(state_hash)
        elif encoding == 'hex':
            return crypto.byte_array_to_hex(state_hash)

        raise ValueError('unknown encoding; {}'.format(encoding))
Exemple #8
0
    def compute_hash(raw_state, encoding='raw'):
        """ compute the hash of the contract state

        :param raw_state string: root block of contract state, json string
        """
        state_hash = crypto.compute_message_hash(raw_state)
        if encoding == 'raw':
            return state_hash
        elif encoding == 'b64':
            return crypto.byte_array_to_base64(state_hash)
        elif encoding == 'hex':
            return crypto.byte_array_to_hex(state_hash)

        raise ValueError('unknown encoding; {}'.format(encoding))
Exemple #9
0
    def build_contract_registration_from_data(
        contract_creator_keys,
        contract_code_hash,
        provisioning_service_ids):
        payloadblob = dict()
        payloadblob['contract_code_hash'] = contract_code_hash
        payloadblob['provisioning_service_ids'] = provisioning_service_ids
        payloadblob['contract_creator_verifying_key_PEM'] = contract_creator_keys.verifying_key

        # sign the payload after adding a nonce
        nonce = time.time().hex()
        payloadblob['nonce'] = nonce
        payloadblob['signature'] = compute_pdo_signature_contract_registration(contract_creator_keys.signing_key,
                contract_creator_keys.verifying_key, contract_code_hash, provisioning_service_ids, nonce)
        payloadblob['contract_id'] = \
            crypto.byte_array_to_base64(crypto.compute_message_hash(payloadblob['signature']))

        return payloadblob
def verify_state_encryption_key_signature(encrypted_state_key, secret_list,
                                          contract_id, creator_id, signature,
                                          enclave_keys):
    """verify the signature on the contract state encryption key received from the enclave

    :param encrypted_state_key; base64 encoded string
    :param secret_list: array of dictionary defines values for pspk and encrypted_secret
    :param contract_id: 16 character, hex encoded, sha256 hashed, registration transaction signature
    :param creator_id: PEM encoded ECDSA verifying key
    :param signature: base64 encoded signature
    :param enclave_keys: object of type :EnclaveKeys:
    """
    message = serialize_for_signing(encrypted_state_key, secret_list,
                                    contract_id, creator_id)
    logger.debug(
        "signed message has length %d and hash %s", len(message),
        crypto.byte_array_to_base64(crypto.compute_message_hash(message)))

    return enclave_keys.verify(message, signature, encoding='b64')
Exemple #11
0
def CreateAndRegisterContract(config, enclave, contract_creator_keys):
    global txn_dependencies

    data_dir = config['PDO']['DataPath']

    ledger_config = config.get('Sawtooth')
    contract_creator_id = contract_creator_keys.identity

    contract_name = config['contract']
    contract_code = contract_helper.ContractCode.create_from_scheme_file(
        contract_name, search_path=[".", "..", "contracts"])

    # create the provisioning servers
    if use_pservice:
        pservice_urls = config.get("pservice-urls")
        provisioning_services = list(
            map(lambda url: pservice_helper.ProvisioningServiceClient(url),
                pservice_urls))
    else:
        provisioning_services = secret_helper.create_provisioning_services(
            config['secrets'])
    provisioning_service_keys = list(
        map(lambda svc: svc.identity, provisioning_services))

    try:
        if use_ledger:
            contract_id = contract_helper.register_contract(
                ledger_config, contract_creator_keys, contract_code,
                provisioning_service_keys)
            logger.info('contract registration successful; %s', contract_id)
        else:
            contract_id = crypto.byte_array_to_base64(
                crypto.compute_message_hash(crypto.random_bit_string(256)))
            logger.info('no ledger config; skipping contract registration')
    except Exception as e:
        logger.error('failed to register the contract; %s', str(e))
        sys.exit(-1)

    contract_state = contract_helper.ContractState.create_new_state(
        contract_id)
    contract = contract_helper.Contract(contract_code, contract_state,
                                        contract_id, contract_creator_id)

    # --------------------------------------------------
    logger.info('create the provisioning secrets')
    # --------------------------------------------------
    if use_pservice:
        secret_list = []
        for pservice in provisioning_services:
            logger.debug('ask pservice %s to generate a secret for %s',
                         pservice.ServiceURL, contract_id)
            message = enclave.enclave_id + contract_id
            signature = contract_creator_keys.sign(message, encoding='hex')
            secret = pservice.get_secret(enclave.enclave_id, contract_id,
                                         contract_creator_keys.verifying_key,
                                         signature)
            if secret is None:
                logger.error('failed to create secret for %s',
                             pservice.ServiceURL)
                sys.exit(-1)
            secret_list.append(secret)
    else:
        secret_list = secret_helper.create_secrets_for_services(
            provisioning_services, enclave.enclave_keys, contract_id,
            contract_creator_id)

    logger.debug('secrets: %s', secret_list)

    try:
        secretinfo = enclave.verify_secrets(contract_id, contract_creator_id,
                                            secret_list)
        assert secretinfo

        encrypted_state_encryption_key = secretinfo[
            'encrypted_state_encryption_key']
        signature = secretinfo['signature']

    except Exception as e:
        logger.error('failed to create the state encryption key; %s', str(e))
        sys.exit(-1)

    try:
        if not secrets.verify_state_encryption_key_signature(
                encrypted_state_encryption_key, secret_list, contract_id,
                contract_creator_id, signature, enclave.enclave_keys):
            raise RuntimeError('signature verification failed')
    except Exception as e:
        logger.error('failed to verify the state encryption key; %s', str(e))
        sys.exit(-1)

    logger.info('encrypted state encryption key: %s',
                encrypted_state_encryption_key)

    # --------------------------------------------------
    logger.info('add the provisioned enclave to the contract')
    # --------------------------------------------------
    try:
        if use_ledger:
            txnid = contract_helper.add_enclave_to_contract(
                ledger_config,
                contract_creator_keys,
                contract_id,
                enclave.enclave_id,
                secret_list,
                encrypted_state_encryption_key,
                signature,
                transaction_dependency_list=txn_dependencies)
            txn_dependencies = [txnid]

            logger.info('contract state encryption key added to contract')
        else:
            logger.info(
                'no ledger config; skipping state encryption key registration')
    except Exception as e:
        logger.error('failed to add state encryption key; %s', str(e))
        sys.exit(-1)

    contract.set_state_encryption_key(enclave.enclave_id,
                                      encrypted_state_encryption_key)
    contract.save_to_file(contract_name, data_dir=data_dir)

    # --------------------------------------------------
    logger.info('create the initial contract state')
    # --------------------------------------------------
    try:
        initialize_request = contract.create_initialize_request(
            contract_creator_keys, enclave)
        initialize_response = initialize_request.evaluate()
        contract.set_state(initialize_response.encrypted_state)

    except Exception as e:
        logger.error('failed to create the initial state; %s', str(e))
        sys.exit(-1)

    logger.info('enclave created initial state')

    # --------------------------------------------------
    logger.info('save the initial state in the ledger')
    # --------------------------------------------------
    try:
        if use_ledger:
            logger.info("sending to ledger")
            # note that we will wait for commit of the transaction before
            # continuing; this is not necessary in general (if there is
            # confidence the transaction will succeed) but is useful for
            # testing
            txnid = initialize_response.submit_initialize_transaction(
                ledger_config,
                wait=30,
                transaction_dependency_list=txn_dependencies)
            txn_dependencies = [txnid]
        else:
            logger.info('no ledger config; skipping iniatialize state save')
    except Exception as e:
        logger.error('failed to save the initial state; %s', str(e))
        sys.exit(-1)

    contract.contract_state.save_to_cache(data_dir=data_dir)

    return contract
 def hashed_identity(self):
     key_byte_array = crypto.string_to_byte_array(self.txn_public)
     hashed_txn_key = crypto.compute_message_hash(key_byte_array)
     encoded_hashed_key = crypto.byte_array_to_hex(hashed_txn_key)
     encoded_hashed_key = encoded_hashed_key.lower()
     return encoded_hashed_key
            "Symmetric decryption (random IV) invalid key detection test successful!"
        )
    else:
        logger.error(
            "ERROR: Symmetric decryption (random IV) invalid key detection test failed: ",
            exc)
        sys.exit(-1)
try:
    iv = crypto.SKENC_GenerateIV("A message")
except Exception as exc:
    logger.error(
        "ERROR: Symmetric encryption deterministic iv generation test failed: ",
        exc)
    sys.exit(-1)
logger.debug(
    "Symmetric encryption deterministic iv generation test successful!")
try:
    rand = crypto.random_bit_string(16)
except Exception as exc:
    logger.error("ERROR: Random number generation failed: ", exc)
    sys.exit(-1)
logger.debug("Random number generation successful!")

hash = crypto.compute_message_hash(rand)
bhash = bytearray(hash)
b64hash = crypto.byte_array_to_base64(bhash)
logger.debug("Hash computed!")
crypto.base64_to_byte_array(b64hash)
logger.debug("SWIG CRYPTO_WRAPPER TEST SUCCESSFUL!")
sys.exit(0)
Exemple #14
0
def CreateAndRegisterContract(config, enclaves, contract_creator_keys):
    global txn_dependencies

    data_dir = config['Contract']['DataDirectory']

    ledger_config = config.get('Sawtooth')
    contract_creator_id = contract_creator_keys.identity

    try:
        contract_class = config['Contract']['Name']
        contract_source = config['Contract']['SourceFile']
        source_path = config['Contract']['SourceSearchPath']
        interpreter = config['Contract']['Interpreter']
        contract_code = contract_helper.ContractCode.create_from_file(
            contract_class,
            contract_source,
            source_path,
            interpreter=interpreter)
    except Exception as e:
        raise Exception('unable to load contract source; {0}'.format(str(e)))

    # create the provisioning servers
    if use_pservice:
        try:
            pservice_urls = config['Service']['ProvisioningServiceURLs']
            provisioning_services = list(
                map(lambda url: pservice_helper.ProvisioningServiceClient(url),
                    pservice_urls))
        except Exception as e:
            logger.error('failed to connect to provisioning service; %s',
                         str(e))
            ErrorShutdown()
    else:
        provisioning_services = secret_helper.create_provisioning_services(
            config['secrets'])
    provisioning_service_keys = list(
        map(lambda svc: svc.identity, provisioning_services))

    try:
        if use_ledger:
            contract_id = contract_helper.register_contract(
                ledger_config, contract_creator_keys, contract_code,
                provisioning_service_keys)
            logger.info('contract registration successful; %s', contract_id)
        else:
            contract_id = crypto.byte_array_to_base64(
                crypto.compute_message_hash(crypto.random_bit_string(256)))
            logger.debug('no ledger config; skipping contract registration')
    except Exception as e:
        logger.error('failed to register the contract; %s', str(e))
        ErrorShutdown()

    contract_state = contract_helper.ContractState.create_new_state(
        contract_id)
    contract = contract_helper.Contract(contract_code, contract_state,
                                        contract_id, contract_creator_id)

    # --------------------------------------------------
    logger.info('create the provisioning secrets')
    # --------------------------------------------------
    encrypted_state_encryption_keys = AddEnclaveSecrets(
        ledger_config, contract.contract_id, contract_creator_keys, enclaves,
        provisioning_services)

    for enclave_id in encrypted_state_encryption_keys:
        encrypted_key = encrypted_state_encryption_keys[enclave_id]
        contract.set_state_encryption_key(enclave_id, encrypted_key)

    #add replication information to contract
    AddReplicationParamsToContract(config, enclaves, contract)

    # Decide if the contract use a fixed enclave or a randomized one for each update.
    if use_eservice and config['Service']['Randomize_Eservice']:
        enclave_to_use = 'random'
    else:
        enclave_to_use = enclaves[0]

    # save the contract info as a pdo file
    contract_save_file = '_' + contract.short_id + '.pdo'
    contract.save_to_file(contract_save_file, data_dir=data_dir)

    # --------------------------------------------------
    logger.info('create the initial contract state')
    # --------------------------------------------------
    try:
        initialize_request = contract.create_initialize_request(
            contract_creator_keys, enclave_to_use)
        initialize_response = initialize_request.evaluate()
        if initialize_response.status is False:
            logger.error('contract initialization failed: %s',
                         initialize_response.invocation_response)
            ErrorShutdown()

        contract.set_state(initialize_response.raw_state)

    except Exception as e:
        logger.error('failed to create the initial state; %s', str(e))
        ErrorShutdown()

    logger.info('Created initial state')

    # submit the commit task: (a commit task replicates change-set and submits the corresponding transaction)
    try:
        initialize_response.commit_asynchronously(ledger_config)
    except Exception as e:
        logger.exception(
            'failed to asynchronously start replication and transaction submission:'
            + str(e))
        ErrorShutdown()

    # wait for the commit to finish.
    try:
        txn_id = initialize_response.wait_for_commit()
        if use_ledger and txn_id is None:
            logger.error("Did not receive txn id for the initial commit")
            ErrorShutdown()
    except Exception as e:
        logger.error(str(e))
        ErrorShutdown()

    contract.contract_state.save_to_cache(data_dir=data_dir)

    return contract
 def compute_hash(self):
     serialized = self.__serialize_for_hashing()
     report_hash = crypto.compute_message_hash(serialized)
     # the contract code class expects a string when serializing
     # for hashing, so use Base64 encoding
     return crypto.byte_array_to_base64(report_hash)
 def compute_hash(self):
     return crypto.compute_message_hash(
         crypto.string_to_byte_array(self.serialize_for_hash()))