def __init__(self, sgx_endpoint, web3, key_name=None, path_to_cert=None): self.sgx_client = SgxClient(sgx_endpoint, path_to_cert=path_to_cert) self._web3 = web3 if key_name is None: self._key_name, self._address, self._public_key = self._generate() else: self._key_name = key_name self._address, self._public_key = self._get_account(key_name)
def generate_sgx_key(sgx_server_url, ssl_port) -> tuple: if not os.path.isdir(SGX_SSL_CERTS_PATH): os.makedirs(SGX_SSL_CERTS_PATH) if ssl_port is not None: client = SgxClient(sgx_server_url, SGX_SSL_CERTS_PATH) else: client = SgxClient(sgx_server_url) return client.generate_key()
def generate_sgx_key(config): if not SGX_SERVER_URL: raise SGXConnecionError('SGX server URL is not provided') if not config.sgx_key_name: sgx = SgxClient(SGX_SERVER_URL, SGX_CERTIFICATES_FOLDER) key_info = sgx.generate_key() logger.info( arguments_list_string( { 'Name': key_info.name, 'Address': key_info.address }, 'Generated new SGX key')) config.sgx_key_name = key_info.name
def sgx_status(): logger.debug(request) sgx = SgxClient(SGX_SERVER_URL, SGX_CERTIFICATES_FOLDER) try: status = sgx.get_server_status() except Exception: # todo: catch specific error - edit sgx.py status = 1 res = { 'status': status, 'status_name': SGXStatus(status).name, 'sgx_server_url': SGX_SERVER_URL } return construct_ok_response(res)
def test_delete(): sgx = SgxClient(os.environ['SERVER'], path_to_cert=os.environ.get('CERT_PATH'), n=2, t=2) random_dkg_id = random.randint(0, 10**50) bls_key_name = ("BLS_KEY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(0)}" ":DKG_ID:" f"{str(random_dkg_id)}") insecure_bls_private_key = "f253bad7b1f62b8ff60bbf451cf2e8e9ebb5d6e9bff450c55b8d5504b8c63d3" response = sgx.import_bls_private_key(bls_key_name, insecure_bls_private_key) assert len(response) > 0 sgx.delete_bls_key(bls_key_name) try: sgx.delete_bls_key(bls_key_name) except SgxServerError as e: assert str(e) == f'BLS key not found: {bls_key_name}' print("TEST DELETE BLS KEY PASSED")
def test_poly_existance(): sgx = SgxClient(os.environ['SERVER'], path_to_cert=os.environ.get('CERT_PATH'), n=2, t=2) random_dkg_id = random.randint(0, 10**50) poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(0)}" ":DKG_ID:" f"{str(random_dkg_id)}") assert sgx.generate_dkg_poly(poly_name) == DkgPolyStatus.NEW_GENERATED assert sgx.is_poly_exists(poly_name) poly_name_incorrect = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(0)}" ":DKG_ID:" f"{str(random_dkg_id+1)}") assert not sgx.is_poly_exists(poly_name_incorrect) response = sgx.generate_dkg_poly(poly_name) assert response == DkgPolyStatus.PREEXISTING print("TEST POLY EXISTANCE PASSED")
class SgxWallet(BaseWallet): def __init__(self, sgx_endpoint, web3, key_name=None, path_to_cert=None): self.sgx_client = SgxClient(sgx_endpoint, path_to_cert=path_to_cert) self._web3 = web3 if key_name is None: self._key_name, self._address, self._public_key = self._generate() else: self._key_name = key_name self._address, self._public_key = self._get_account(key_name) def sign(self, tx_dict): if tx_dict.get('nonce') is None: tx_dict['nonce'] = get_eth_nonce(self._web3, self._address) return self.sgx_client.sign(tx_dict, self.key_name) def sign_and_send(self, tx_dict) -> str: signed_tx = self.sign(tx_dict) return self._web3.eth.sendRawTransaction( signed_tx.rawTransaction).hex() @property def address(self): return self._address @property def public_key(self): return self._public_key @property def key_name(self): return self._key_name def _generate(self): key = self.sgx_client.generate_key() return key.name, key.address, key.public_key def _get_account(self, key_name): account = self.sgx_client.get_account(key_name) return account.address, account.public_key
def test_import(): sgx = SgxClient(os.environ['SERVER'], path_to_cert=os.environ.get('CERT_PATH'), n=2, t=2) random_dkg_id = random.randint(0, 10**50) bls_key_name = ("BLS_KEY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(0)}" ":DKG_ID:" f"{str(random_dkg_id)}") insecure_bls_private_key = "f253bad7b1f62b8ff60bbf451cf2e8e9ebb5d6e9bff450c55b8d5504b8c63d3" response = sgx.import_bls_private_key(bls_key_name, insecure_bls_private_key) assert len(response) > 0 print("TEST IMPORT BLS KEY PASSED")
def __init__(self, node_id_dkg, node_id_contract, skale, t, n, schain_name, public_keys, node_ids_dkg, node_ids_contract, eth_key_name): self.sgx = SgxClient(os.environ['SGX_SERVER_URL'], n=n, t=t, path_to_cert=SGX_CERTIFICATES_FOLDER) self.schain_name = schain_name self.group_index = skale.web3.sha3(text=self.schain_name) self.node_id_contract = node_id_contract self.node_id_dkg = node_id_dkg self.skale = skale self.t = t self.n = n self.eth_key_name = eth_key_name self.incoming_verification_vector = ['0' for _ in range(n)] self.incoming_secret_key_contribution = ['0' for _ in range(n)] self.public_keys = public_keys self.node_ids_dkg = node_ids_dkg self.node_ids_contract = node_ids_contract self.dkg_contract_functions = self.skale.dkg.contract.functions logger.info( f'sChain: {self.schain_name}. Node id on chain is {self.node_id_dkg}; ' f'Node id on contract is {self.node_id_contract}')
from web3 import Web3 from sgx import SgxClient from dotenv import load_dotenv import os load_dotenv() w3 = Web3(Web3.HTTPProvider(os.environ['GETH'])) sgx = SgxClient(os.environ['SERVER'], os.environ.get('CERT_PATH')) txn = { 'to': os.environ['TEST_ACCOUNT'], 'value': 0, 'gas': 2000000, 'gasPrice': 0, 'chainId': w3.eth.chainId } def sign_and_send(): generated_key = sgx.generate_key() key = generated_key.name account = sgx.get_account(key).address txn['nonce'] = w3.eth.getTransactionCount(account) signed_txn = sgx.sign(txn, key) tx = w3.eth.sendRawTransaction(signed_txn.rawTransaction) return w3.toHex(tx) def get_info():
class DKGClient: def __init__(self, node_id_dkg, node_id_contract, skale, t, n, schain_name, public_keys, node_ids_dkg, node_ids_contract, eth_key_name): self.sgx = SgxClient(os.environ['SGX_SERVER_URL'], n=n, t=t, path_to_cert=SGX_CERTIFICATES_FOLDER) self.schain_name = schain_name self.group_index = skale.web3.sha3(text=self.schain_name) self.node_id_contract = node_id_contract self.node_id_dkg = node_id_dkg self.skale = skale self.t = t self.n = n self.eth_key_name = eth_key_name self.incoming_verification_vector = ['0' for _ in range(n)] self.incoming_secret_key_contribution = ['0' for _ in range(n)] self.public_keys = public_keys self.node_ids_dkg = node_ids_dkg self.node_ids_contract = node_ids_contract self.dkg_contract_functions = self.skale.dkg.contract.functions logger.info( f'sChain: {self.schain_name}. Node id on chain is {self.node_id_dkg}; ' f'Node id on contract is {self.node_id_contract}') def is_channel_opened(self): return self.dkg_contract_functions.isChannelOpened( self.group_index).call() def generate_polynomial(self, poly_name): self.poly_name = poly_name return self.sgx.generate_dkg_poly(poly_name) def verification_vector(self): verification_vector = self.sgx.get_verification_vector(self.poly_name) self.incoming_verification_vector[ self.node_id_dkg] = verification_vector verification_vector_hexed = eth_utils.conversions.add_0x_prefix( convert_g2_points_to_hex(verification_vector)) return verification_vector_hexed def secret_key_contribution(self): self.sent_secret_key_contribution = self.sgx.get_secret_key_contribution( self.poly_name, self.public_keys) self.incoming_secret_key_contribution[ self.node_id_dkg] = self.sent_secret_key_contribution[ self.node_id_dkg * 192:(self.node_id_dkg + 1) * 192] return self.sent_secret_key_contribution def broadcast(self, poly_name): poly_success = self.generate_polynomial(poly_name) if not poly_success: raise SgxDkgPolynomGenerationError( f'sChain: {self.schain_name}. Sgx dkg polynom generation failed' ) is_broadcast_possible_function = self.dkg_contract_functions.isBroadcastPossible is_broadcast_possible = is_broadcast_possible_function( self.group_index, self.node_id_contract).call({'from': self.skale.wallet.address}) channel_opened = self.is_channel_opened() if not is_broadcast_possible or not channel_opened: logger.info( f'sChain: {self.schain_name}. ' f'Broadcast is already sent from {self.node_id_dkg} node') return verification_vector = self.verification_vector() secret_key_contribution = self.secret_key_contribution() try: self.skale.dkg.broadcast(self.group_index, self.node_id_contract, verification_vector, secret_key_contribution, wait_for=True, retries=2) except TransactionFailedError as e: logger.error(f'DKG broadcast failed: sChain {self.schain_name}') raise DkgTransactionError(e) logger.info( f'sChain: {self.schain_name}. Everything is sent from {self.node_id_dkg} node' ) def receive_verification_vector(self, from_node, event): input_ = binascii.hexlify(event['args']['verificationVector']).decode() self.incoming_verification_vector[from_node] = input_ def receive_secret_key_contribution(self, from_node, event): input_ = binascii.hexlify( event['args']['secretKeyContribution']).decode() self.incoming_secret_key_contribution[from_node] = input_[ self.node_id_dkg * 192:(self.node_id_dkg + 1) * 192] def verification(self, from_node): return self.sgx.verify_secret_share( self.incoming_verification_vector[from_node], self.eth_key_name, self.incoming_secret_key_contribution[from_node], self.node_id_dkg) def send_complaint(self, to_node): is_complaint_possible_function = self.dkg_contract_functions.isComplaintPossible is_complaint_possible = is_complaint_possible_function( self.group_index, self.node_id_contract, self.node_ids_dkg[to_node]).call( {'from': self.skale.wallet.address}) if not is_complaint_possible or not self.is_channel_opened(): logger.info( f'sChain: {self.schain_name}. ' f'{self.node_id_dkg} node could not sent a complaint on {to_node} node' ) return self.skale.dkg.complaint(self.group_index, self.node_id_contract, self.node_ids_dkg[to_node], wait_for=True) logger.info( f'sChain: {self.schain_name}. ' f'{self.node_id_dkg} node sent a complaint on {to_node} node') def response(self, from_node_index): is_response_possible_function = self.dkg_contract_functions.isResponsePossible is_response_possible = is_response_possible_function( self.group_index, self.node_id_contract).call({'from': self.skale.wallet.address}) if not is_response_possible or not self.is_channel_opened(): logger.info(f'sChain: {self.schain_name}. ' f'{from_node_index} node could not sent a response') return response = self.sgx.complaint_response( self.poly_name, self.node_ids_contract[from_node_index]) share, dh_key = response['share'], response['dh_key'] share = share.split(':') share = convert_g2_point_to_hex(share) try: self.skale.dkg.response(self.group_index, self.node_id_contract, int(dh_key, 16), eth_utils.conversions.add_0x_prefix(share), wait_for=True, retries=2) except TransactionFailedError as e: logger.error(f'DKG response failed: sChain {self.schain_name}') raise DkgTransactionError(e) logger.info( f'sChain: {self.schain_name}. {from_node_index} node sent a response' ) def receive_from_node(self, from_node, event): self.receive_verification_vector(self.node_ids_contract[from_node], event) self.receive_secret_key_contribution(self.node_ids_contract[from_node], event) if not self.verification(self.node_ids_contract[from_node]): raise DkgVerificationError( f"sChain: {self.schain_name}. " f"Fatal error : user {str(self.node_ids_contract[from_node] + 1)} " f"hasn't passed verification by user {str(self.node_id_dkg + 1)}" ) logger.info( f'sChain: {self.schain_name}. ' f'All data from {self.node_ids_contract[from_node]} was received and verified' ) def generate_key(self, bls_key_name): received_secret_key_contribution = "".join( self.incoming_secret_key_contribution[j] for j in range(self.sgx.n)) logger.info( f'sChain: {self.schain_name}. ' f'DKGClient is going to create BLS private key with name {bls_key_name}' ) bls_private_key = self.sgx.create_bls_private_key( self.poly_name, bls_key_name, self.eth_key_name, received_secret_key_contribution) logger.info( f'sChain: {self.schain_name}. ' 'DKGClient is going to fetch BLS public key with name {bls_key_name}' ) self.public_key = self.sgx.get_bls_public_key(bls_key_name) return bls_private_key def alright(self): is_alright_possible_function = self.dkg_contract_functions.isAlrightPossible is_alright_possible = is_alright_possible_function( self.group_index, self.node_id_contract).call({'from': self.skale.wallet.address}) if not is_alright_possible or not self.is_channel_opened(): logger.info( f'sChain: {self.schain_name}. ' f'{self.node_id_dkg} node has already sent an alright note') return try: self.skale.dkg.alright(self.group_index, self.node_id_contract, wait_for=True, retries=2) except TransactionFailedError as e: logger.error(f'DKG alright failed: sChain {self.schain_name}') raise DkgTransactionError(e) logger.info( f'sChain: {self.schain_name}. {self.node_id_dkg} node sent an alright note' )
def perform_dkg(t, n, with_0x=True, with_complaint=False): sgx = SgxClient(os.environ['SERVER'], path_to_cert=os.environ.get('CERT_PATH'), n=n, t=t) public_keys = [] key_name = [] random_dkg_id = random.randint(0, 10**50) for i in range(n): generated_key = sgx.generate_key() if with_0x: public_keys.append(generated_key.public_key) else: public_keys.append(generated_key.public_key[2:]) key_name.append(generated_key.name) sleep(1) for i in range(n): poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(i)}" ":DKG_ID:" f"{str(random_dkg_id)}") response = sgx.generate_dkg_poly(poly_name) if response == DkgPolyStatus.FAIL: raise TypeError("failed generate dkg poly for " + str(i)) sleep(5) verification_vector = [] for i in range(n): poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(i)}" ":DKG_ID:" f"{str(random_dkg_id)}") verification_vector.append(sgx.get_verification_vector(poly_name)) sleep(5) hexed_vv = [] for vv in verification_vector: cur_hexed = "" for elem in vv: cur_hexed += convert_g2_point_to_hex(elem) hexed_vv.append(cur_hexed) secret_key_contribution = [] for i in range(n): poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(i)}" ":DKG_ID:" f"{str(random_dkg_id)}") secret_key_contribution.append( sgx.get_secret_key_contribution(poly_name, public_keys)) sleep(5) if not with_complaint: for i in range(n): for j in range(n): if not sgx.verify_secret_share( hexed_vv[j], key_name[i], secret_key_contribution[j][192 * i:192 * (i + 1)], i): raise ValueError(f'{i} failed to verify {j}') sleep(5) public_keys = sgx.calculate_all_bls_public_keys(hexed_vv) for i in range(n): poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(i)}" ":DKG_ID:" f"{str(random_dkg_id)}") bls_key_name = ("BLS_KEY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(i)}" ":DKG_ID:" f"{str(random_dkg_id)}") sgx.create_bls_private_key( poly_name, bls_key_name, key_name[i], "".join(secret_key_contribution[j][192 * i:192 * (i + 1)] for j in range(n))) public_key = sgx.get_bls_public_key(bls_key_name) assert ":".join(public_key) == public_keys[i] sleep(5) else: corrupted_secret_key_contribution = secret_key_contribution[0] secret_key_contribution[0] = secret_key_contribution[1] for i in range(n): for j in range(n): if j == 0: assert not sgx.verify_secret_share( hexed_vv[j], key_name[i], secret_key_contribution[j][192 * i:192 * (i + 1)], i) else: assert sgx.verify_secret_share( hexed_vv[j], key_name[i], secret_key_contribution[j][192 * i:192 * (i + 1)], i) sleep(5) poly_name = ("POLY:SCHAIN_ID:" f"{str(0)}" ":NODE_ID:" f"{str(0)}" ":DKG_ID:" f"{str(random_dkg_id)}") perform_complaint(sgx, t, poly_name, public_keys[1], corrupted_secret_key_contribution[192:256])
import os from telnetlib import Telnet from dotenv import load_dotenv from eth_account._utils import transactions from hexbytes import HexBytes from web3 import Web3 from sgx import SgxClient load_dotenv() SGX_URL = os.getenv('SERVER') GETH_URL = os.getenv('GETH') sgx = SgxClient(SGX_URL, os.getenv('CERT_PATH')) w3 = Web3(Web3.HTTPProvider(GETH_URL)) txn = { 'to': os.getenv('TEST_ACCOUNT'), 'value': 0, 'gas': 2000000, 'gasPrice': 0, 'chainId': w3.eth.chainId } def test_server_connection(): parsed_url = urllib.parse.urlparse(SGX_URL) with Telnet(parsed_url.hostname, parsed_url.port, timeout=5) as tn: tn.msg('Test')