ex and hw of week 4
This commit is contained in:
parent
7185389683
commit
e3e587a74e
@ -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()
|
@ -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")
|
@ -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
|
@ -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")
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user