From c0a1fbc5864a60395c7a77dca9ab59f79be85e18 Mon Sep 17 00:00:00 2001 From: Spekulaas <“ryan@aterve.nl”> Date: Wed, 27 Sep 2023 09:57:23 +0200 Subject: [PATCH] finished lesson lesson 5.3 --- .../503_T03_A03_Transaction_Sign/Signature.py | 33 +++++++ .../Transaction.py | 31 ++++++ .../Transaction_t.py | 96 +++++++++++++++++++ .../503_T03_A03_Transaction_Sign/output.txt | 20 ++++ 4 files changed, 180 insertions(+) create mode 100644 period_1/05-transaction/503_T03_A03_Transaction_Sign/Signature.py create mode 100644 period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction.py create mode 100644 period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction_t.py create mode 100644 period_1/05-transaction/503_T03_A03_Transaction_Sign/output.txt diff --git a/period_1/05-transaction/503_T03_A03_Transaction_Sign/Signature.py b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Signature.py new file mode 100644 index 0000000..c9803f2 --- /dev/null +++ b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Signature.py @@ -0,0 +1,33 @@ +from cryptography.exceptions import * +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import padding + +def generate_keys(): + private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048) + public_key = private_key.public_key() + return private_key, public_key + +def sign(message, private_key): + signature = private_key.sign( + message, + padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), + hashes.SHA256() + ) + return signature + +def verify(message, signature, public_key): + try: + public_key.verify( + signature, + message, + padding.PSS(mgf=padding.MGF1(hashes.SHA256()), + salt_length=padding.PSS.MAX_LENGTH), + hashes.SHA256() + ) + return True + except InvalidSignature: + return False + except: + print('Error executing public_key.verify') + return False \ No newline at end of file diff --git a/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction.py b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction.py new file mode 100644 index 0000000..03a74af --- /dev/null +++ b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +""" +Transaction Class - Definition of Input and Output + +This is just a copy of the previous tutorial. If you have already completed the previous tutorial, +simply copy and paste the code of transaction class, here. + +Check the test file. It includes signing and verification of transactions +using this new defined transaction class. +""" + +from Signature import * + +class Tx: + + def __init__(self): + self.inputs = [] + self.outputs = [] + + + + + # TODO 2: Complete the method + + def add_input(self, from_addr, amount): + self.inputs.append([from_addr, amount]) + + # TODO 3: Complete the method + + def add_output(self, to_addr, amount): + self.outputs.append([to_addr, amount]) \ No newline at end of file diff --git a/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction_t.py b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction_t.py new file mode 100644 index 0000000..3146cd6 --- /dev/null +++ b/period_1/05-transaction/503_T03_A03_Transaction_Sign/Transaction_t.py @@ -0,0 +1,96 @@ +""" +This test case will verify if the provided exercise solution by a student for the Transaction.py is correct. +""" + +from Signature import * +from Transaction import * + + +def print_transaction(tx_name, tx): + print('---------------') + print(f'-- {tx_name}') + + for (index, input_item) in enumerate(tx.inputs): + for key_name, prv_key, pbc_key in keys_list: + if pbc_key == input_item[0]: + payer = key_name + print(f'In[{index+1}]: {payer} sends {input_item[1]} coin') + + for (index, output_item) in enumerate(tx.outputs): + for key_name, prv_key, pbc_key in keys_list: + if pbc_key == output_item[0]: + receiver = key_name + print(f'Out[{index+1}]: {receiver} receives {output_item[1]} coin') + print() + + +if __name__ == '__main__': + + keys_list =[] + + alex_prv, alex_pbc = generate_keys() + keys_list.append(('alex', alex_prv, alex_pbc)) + + mike_prv, mike_pbc = generate_keys() + keys_list.append(('mike', mike_prv, mike_pbc)) + + rose_prv, rose_pbc = generate_keys() + keys_list.append(('rose', rose_prv, rose_pbc)) + + mara_prv, mara_pbc = generate_keys() + keys_list.append(('mara', mara_prv, mara_pbc)) + + Tx1 = Tx() + Tx1.add_input(alex_pbc, 0.9) + Tx1.add_output(mike_pbc, 0.8) + print_transaction('Tx1', Tx1) + + Tx1_alex_signature = sign(bytes(str(Tx1), 'utf-8'), alex_prv) + verified = verify(bytes(str(Tx1), 'utf-8'), Tx1_alex_signature, alex_pbc) + if verified: + print('Success: Valid signature is verified.') + else: + print('Fail: Valid signature is not verified.') + + # if mike sign it to perform illegal transfer + Tx1_mike_signature = sign(bytes(str(Tx1), 'utf-8'), mike_prv) + verified = verify(bytes(str(Tx1), 'utf-8'), Tx1_mike_signature, alex_pbc) + if verified: + print('Fail: Invalid signature is accepted.') + else: + print('Success: Invalid signature is not verified.') + + + Tx2 = Tx() + Tx2.add_input(alex_pbc, 2.1) + Tx2.add_output(mike_pbc, 0.9) + Tx2.add_output(rose_pbc, 1.0) + Tx2.add_input(mara_pbc, 0.7) + Tx2.add_input(mara_pbc, 1.1) + Tx2.add_input(mara_pbc, 1.5) + Tx2.add_output(mike_pbc, 1.9) + Tx2.add_output(rose_pbc, 0.2) + print_transaction('Tx2', Tx2) + + Tx2_alex_signature = sign(bytes(str(Tx2), 'utf-8'), alex_prv) + Tx2_mara_signature = sign(bytes(str(Tx2), 'utf-8'), mara_prv) + + alex_verified = verify(bytes(str(Tx2), 'utf-8'), Tx2_alex_signature, alex_pbc) + mara_verified = verify(bytes(str(Tx2), 'utf-8'), Tx2_mara_signature, mara_pbc) + + if alex_verified and mara_verified: + print('Success: A valid Transaction is verified.') + else: + print('Fail: A Valid Transaction is not verified.') + + + Tx2_alex_signature = sign(bytes(str(Tx2), 'utf-8'), alex_prv) + Tx2_mike_signature = sign(bytes(str(Tx2), 'utf-8'), mike_prv) + + alex_verified = verify(bytes(str(Tx2), 'utf-8'), Tx2_alex_signature, alex_pbc) + mara_verified = verify(bytes(str(Tx2), 'utf-8'), Tx2_mike_signature, mara_pbc) + + if alex_verified and mara_verified: + print('Fail: An Invalid Transaction is not verified.') + else: + print('Success: An Invalid Transaction is not verified.') \ No newline at end of file diff --git a/period_1/05-transaction/503_T03_A03_Transaction_Sign/output.txt b/period_1/05-transaction/503_T03_A03_Transaction_Sign/output.txt new file mode 100644 index 0000000..df242d1 --- /dev/null +++ b/period_1/05-transaction/503_T03_A03_Transaction_Sign/output.txt @@ -0,0 +1,20 @@ +--------------- +-- Tx1 +In[1]: alex sends 0.9 coin +Out[1]: mike receives 0.8 coin + +Success: Valid signature is verified. +Success: Invalid signature is not verified. +--------------- +-- Tx2 +In[1]: alex sends 2.1 coin +In[2]: mara sends 0.7 coin +In[3]: mara sends 1.1 coin +In[4]: mara sends 1.5 coin +Out[1]: mike receives 0.9 coin +Out[2]: rose receives 1.0 coin +Out[3]: mike receives 1.9 coin +Out[4]: rose receives 0.2 coin + +Success: A valid Transaction is verified. +Success: An Invalid Transaction is not verified. \ No newline at end of file