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
Example #2
0
    def __init__(self, code, name, nonce = None) :
        if nonce is None :
            nonce = crypto.byte_array_to_hex(crypto.random_bit_string(16))

        self.code = code
        self.name = name
        self.nonce = nonce
Example #3
0
    def _GetContractSecret(self, contracttxnid):
        """
        Retrieve or create the secret for a particular contract, returned in
        raw format
        """

        file_secrets = dict()
        with open(self.secrets_file_path, "r") as f:
            for line in f:
                key, val = line.partition(":")[::2]
                file_secrets[key.strip()] = val.strip()

        # If secret already exists, return it, otherwise create, store, and return a new secret
        if contracttxnid in file_secrets:
            secret = file_secrets[contracttxnid]
            logger.debug('Secret for contract %s found', contracttxnid)
        else:
            secret = pcrypto.byte_array_to_hex(pcrypto.SKENC_GenerateKey())
            file_secrets[contracttxnid] = secret
            logger.debug('Creating new Secret for contract %s', contracttxnid)
            with open(self.secrets_file_path, "w") as f:
                for key in file_secrets:
                    f.write(key + ' : ' + file_secrets[key] + "\n")

        return secret
    def sign(self, message, encoding='hex'):
        """
        sign a message from the agent

        :param message: the message for verification, no encoding
        :param encoding: the encoding used for the signature; one of raw, hex, b64
        """

        if type(message) is bytes:
            message_byte_array = message
        elif type(message) is tuple:
            message_byte_array = message
        else:
            message_byte_array = bytes(message, 'ascii')

        signature = self._signing_key.SignMessage(message_byte_array)
        if encoding == 'raw':
            encoded_signature = signature
        elif encoding == 'hex':
            encoded_signature = crypto.byte_array_to_hex(signature)
        elif encoding == 'b64':
            encoded_signature = crypto.byte_array_to_base64(signature)
        else:
            raise ValueError('unknown encoding; {0}'.format(encoding))

        logger.debug("message: %s", message)
        logger.debug("signature: %s", encoded_signature)

        return encoded_signature
    def encrypt(self, message, encoding='raw'):
        """
        encrypt a message to send privately to the enclave

        :param message: text to encrypt
        :param encoding: encoding for the encrypted cipher text, one of raw, hex, b64
        """

        if type(message) is bytes:
            message_byte_array = message
        elif type(message) is tuple:
            message_byte_array = message
        else:
            message_byte_array = bytes(message, 'ascii')

        encrypted_byte_array = self._encryption_key.EncryptMessage(
            message_byte_array)
        if encoding == 'raw':
            encoded_bytes = encrypted_byte_array
        elif encoding == 'hex':
            encoded_bytes = crypto.byte_array_to_hex(encrypted_byte_array)
        elif encoding == 'b64':
            encoded_bytes = crypto.byte_array_to_base64(encrypted_byte_array)
        else:
            raise ValueError('unknown encoding; {0}'.format(encoding))

        logger.debug("message: %s", message)
        logger.debug("encrypted message: %s", encoded_bytes)

        return encoded_bytes
Example #6
0
 def safe_filename(b64name):
     """the base64 encoding we use for contract_id and state_hash make
     them very poor file names; convert to hex for better behavior
     """
     decoded = crypto.base64_to_byte_array(b64name)
     encoded = crypto.byte_array_to_hex(decoded)
     return encoded[16:]
    def __init__(self, request_originator_keys, channel_keys, **kwargs):
        """
        :param request_originator_keys: object of type ServiceKeys
        :param channel_keys: object of type TransactionKeys
        """
        self.__request_originator_keys = request_originator_keys
        self.__channel_keys = channel_keys

        self.expression = kwargs.get('expression', '')
        self.nonce = crypto.byte_array_to_hex(crypto.random_bit_string(16))
Example #8
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))
Example #9
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))
Example #10
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))
Example #11
0
    def register_contract(self, contract_code_hash, provisioning_service_ids,
                          **extra_params):

        tx_method = "register_contract"

        tx_params = PayloadBuilder.build_contract_registration_from_data(
            self.pdo_signer, contract_code_hash, provisioning_service_ids)

        try:
            response = self.ccf_client.submit_rpc(tx_method, tx_params)
            if response.result:  # result will be "True" for contract registration transaction
                return crypto.byte_array_to_hex(tx_params['signature'])
            else:
                raise Exception(response.error)
        except Exception as e:
            raise
Example #12
0
    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))
Example #13
0
    def __init__(self, request_originator_keys, channel_keys, **kwargs):
        """
        :param request_originator_keys: object of type ServiceKeys
        :param channel_keys: object of type TransactionKeys
        """
        self.__request_originator_keys = request_originator_keys
        self.__channel_keys = channel_keys

        # remove this when we are convinced that we've converted
        # all forms to use InvocationRequest
        invocation_request = kwargs.get('invocation_request')
        if invocation_request:
            if not issubclass(type(invocation_request), InvocationRequest):
                logger.warn("not an InvocationRequest: %s",
                            str(invocation_request))

        self.invocation_request = str(kwargs.get('invocation_request', ''))

        # remove this when we are convinced that we've removed
        # all forms expressing the message through 'expression'
        assert kwargs.get('expression') is None

        self.nonce = crypto.byte_array_to_hex(crypto.random_bit_string(16))
    def verify(self, message, encoded_signature, encoding='b64'):
        """
        verify a signature that was created by the enclave

        :param message: the message for verification, no encoding
        :param signature: encoded signature
        :param encoding: the encoding used for the signature; one of raw, hex, b64
        """
        logger.debug("signature for verification: %s", encoded_signature)

        if type(message) is bytes:
            message_byte_array = message
        elif type(message) is tuple:
            message_byte_array = message
        else:
            message_byte_array = bytes(message, 'ascii')

        if encoding == 'raw':
            decoded_signature = encoded_signature
        elif encoding == 'hex':
            decoded_signature = crypto.hex_to_byte_array(encoded_signature)
        elif encoding == 'b64':
            decoded_signature = crypto.base64_to_byte_array(encoded_signature)
        else:
            raise ValueError('unknown encoding; {0}'.format(encoding))

        logger.debug("verifying key: %s", self._verifying_key.Serialize())
        logger.debug("signature for verification: %s",
                     crypto.byte_array_to_hex(decoded_signature))

        result = self._verifying_key.VerifySignature(message_byte_array,
                                                     decoded_signature)
        if result < 0:
            raise Error('malformed signature')

        return result
    logger.error(str(e))
    ErrorShutdown()

try :
    if config.get('StorageService') is None :
        config['StorageService'] = {
            'BlockStore' : os.path.join(config['Contract']['DataDirectory'], 'test-request.mdb'),
        }

except KeyError as ke :
    logger.error('missing configuration for %s', str(ke))
    ErrorShutdown()

contract_creator_keys = keys.ServiceKeys.create_service_keys()
contract_creator_id = contract_creator_keys.identity
contract_id = crypto.byte_array_to_hex(crypto.random_bit_string(256))[:32]

try :
    block_store_file = config['StorageService']['BlockStore']
    block_store = BlockStoreManager(block_store_file, create_block_store=True)
except Exception as e :
    logger.error('failed to initialize the block store; %s', str(e))
    ErrorShutdown()

# -----------------------------------------------------------------
# -----------------------------------------------------------------
plogger.setup_loggers({'LogLevel' : options.loglevel.upper(), 'LogFile' : options.logfile})

# -----------------------------------------------------------------
# -----------------------------------------------------------------
enclave_helper.initialize_enclave(config)
 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
Example #17
0
    def _secretreq(self, minfo):
        # unpack the request
        try:
            enclave_id = minfo['enclave_id']
            contract_id = minfo['contract_id']
            opk = minfo['opk']
            signature = minfo['signature']

        except KeyError as ke:
            raise Error(http.BAD_REQUEST,
                        'missing required field {0}'.format(ke))

        logger.debug('request for key for contract %s, enclave %s',
                     contract_id, enclave_id)

        # verify the signature, that is, make sure that the request was really signed by opk
        try:
            opkkey = pcrypto.SIG_PublicKey(opk)
            opkkey.VerifySignature(
                pcrypto.string_to_byte_array(enclave_id + contract_id),
                pcrypto.hex_to_byte_array(signature))
        except:
            logger.warn("Signature verification failed")
            raise Error(http.BAD_REQUEST, 'Signature Mismatch')

        # Get enclave state
        try:
            logger.debug('retrieve information for enclave %s', enclave_id)
            enclave_info = self.__registry_helper.get_enclave_dict(enclave_id)
            logger.debug("enclave information retrieved: %s", enclave_info)
        except BaseException as err:
            logger.warn(
                'exception occurred when getting ledger information for enclave %s; %s',
                enclave_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve enclave state; {0}'.format(err))
        except ClientConnectException as err:
            logger.warn(
                'client exception occurred when getting ledger information for enclave %s; %s',
                enclave_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve enclave state; {0}'.format(err))

        # Get contract state
        try:
            logger.debug('retrieve information for contract <%s>', contract_id)
            contract_info = self.__registry_helper.get_contract_dict(
                contract_id)
            logger.debug("contract_info from ledger: %s", contract_info)
        except BaseException as err:
            logger.warn(
                'exception occurred when getting ledger information for contract %s; %s',
                contract_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve contract state; {0}'.format(err))
        except ClientConnectException as err:
            logger.warn(
                'client exception occurred when getting ledger information for contract %s; %s',
                contract_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve contract state; {0}'.format(err))

        # make sure that the signer of this request is really the owner of the contract
        try:
            # make sure that the signer of this request is really the owner of the contract
            # PdoContractInfo.pdo_contract_creator_pem_key is the VerifyingKey
            logger.debug("Contract creator's public key: %s",
                         contract_info['pdo_contract_creator_pem_key'])
            logger.debug("Expected public key: %s", opk)
            assert contract_info['pdo_contract_creator_pem_key'] == opk
        except:
            logger.error(
                'request to create secret did not come from the contract owner; %s != %s',
                contracttxn.OriginatorID, opk)
            raise Error(http.NOT_ALLOWED,
                        'operation not allowed for {0}'.format(opk))

        # make sure the provisioning service is allowed to access contract by the checking the list of allowed provisioning services
        try:
            logger.debug("Contract allowed service ids: %s",
                         contract_info['provisioning_service_ids'])
            logger.debug("Expected provisioning service id: %s",
                         self.PSPK.Serialize())
            assert self.PSPK.Serialize(
            ) in contract_info['provisioning_service_ids']
        except:
            logger.error(
                'This Pservice is not the list of allowed provisioning services, PSerivce ID: %s',
                self.PSPK.Serialize())
            raise Error(
                http.NOT_ALLOWED,
                'operation not allowed for {0}'.format(self.PSPK.Serialize()))

        # retrieve the secret
        secret = self._GetContractSecret(contract_id)

        # create the signature
        message = secret + enclave_id + contract_id + opk
        secretsig = pcrypto.byte_array_to_hex(
            self.SigningKey.SignMessage(pcrypto.string_to_byte_array(message)))

        # pad secret to required max size
        # TODO: Eventually this requirement needs to be fixed in the crypto library itself
        required_padding = 2 * pcrypto.MAX_SIG_SIZE - len(secretsig)
        secretsig = secretsig + ('0' * required_padding)

        enclavekey = pcrypto.PKENC_PublicKey(enclave_info['encryption_key'])
        esecret = pcrypto.byte_array_to_base64(
            enclavekey.EncryptMessage(
                pcrypto.string_to_byte_array(secret + secretsig)))

        logger.debug("Encrypted secret for contract %s: %s", contract_id,
                     esecret)

        # create the response
        response = dict()
        response['pspk'] = self.PSPK.Serialize()
        response['encrypted_secret'] = esecret

        logger.info('created secret for contract %s and enclave %s',
                    contract_id, enclave_id)
        return response