def to_dict(self): """Transform the Block to a Python dictionary. Returns: dict: The Block as a dict. Raises: OperationError: If the Block doesn't contain any transactions. """ if len(self.transactions) == 0: raise OperationError('Empty block creation is not allowed') block = { 'timestamp': self.timestamp, 'transactions': [tx.to_dict() for tx in self.transactions], 'node_pubkey': self.node_pubkey, 'voters': self.voters, } block_serialized = serialize(block) block_id = hash_data(block_serialized) return { 'id': block_id, 'block': block, 'signature': self.signature, }
def from_dict(cls, block_body): block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) verifying_key = VerifyingKey(block['node_pubkey']) try: signature = block_body['signature'] except KeyError: signature = None if block_id != block_body['id']: raise InvalidHash() if signature is not None: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 try: signature_valid = verifying_key\ .verify(block_serialized.encode(), signature) except ValueError: signature_valid = False if signature_valid is False: raise InvalidSignature('Invalid block signature') transactions = [ Transaction.from_dict(tx) for tx in block['transactions'] ] return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
def vote(self, block_id, previous_block_id, decision, invalid_reason=None): """Create a signed vote for a block given the :attr:`previous_block_id` and the :attr:`decision` (valid/invalid). Args: block_id (str): The id of the block to vote on. previous_block_id (str): The id of the previous block. decision (bool): Whether the block is valid or invalid. invalid_reason (Optional[str]): Reason the block is invalid """ if block_id == previous_block_id: raise exceptions.CyclicBlockchainError() vote = { 'voting_for_block': block_id, 'previous_block': previous_block_id, 'is_block_valid': decision, 'invalid_reason': invalid_reason, 'timestamp': gen_timestamp() } vote_data = serialize(vote) signature = crypto.SigningKey(self.me_private).sign(vote_data.encode()) vote_signed = { 'node_pubkey': self.me, 'signature': signature, 'vote': vote } return vote_signed
def vote(self, block_id, previous_block_id, decision, invalid_reason=None): """Create a signed vote for a block given the :attr:`previous_block_id` and the :attr:`decision` (valid/invalid). Args: block_id (str): The id of the block to vote on. previous_block_id (str): The id of the previous block. decision (bool): Whether the block is valid or invalid. invalid_reason (Optional[str]): Reason the block is invalid """ if block_id == previous_block_id: raise exceptions.CyclicBlockchainError() vote = { 'voting_for_block': block_id, 'previous_block': previous_block_id, 'is_block_valid': decision, 'invalid_reason': invalid_reason, 'timestamp': gen_timestamp() } vote_data = serialize(vote) signature = crypto.PrivateKey(self.me_private).sign(vote_data.encode()) vote_signed = { 'node_pubkey': self.me, 'signature': signature.decode(), 'vote': vote } return vote_signed
def is_signature_valid(self): block = self.to_dict()['block'] # cc only accepts bytesting messages block_serialized = serialize(block).encode() verifying_key = VerifyingKey(block['node_pubkey']) try: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 return verifying_key.verify(block_serialized, self.signature) except (ValueError, AttributeError): return False
def sign(self, private_key): """Create a signature for the Block and overwrite `self.signature`. Args: private_key (str): A private key corresponding to `self.node_pubkey`. Returns: :class:`~.Block` """ block_body = self.to_dict() block_serialized = serialize(block_body['block']) private_key = PrivateKey(private_key) self.signature = private_key.sign(block_serialized.encode()).decode() return self
def is_signature_valid(self): """Check the validity of a Block's signature. Returns: bool: Stating the validity of the Block's signature. """ block = self.to_dict()['block'] # cc only accepts bytestring messages block_serialized = serialize(block).encode() public_key = PublicKey(block['node_pubkey']) try: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 return public_key.verify(block_serialized, self.signature) except (ValueError, AttributeError): return False
def from_dict(cls, block_body): """Transform a Python dictionary to a Block object. Args: block_body (dict): A block dictionary to be transformed. Returns: :class:`~Block` Raises: InvalidHash: If the block's id is not corresponding to its data. InvalidSignature: If the block's signature is not corresponding to it's data or `node_pubkey`. """ # TODO: Reuse `is_signature_valid` method here. block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) public_key = PublicKey(block['node_pubkey']) try: signature = block_body['signature'] except KeyError: signature = None if block_id != block_body['id']: raise InvalidHash() if signature is not None: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 try: signature_valid = public_key\ .verify(block_serialized.encode(), signature) except ValueError: signature_valid = False if signature_valid is False: raise InvalidSignature('Invalid block signature') transactions = [ Transaction.from_dict(tx) for tx in block['transactions'] ] return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
def tamper_block(): # Cryptographic Identities Generation alice, bob = generate_keypair(), generate_keypair() print(" ") # Digital Asset Definition (e.g. bicycle) asset = Asset(data={ "bicycle": { "manufacturer": "bkfab", "serial_number": "abcd1234" } }) # Metadata Definition metadata = {'planet': 'earth'} # create trnsaction TODO : owners_before might be node_pubkey in v0.8.0 tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset) # sign with private key tx = tx.sign([alice.private_key]) tx_id = tx.to_dict()['id'] print("tx_id : ", tx_id) # create block b = Bigchain() block = b.create_block([tx]) block_id = block.to_dict()['id'] block_voters = block.to_dict()['block']['voters'] print("last_block_id sig : ", block_id, block.signature) print(block.to_dict()) # tamper block sig block.sign(alice.private_key) block_dict = block.to_dict() print("tamper_block_id sig : ", block_dict['id'], block_dict['signature']) print(block_dict) print("db response : ", b.backend.write_block(serialize(block_dict))) sleep(delay) print("tamper_block status : ", b.block_election_status(block_dict['id'], block_voters)) print("blocks_status_containing_tx : ", b.get_blocks_status_containing_tx(tx_id)) print(" ")
def from_dict(cls, block_body): """Transform a Python dictionary to a Block object. Args: block_body (dict): A block dictionary to be transformed. Returns: :class:`~Block` Raises: InvalidHash: If the block's id is not corresponding to its data. InvalidSignature: If the block's signature is not corresponding to it's data or `node_pubkey`. """ # TODO: Reuse `is_signature_valid` method here. block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) public_key = PublicKey(block['node_pubkey']) try: signature = block_body['signature'] except KeyError: signature = None if block_id != block_body['id']: raise InvalidHash() if signature is not None: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 try: signature_valid = public_key\ .verify(block_serialized.encode(), signature) except ValueError: signature_valid = False if signature_valid is False: raise InvalidSignature('Invalid block signature') transactions = [Transaction.from_dict(tx) for tx in block['transactions']] return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
def to_dict(self): if len(self.transactions) == 0: raise OperationError('Empty block creation is not allowed') block = { 'timestamp': self.timestamp, 'transactions': [tx.to_dict() for tx in self.transactions], 'node_pubkey': self.node_pubkey, 'voters': self.voters, } block_serialized = serialize(block) block_id = hash_data(block_serialized) return { 'id': block_id, 'block': block, 'signature': self.signature, }
def verify_vote_signature(voters, signed_vote): """Verify the signature of a vote A valid vote should have been signed by a voter's private key. Args: voters (list): voters of the block that is under election signed_vote (dict): a vote with the `signature` included. Returns: bool: True if the signature is correct, False otherwise. """ signature = signed_vote['signature'] pk_base58 = signed_vote['node_pubkey'] # immediately return False if the voter is not in the block voter list if pk_base58 not in voters: return False public_key = crypto.PublicKey(pk_base58) return public_key.verify(serialize(signed_vote['vote']).encode(), signature)
def verify_vote_signature(voters, signed_vote): """Verify the signature of a vote A valid vote should have been signed by a voter's private key. Args: voters (list): voters of the block that is under election signed_vote (dict): a vote with the `signature` included. Returns: bool: True if the signature is correct, False otherwise. """ signature = signed_vote['signature'] pk_base58 = signed_vote['node_pubkey'] # immediately return False if the voter is not in the block voter list if pk_base58 not in voters: return False public_key = crypto.PublicKey(pk_base58) return public_key.verify( serialize(signed_vote['vote']).encode(), signature)
# print(r.text) # headers = {'Content-Type': 'application/json'} # print(values) # s = rapidjson.dumps(values, skipkeys=False, ensure_ascii=False, sort_keys=True) # print(s) # s = rapidjson.loads('{"id":"56c6a6780abd76bd486d3abe63f2266318bd83be0f913521adbb961944c04f3f","transaction":{"Contract":{"ContractBody":{"Caption":"","Cname":"star","ContractAssets":null,"ContractComponents":null,"ContractId":"","ContractOwners":["qC5zpgJBqUdqi3Gd6ENfGzc5ZM9wrmqmiPX37M9gjq3","J2rSKoCuoZE1MKkXGAvETp757ZuARveRvJYAzJxqEjoo"],"ContractSignatures":null,"ContractState":"","Creator":"","CreatorTime":"","Ctype":"","Description":"","EndTime":"","StartTime":""},"ContractHead":{"MainPubkey":"qC5zpgJBqUdqi3Gd6ENfGzc5ZM9wrmqmiPX37M9gjq3","Version":1},"id":"3ea445410f608e6453cdcb7dbe42d57a89aca018993d7e87da85993cbccc6308"},"Relation":{"ContractId":"834fbab3-9118-45a5-b6d4-31d7baad5e13","TaskId":"","Voters":["qC5zpgJBqUdqi3Gd6ENfGzc5ZM9wrmqmiPX37M9gjq3","J2rSKoCuoZE1MKkXGAvETp757ZuARveRvJYAzJxqEjoo"],"Votes":[{"NodePubkey":"qC5zpgJBqUdqi3Gd6ENfGzc5ZM9wrmqmiPX37M9gjq3","Signature":"65D27HW4uXYvkekGssAQB93D92onMyU1NVnCJnE1PgRKz2uFSPZ6aQvid4qZvkxys7G4r2Mf2KFn5BSQyEBhWs34","Vote":{"InvalidReason":"","IsValid":true,"Timestamp":"1493261777831","VoteFor":"7fb5daf3548c2d0d9b71ce25ee962d164cbb87d82078d7361b8424a95c7c4b94","VoteType":"None"},"id":"320abad9-7134-40e0-9152-176e5d3c10be"},{"NodePubkey":"J2rSKoCuoZE1MKkXGAvETp757ZuARveRvJYAzJxqEjoo","Signature":"5i5dTtQseQjWZ8UdchqQtgttyeeFmB3LDFYzNKafvV2YvTqwv4wZ9mFsH7qgysV9ow893D1h2Xnt1uCXLHtbKrkT","Vote":{"InvalidReason":"","IsValid":true,"Timestamp":"1493261777831","VoteFor":"7fb5daf3548c2d0d9b71ce25ee962d164cbb87d82078d7361b8424a95c7c4b94","VoteType":"None"},"id":"ed116223-f218-4465-a1bc-8c9de6fd51de"}]},"asset":null,"conditions":null,"fulfillments":null,"metadata":{"data":{"a":"1","b":"2","c":"3"},"id":"meta-data-id"},"operation":"OUTPUT","timestamp":"1493261777831"},"version":1}') # print(s) # s = rapidjson.dumps(s, skipkeys=False, ensure_ascii=False, sort_keys=True) # print(s) msg = "hello unichain 2017" pri = "5Pv7F7g9BvNDEMdb8HV5aLHpNTNkxVpNqnLTQ58Z5heC" signing_key = SigningKey(pri) signature = signing_key.sign(serialize(msg).encode()).decode() print(signature) public_key = signing_key.get_verifying_key().encode() print(public_key) detail_serialized = serialize(msg).encode() verifying_key = VerifyingKey("3FyHdZVX4adfSSTg7rZDPMzqzM8k5fkpu43vbRLvEXLJ") s = verifying_key.verify(detail_serialized, signature) print(s) print(serialize(msg).encode()) print(msg.encode()) # a = ["a","b","c"] # len(a)
def to_str(self): return serialize(self.to_dict())
def sign(self, signing_key): block_body = self.to_dict() block_serialized = serialize(block_body['block']) signing_key = SigningKey(signing_key) self.signature = signing_key.sign(block_serialized.encode()).decode() return self
def _to_str(value): return serialize(value)
def validate(self, bigchain): """Validate a transaction. Args: bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. Returns: The transaction (Transaction) if the transaction is valid else it raises an exception describing the reason why the transaction is invalid. Raises: OperationError: if the transaction operation is not supported TransactionDoesNotExist: if the input of the transaction is not found TransactionOwnerError: if the new transaction is using an input it doesn't own DoubleSpend: if the transaction is a double spend InvalidHash: if the hash of the transaction is wrong InvalidSignature: if the signature of the transaction is wrong """ # print(self.operation) if self.operation == Transaction.METADATA: return self if len( self.fulfillments ) == 0 and self.operation != Transaction.CONTRACT and self.operation != Transaction.INTERIM: # print(self.id) print('Transaction contains no fulfillments') raise ValueError('Transaction contains no fulfillments') # print("3") # print("self::",self) if len( self.conditions ) == 0 and self.operation != Transaction.CONTRACT and self.operation != Transaction.INTERIM: print('Transaction contains no conditions') raise ValueError('Transaction contains no conditions') input_conditions = [] inputs_defined = all([ffill.tx_input for ffill in self.fulfillments]) # print("4",inputs_defined) if self.operation in (Transaction.CREATE, Transaction.GENESIS): # print("5") # validate inputs if inputs_defined: raise ValueError('A CREATE operation has no inputs') # validate asset self.asset._validate_asset() elif self.operation in (Transaction.CONTRACT, Transaction.INTERIM): pass elif self.operation == Transaction.TRANSFER: if not inputs_defined: raise ValueError('Only `CREATE` transactions can have null ' 'inputs') # print("6") # check inputs # store the inputs so that we can check if the asset ids match input_txs = [] for ffill in self.fulfillments: input_txid = ffill.tx_input.txid input_cid = ffill.tx_input.cid input_tx, status = bigchain.\ get_transaction(input_txid, include_status=True) if input_tx is None: raise TransactionDoesNotExist( "input `{}` doesn't exist".format(input_txid)) if status != bigchain.TX_VALID: raise FulfillmentNotInValidBlock( 'input `{}` does not exist in a valid block'.format( input_txid)) spent = bigchain.get_spent(input_txid, ffill.tx_input.cid) if spent and spent.id != self.id: raise DoubleSpend( 'input `{}` was already spent'.format(input_txid)) input_conditions.append(input_tx.conditions[input_cid]) input_txs.append(input_tx) # validate asset id asset_id = Asset.get_asset_id(input_txs) if asset_id != self.asset.data_id: raise AssetIdMismatch( 'The asset id of the input does not match the asset id of the transaction' ) else: allowed_operations = ', '.join(Transaction.ALLOWED_OPERATIONS) raise TypeError('`operation`: `{}` must be either {}.'.format( self.operation, allowed_operations)) # print("validate in=2========",self.operation) if self.operation in (Transaction.CONTRACT): # validate contract signature # 1.validate the contract users signture # print("7") ContractBody = deepcopy(self.Contract["ContractBody"]) contract_owners = ContractBody["ContractOwners"] contract_signatures = ContractBody["ContractSignatures"] ContractBody["ContractSignatures"] = None detail_serialized = serialize(ContractBody) if contract_owners != None and contract_signatures != None: if len(contract_owners) < len(contract_signatures): raise MutilContractOwner for index, contract_sign in enumerate(contract_signatures): owner_pubkey = contract_owners[index] signature = contract_sign["Signature"] if not self.is_signature_valid(detail_serialized, owner_pubkey, signature): print("Invalid contract Signature") raise InvalidSignature() return self else: # TODO 2.validate the contract votes? return self # print("validate in=3========",self.operation,"==",self.version) if self.version == 2: # 1.validate the nodes signature voters = self.Relation["Voters"] votes = self.Relation["Votes"] # print("taskid 146 --- ",self.Relation["TaskId"]) # tx_dict = deepcopy(self.to_dict()) # tx_dict["transaction"].pop('Relation') # tx_dict["transaction"].pop('Contract') # detail_serialized = serialize(tx_dict) if len(voters) < len(votes): raise MutilcontractNode for index, vote in enumerate(votes): # print(index) owner_pubkey = voters[index] signature = vote["Signature"] detail_serialized = self.id print(detail_serialized) # print(owner_pubkey) # print(signature) if not self.is_signature_valid(detail_serialized, owner_pubkey, signature): print("Invalid vote Signature") raise InvalidSignature() return self if not self.fulfillments_valid(input_conditions): raise InvalidSignature() else: return self
def sign(self, signing_dict, signing_key): signing_str = serialize(signing_dict) signing_key = SigningKey(signing_key) return signing_key.sign(signing_str.encode()).decode()
if __name__ == "__main__": test_case = ValidateSignatureTest() #gen key paire private_key, public_key = generate_key_pair() #print (SigningKey(private_key).get_verifying_key().encode().decode()) print("\nnode pubkey&prikey is:") print(" public key is:" + str(public_key)) print(" private key is:" + str(private_key)) #sign transation payload = {"payload": "test signature"} print("\npayload is:" + str(payload)) signature = test_case.sign(payload, private_key) print("\nthe signature of payload is:" + str(signature)) #check signature pass print("\n====when payload is valid====") check_public_key = VerifyingKey(public_key) check_res = check_public_key.verify(serialize(payload).encode(), signature) print("check signature result:" + str(check_res)) #check signature not pass payload_new = {"payload": "test signature invalid"} print("\n====when payload is novalid====") print("old payload is:" + str(payload)) print("new payload is:" + str(payload_new)) check_public_key = VerifyingKey(public_key) check_res = check_public_key.verify( serialize(payload_new).encode(), signature) print("check signature result:" + str(check_res))
def encrypt(self, text): # 这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用 cryptor = AES.new(self.key, self.mode, self.key) # 加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数 length = 16 count = len(text) add = length - (count % length) text = text + ('\0' * add) ciphertext = cryptor.encrypt(text) # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题 # 所以这里统一把加密后的字符串转化为16进制字符串 return b2a_hex(ciphertext).decode() def decrypt(self, text): cryptor = AES.new(self.key, self.mode, self.key) plain_text = cryptor.decrypt(a2b_hex(text)).decode() # 解密后,去掉补足的空格用strip() 去掉 return plain_text.rstrip('\0') ac = aescrypt('NoVUykFjRmR1CJ2M') if __name__ == '__main__': config = serialize(bigchaindb.config) # 初始化密钥 e = ac.encrypt(config) print(e) d = ac.decrypt(e) print(d)
import base58 import bigchaindb from bigchaindb.common.util import serialize config = serialize(bigchaindb.config).encode() a = base58.b58encode(config) print(a) b = base58.b58decode(a) print(b.decode())
def get_serialize_data(self, p_dict): return serialize(p_dict)