finished lesson 5
This commit is contained in:
parent
28917ff865
commit
c43218e0e3
@ -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
|
@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Transaction Class
|
||||||
|
|
||||||
|
The goal of this exercise is to learn how to complete transaction class.
|
||||||
|
A transaction is composed of a list of Inputs and a list of outputs, and few methods.
|
||||||
|
add_input() and add_output(), and sign() are already completed in the previous tutorials and exercise.
|
||||||
|
In this hoemwork, we will add another method is_valid() to the class. With this method, we can
|
||||||
|
validate a transaction.
|
||||||
|
|
||||||
|
Your task is to:
|
||||||
|
* locate the TODOs in this file
|
||||||
|
* complete the missing part from the code
|
||||||
|
* run the test of this tutorial located in same folder.
|
||||||
|
|
||||||
|
To test run 'Transactions_t.py' in your command line
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
* do not change class structure or method signature to not break unit tests
|
||||||
|
"""
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
class Tx:
|
||||||
|
inputs = None
|
||||||
|
outputs =None
|
||||||
|
sigs = None
|
||||||
|
reqd = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.inputs = []
|
||||||
|
self.outputs = []
|
||||||
|
self.sigs = []
|
||||||
|
self.reqd = [] # A placeholder for any other extra required signature (e.g. escrow)
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
# TODO 2: Complete the method
|
||||||
|
# We would like to have another method to add extra required signature if needded (e.g. escrow)
|
||||||
|
# with this method, we can specify other required signature to the transaction by adding the
|
||||||
|
# public key of the required signature
|
||||||
|
# If this signature is needed, later we can check if the transaction is also signed by that person/party.
|
||||||
|
def add_reqd(self, addr):
|
||||||
|
self.reqd.append(addr)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO 3: Complete the method
|
||||||
|
# This method is also already done in the previous tutorials.
|
||||||
|
# you can copy and paste the previous codes here
|
||||||
|
def sign(self, private):
|
||||||
|
tx_data = self.__gather()
|
||||||
|
new_sig = sign(tx_data, private)
|
||||||
|
self.sigs.append(new_sig)
|
||||||
|
|
||||||
|
def __gather(self):
|
||||||
|
data = []
|
||||||
|
data.append(self.inputs)
|
||||||
|
data.append(self.outputs)
|
||||||
|
data.append(self.reqd)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
for (addr, amount) in self.inputs:
|
||||||
|
found = False
|
||||||
|
for s in self.sigs:
|
||||||
|
if verify(self.__gather(), s, addr):
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
return False
|
||||||
|
if amount < 0:
|
||||||
|
return False
|
||||||
|
total_in = total_in + amount
|
||||||
|
for (addr, amount) in self.outputs:
|
||||||
|
if amount < 0:
|
||||||
|
return False
|
||||||
|
total_out = total_out + amount
|
||||||
|
|
||||||
|
for sender in self.reqd:
|
||||||
|
found = False
|
||||||
|
for s in self.sigs:
|
||||||
|
if verify(self.__gather(), s, sender):
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
return False
|
||||||
|
if total_out > total_in:
|
||||||
|
return False
|
||||||
|
return True
|
@ -0,0 +1,103 @@
|
|||||||
|
"""
|
||||||
|
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 *
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
alex_prv, alex_pbc = generate_keys()
|
||||||
|
mike_prv, mike_pbc = generate_keys()
|
||||||
|
rose_prv, rose_pbc = generate_keys()
|
||||||
|
mara_prv, mara_pbc = generate_keys()
|
||||||
|
|
||||||
|
# Check Valid Transactions
|
||||||
|
# Test 1
|
||||||
|
# --------------------------------------
|
||||||
|
Tx1 = Tx()
|
||||||
|
Tx1.add_input(alex_pbc, 1)
|
||||||
|
Tx1.add_output(mike_pbc, 1)
|
||||||
|
Tx1.sign(alex_prv)
|
||||||
|
|
||||||
|
# Test 2
|
||||||
|
# --------------------------------------
|
||||||
|
Tx21 = Tx()
|
||||||
|
Tx21.add_input(alex_pbc, 2)
|
||||||
|
Tx21.add_output(mike_pbc, 1)
|
||||||
|
Tx21.add_output(rose_pbc, 1)
|
||||||
|
Tx21.sign(alex_prv)
|
||||||
|
|
||||||
|
Tx22 = Tx()
|
||||||
|
Tx22.add_input(rose_pbc, 1.2)
|
||||||
|
Tx22.add_output(alex_pbc, 1.1)
|
||||||
|
Tx22.add_reqd(mara_pbc)
|
||||||
|
Tx22.sign(rose_prv)
|
||||||
|
Tx22.sign(mara_prv)
|
||||||
|
|
||||||
|
for transaction in [Tx1, Tx21, Tx22]:
|
||||||
|
if transaction.is_valid():
|
||||||
|
print("SUCCESS! Valid transaction is verified.")
|
||||||
|
else:
|
||||||
|
print("ERROR! Valid transaction is not verified.")
|
||||||
|
|
||||||
|
# Check Invalid Transactions
|
||||||
|
# Test 3
|
||||||
|
# --------------------------------------
|
||||||
|
# Wrong signatures
|
||||||
|
Tx3 = Tx()
|
||||||
|
Tx3.add_input(alex_pbc, 1)
|
||||||
|
Tx3.add_output(mike_pbc, 1)
|
||||||
|
Tx3.sign(mike_prv)
|
||||||
|
|
||||||
|
# Test 4
|
||||||
|
# --------------------------------------
|
||||||
|
# Escrow Tx not signed by the arbiter
|
||||||
|
Tx4 = Tx()
|
||||||
|
Tx4.add_input(rose_pbc, 1.2)
|
||||||
|
Tx4.add_output(mike_pbc, 1.1)
|
||||||
|
Tx4.add_reqd(mara_pbc)
|
||||||
|
Tx4.sign(rose_prv)
|
||||||
|
|
||||||
|
# Test 5
|
||||||
|
# --------------------------------------
|
||||||
|
# Two input addrs, signed by one
|
||||||
|
Tx5 = Tx()
|
||||||
|
Tx5.add_input(rose_pbc, 1)
|
||||||
|
Tx5.add_input(mara_pbc, 0.1)
|
||||||
|
Tx5.add_output(mike_pbc, 1.1)
|
||||||
|
Tx5.sign(mara_prv)
|
||||||
|
|
||||||
|
# Test 6
|
||||||
|
# --------------------------------------
|
||||||
|
# Outputs exceed inputs
|
||||||
|
Tx6 = Tx()
|
||||||
|
Tx6.add_input(mara_pbc, 1.2)
|
||||||
|
Tx6.add_output(alex_pbc, 1)
|
||||||
|
Tx6.add_output(alex_pbc, 2)
|
||||||
|
Tx6.sign(mara_prv)
|
||||||
|
|
||||||
|
# Test 7
|
||||||
|
# --------------------------------------
|
||||||
|
# Negative values
|
||||||
|
Tx7 = Tx()
|
||||||
|
Tx7.add_input(mike_pbc, -1)
|
||||||
|
Tx7.add_output(alex_pbc, -1)
|
||||||
|
Tx7.sign(mike_prv)
|
||||||
|
|
||||||
|
# Test 8
|
||||||
|
# --------------------------------------
|
||||||
|
# Modified Tx
|
||||||
|
Tx8 = Tx()
|
||||||
|
Tx8.add_input(mike_pbc, 1)
|
||||||
|
Tx8.add_output(alex_pbc, 1)
|
||||||
|
Tx8.sign(mike_prv)
|
||||||
|
|
||||||
|
# outputs = [(alex_pbc,1)] change to [(rose_pbc,1)]
|
||||||
|
Tx8.outputs[0] = (rose_pbc, 1)
|
||||||
|
|
||||||
|
for transaction in [Tx3, Tx4, Tx5, Tx6, Tx7, Tx8]:
|
||||||
|
if transaction.is_valid():
|
||||||
|
print("ERROR! Invalid transaction is verified.")
|
||||||
|
else:
|
||||||
|
print("SUCCESS! Invalid transaction is not verified.")
|
@ -0,0 +1,9 @@
|
|||||||
|
SUCCESS! Valid transaction is verified.
|
||||||
|
SUCCESS! Valid transaction is verified.
|
||||||
|
SUCCESS! Valid transaction is verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
||||||
|
SUCCESS! Invalid transaction is not verified.
|
Loading…
x
Reference in New Issue
Block a user