From e3e587a74e2638d81e293d539538b10d347a5dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSpekulaas=E2=80=9D?= <“ryan@aterve.nl”> Date: Wed, 20 Sep 2023 16:40:44 +0200 Subject: [PATCH] ex and hw of week 4 --- .../Blockchain.py | 58 +++++++++++++ .../Blockchain_t.py | 58 +++++++++++++ .../405_HW3_Tamper-Proof_Chain/BlockChain.py | 86 +++++++++++++++++++ .../BlockChain_t.py | 73 ++++++++++++++++ .../405_HW3_Tamper-Proof_Chain/output.txt | 43 ++++++++++ 5 files changed, 318 insertions(+) create mode 100644 period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain.py create mode 100644 period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain_t.py create mode 100644 period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain.py create mode 100644 period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain_t.py create mode 100644 period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/output.txt diff --git a/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain.py b/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain.py new file mode 100644 index 0000000..c5e643a --- /dev/null +++ b/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Block Integrity -> Blockchain Data Structure: Exercise 1 + +The goal of this exercise is to learn how a simple blockchain can be created and securely linked +together using cryptography. In general, each block is used to hold a batch of transactions. In addition a cryptographic +hash of the previous block in the chain and some other needed values for computation. +For the simplicity of this exercise each block will hold a string message (data) and hash of the previous block (previousBlock). +The computeHash() method should compute the cryptographic hash of the current block. +Be sure which values must be considered to compute the hash properly. + +Your task is to: + * locate the TODOs in this file + * complete the missing part from the code + * run the test of this exercise located in same folder. + +To test run 'Blockchain_t.py' in your command line + +Notes: + * do not change class structure or method signature to not break unit tests + * visit this url for more information on this topic: + https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/ +""" +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes + +class CBlock: + previousHash = None + previousBlock = None + data = None + + # TODO 1: Initialize a block + # Make sure you initialize the genesis block and transaction blocks differently + + def __init__(self, data, previousBlock): + if previousBlock == None : + self.previousHash = None + self.previousBlock = None + self.data = data + else: + self.previousBlock = previousBlock + self.previousHash = self.previousBlock.computeHash() + self.data = data + pass + + # TODO 2: Compute the hash of a the current block + # Make sure you include all required data + def computeHash(self): + digest = hashes.Hash(hashes.SHA256()) + + if self.previousHash != None: + digest.update(self.previousHash) + + try: + digest.update(str(self.data).encode()) + except: + digest.update(self.data) + + return digest.finalize() diff --git a/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain_t.py b/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain_t.py new file mode 100644 index 0000000..f35578d --- /dev/null +++ b/period_1/04-blockchain_class/404_EX3_A04_Blockchain_Class/Blockchain_t.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +""" +This test case will verify if the provided exercise solution by a student for Blockchain.py is correct. +""" +from Blockchain import * + +class anotherClass: + string = None + num = 1264378 + + def __init__(self, mystring): + self.string = mystring + def __repr__(self): + return self.string + str(self.num) + +if __name__ == '__main__': + + # Instantiate the genesis block + root = CBlock(b'I am root', None) + + # Instantiate another block + B1 = CBlock('I am a child!', root) + + # Check if blocks are correctly linked + if root.computeHash() == B1.previousHash: + print("Success! B1 hash matches") + else: + print("Fail! B1 hash does not match") + if B1.previousBlock.computeHash() == B1.previousHash: + print("Success! B1 hash matches") + else: + print("Fail! B1 hash does not match") + + # Add more blocks to the chain + B2 = CBlock('I am a brother', root) + B3 = CBlock(b'I contiain bytes', B1) + B4 = CBlock(12354, B3) + B5 = CBlock(anotherClass('Hi there!'), B4) + B6 = CBlock("child of B5", B5) + + for b, name in [(B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4'), (B5, 'B5')]: + if b.previousBlock.computeHash() == b.previousHash: + print("Success! "+name+" hash matches") + else: + print("Fail! " +name+" hash does not match") + + #Check if tampered blocks can be detected + B4.data = 12345 + if B5.previousBlock.computeHash() == B5.previousHash: + print("Fail! Couldn't detect a tamper") + else: + print("Success! Tampering is detected") + + B5.data.num = 23678 + if B6.previousBlock.computeHash() == B6.previousHash: + print("Fail! Couldn't detect a tamper") + else: + print("Success! Tampering is detected") \ No newline at end of file diff --git a/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain.py b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain.py new file mode 100644 index 0000000..e2344fc --- /dev/null +++ b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Block Integrity -> Tamper Proof Chain: Homework + +The goal of this homework is to extend the behavior of a block to created a chain and securely link +them together using cryptography. In general, each block is used to hold a batch of transactions. In addition a cryptographic +hash of the previous block in the chain and some other needed values for computation. +In this homework each block will hold: + * a string message (data) + * its own block hash value + * hash value of the previous block + * nonce value which will be incremented when a block is mined + +Your task is to: + * locate the TODOs in this file + * complete the missing part from the code + * run the test of this exercise located in same folder. + +To test run 'Blockchain_t.py' in your command line + +Notes: + * do not change class structure or method signature to not break unit tests + * visit this url for more information on this topic: + https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/ +""" +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes + +class CBlock: + # TODO 1: Initialize the values of a block + # Make sure you distinguish between the genesis block and other blocks + def __init__(self, data, previousBlock): + if previousBlock == None : + self.previousHash = None + self.previousBlock = None + self.data = data + else: + self.previousBlock = previousBlock + self.previousHash = self.previousBlock.computeHash() + self.data = data + self.blockHash = None + self.nonce = 0 + + # TODO 2: Compute the cryptographic hash of the current block. + # Be sure which values must be considered to compute the hash properly. + # return the digest value + def computeHash(self): + digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) + + if self.previousHash != None: + digest.update(self.previousHash) + + try: + digest.update(str(self.data).encode()) + except: + digest.update(self.data) + + digest.update(str(self.nonce).encode()) + return digest.finalize() + + # TODO 3: Mine the current value of a block + # Calculates a digest based on required values from the block, such as: + # data, previousHash, nonce + # Make sure to compute the hash value of the current block and store it properly + def mine(self, leading_zeros): + self.nonce = 0 + while True: + digest = self.computeHash() + + if digest[:leading_zeros] == b'\x00' * leading_zeros: + self.blockHash = digest + print(self.nonce) # Output.txt file has printed nonce values + break + + self.nonce += 1 + + # TODO 4: Check if the current block contains valid hash digest values + # Make sure to distinguish between the genesis block and other blocks + # Make sure to compare both hash digest values: + # The computed digest of the current block + # The stored digest of the previous block + # return the result of all comparisons as a boolean value + def is_valid_hash(self): + if self.previousBlock == None: + return True + + return self.computeHash() == self.blockHash \ No newline at end of file diff --git a/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain_t.py b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain_t.py new file mode 100644 index 0000000..60b1ea8 --- /dev/null +++ b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/BlockChain_t.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +This test case will verify if the provided homework solution by a student for Blockchain.py is correct. +""" +from BlockChain import * + +leading_zero = 2 + +dataG = 'Root' +data1 = 'It is B1' +data2 = 'It is B2' +data3 = 'It is B3' +data4 = 'It is B4' +data5 = 'It is B5' + +if __name__ == '__main__': + + # Instantiate different blocks to be added to the chain + Gn = CBlock(dataG, None) + B1 = CBlock(data1, Gn) + B2 = CBlock(data2, B1) + B3 = CBlock(data3, B2) + B4 = CBlock(data4, B3) + + print('\n--- Blocks are created --- Hashes and Nonces should not match!') + + # Check if hashes and nonces of each block are valid + for b, name in [(B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + if b.is_valid_hash(): + print("Success! "+name+" hash matches") + else: + print("Fail! " +name+" hash does not match") + + # Mine each block + for b, name in [(Gn, 'Gn'), (B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + print(f'\nMining {name} ...') + b.mine(leading_zero) + + print('\n--- Blocks are mined --- Hashes and Nonces must match!') + # Check if hashes and nonces of each block are valid + # Check if block are linked correctly + for b, name in [(B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + if b.is_valid_hash(): + print("Success! "+name+" hash matches") + else: + print("Fail! " +name+" hash does not match") + + # Temper the value of a blok + data3t = 'It is B3t' + B3.data = data3t + + print('\n--- Block3 is tampered --- Hashes and Nonces of blocks after B3 should not match!') + # Check if tempering of block B3 can be detected. + # Hashes and Nonces of its block must not match + for b, name in [(B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + if b.is_valid_hash(): + print("Success! "+name+" hash matches") + else: + print("Fail! " +name+" hash does not match") + + # Mine the blockchain again + for b, name in [(Gn, 'Gn'), (B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + print(f'\nMining {name} ...') + b.mine(leading_zero) + + print('\n--- Blocks are mined again --- Hashes and Nonces must match again!') + # Mine the blockchain again + # Hashes and Nonces must match again + for b, name in [(B1, 'B1'), (B2, 'B2'), (B3, 'B3'), (B4, 'B4')]: + if b.is_valid_hash(): + print("Success! "+name+" hash matches") + else: + print("Fail! " +name+" hash does not match") \ No newline at end of file diff --git a/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/output.txt b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/output.txt new file mode 100644 index 0000000..113d19e --- /dev/null +++ b/period_1/04-blockchain_class/405_HW3_Tamper-Proof_Chain/output.txt @@ -0,0 +1,43 @@ +--- Blocks are created --- Hashes and Nonces should not match! +Fail! B1 hash does not match +Fail! B2 hash does not match +Fail! B3 hash does not match +Fail! B4 hash does not match + +Mining Gn ... +11724 +Mining B1 ... +21751 +Mining B2 ... +83579 +Mining B3 ... +209059 +Mining B4 ... +67743 +--- Blocks are mined --- Hashes and Nonces must match! +Success! B1 hash matches +Success! B2 hash matches +Success! B3 hash matches +Success! B4 hash matches + +--- Block3 is tampered --- Hashes and Nonces of blocks after B3 should not match! +Success! B1 hash matches +Success! B2 hash matches +Fail! B3 hash does not match +Fail! B4 hash does not match + +Mining Gn ... +11724 +Mining B1 ... +21751 +Mining B2 ... +83579 +Mining B3 ... +143719 +Mining B4 ... +67743 +--- Blocks are mined again --- Hashes and Nonces must match again! +Success! B1 hash matches +Success! B2 hash matches +Success! B3 hash matches +Success! B4 hash matches \ No newline at end of file