finished tutorials

This commit is contained in:
Spekulaas
2023-10-03 13:19:51 +02:00
parent c43218e0e3
commit f58053b749
19 changed files with 937 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
class CBlock:
data = None
previousHash = None
previousBlock = None
def __init__(self, data, previousBlock):
self.data = data
self.previousBlock = previousBlock
if previousBlock != None:
self.previousHash = previousBlock.computeHash()
def computeHash(self):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(bytes(str(self.data),'utf8'))
digest.update(bytes(str(self.previousHash),'utf8'))
return digest.finalize()

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction Blockchain): Tutorial 1
The goal of this tutorial is to learn how custom data structures can be de-/serialized
before storage and transference. In addition, you will learn how an application will fail
if serialization is not applied before storing an object in a file.
Any data structure needs to be serialized as a byte stream before storing it
in a file or transferring it through the network. Pickle module supports such an operation.
However, it has limited support for data structures to be serialized automatically.
Custom data structures such as asymmetric keys and transactions are not supported natively.
They need to be serialized before storage. Pickle will throw an exception if it
does not support the data structure. Some third-party modules such as Cryptography provide
such serialization functions. Only some objects are needed for storage or transference
should be serialized. For instance, we might need only to serialize public keys and
leave private keys not serialized. Depending on your implementation scenario,
you might also check JSON serialization functions.
Many serialization formats support multiple different types of asymmetric keys
and will return an instance of the appropriate type. You should check that
the returned key matches the type your application expects when using these methods.
In this scenario we generate a asymmetric keys. Use the private to sign a message.
Your task is to de-/serialize public key of alex before storing to and when loading from a file.
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 'KeyFile_test_a.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/asymmetric/serialization/
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.load_pem_public_key
"""
from Signature import *
from Transaction import *
import pickle
if __name__ == "__main__":
alex_prv, alex_pbc = generate_keys()
sample_message = b'a test message'
sig = sign(sample_message, alex_prv)
print(verify(sample_message, sig, alex_pbc))
savefile = open("key.dat", "wb")
# TODO 1: Serialize the public key to bytes
# Use PEM encoding
pickle.dump(alex_pbc, savefile)
savefile.close()
loadfile = open("key.dat", "rb")
new_pbc = pickle.load(loadfile)
# TODO 2: Deserialize a public key from PEM encoded data
# Load using one of the function that supports asymmetric public key-loading
loadfile.close()
print(verify(sample_message, sig, new_pbc))

View File

@@ -0,0 +1,35 @@
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):
message = bytes(str(message), 'utf-8')
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):
message = bytes(str(message), 'utf-8')
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

View File

@@ -0,0 +1,66 @@
from Signature import *
class Tx:
inputs = None
outputs =None
sigs = None
reqd = None
def __init__(self):
self.inputs = []
self.outputs = []
self.sigs = []
self.reqd = []
def add_input(self, from_addr, amount):
self.inputs.append((from_addr, amount))
def add_output(self, to_addr, amount):
self.outputs.append((to_addr, amount))
def add_reqd(self, addr):
self.reqd.append(addr)
def sign(self, private):
message = self.__gather()
newsig = sign(message, private)
self.sigs.append(newsig)
def is_valid(self):
total_in = 0
total_out = 0
message = self.__gather()
for addr,amount in self.inputs:
found = False
for s in self.sigs:
if verify(message, s, addr):
found = True
if not found:
# print ("No good sig found for " + str(message))
return False
if amount < 0:
return False
total_in = total_in + amount
for addr in self.reqd:
found = False
for s in self.sigs:
if verify(message, s, addr):
found = True
if not found:
return False
for addr,amount in self.outputs:
if amount < 0:
return False
total_out = total_out + amount
if total_out > total_in:
# print("Outputs exceed inputs")
return False
return True
def __gather(self):
data=[]
data.append(self.inputs)
data.append(self.outputs)
data.append(self.reqd)
return data

View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction Blockchain): Tutorial 1
The goal of this tutorial is to learn how custom data structures can be de-/serialized
before storage and transference. In addition, you will learn how an application will fail
if serialization is not applied before storing an object in a file.
Any data structure needs to be serialized as a byte stream before storing it
in a file or transferring it through the network. Pickle module supports such an operation.
However, it has limited support for data structures to be serialized automatically.
Custom data structures such as asymmetric keys and transactions are not supported natively.
They need to be serialized before storage. Pickle will throw an exception if it
does not support the data structure. Some third-party modules such as Cryptography provide
such serialization functions. Only some objects are needed for storage or transference
should be serialized. For instance, we might need only to serialize public keys and
leave private keys not serialized. Depending on your implementation scenario,
you might also check JSON serialization functions.
In this scenario we try to store a custom data structure into a file without serialization.
Pickle will fail to store the byte stream into the file as it does not recognize the object.
Your task is to try different Pickle.dump() calls and check the output.
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 'TxFile_test_a.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/asymmetric/serialization/
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.load_pem_public_key
"""
from Signature import *
from Transaction import *
import pickle
if __name__ == "__main__":
# Generating asymmetric keys for multiple users
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Creating a transaction from alex to mike and signing it with alex private key
Tx1 = Tx()
Tx1.add_input(alex_pbc, 1)
Tx1.add_output(mike_pbc, 1)
Tx1.sign(alex_prv)
# Checking the validity of this transaction
if Tx1.is_valid():
print("Success! Tx is valid")
else:
print("Fail! Tx is invalid")
# Opening a file to store a transaction data
savefile = open("tx.dat", "wb")
# TODO 1: Try different dump() calls by uncommenting it
# Make sure you uncomment other dump calls before trying a new one
# Application should stop here as it fails to serialize our custom data structure (transaction)
pickle.dump(Tx1, savefile)
# pickle.dump(Tx1.inputs[0][0], savefile)
# pickle.dump(alex_pbc, savefile)
savefile.close()
loadfile = open("tx.dat", "rb")
newTx = pickle.load(loadfile)
if newTx.is_valid():
print("Sucess! Loaded tx is valid")
loadfile.close()