lessons period 2
This commit is contained in:
parent
c9deff7fda
commit
cb70a03d81
26
period_2/01-sockets/801/client.py
Normal file
26
period_2/01-sockets/801/client.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("localhost")
|
||||||
|
PORT = 5050
|
||||||
|
|
||||||
|
# create a message input
|
||||||
|
message = input("Please enter a message: ")
|
||||||
|
|
||||||
|
# create and bind socket
|
||||||
|
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
socket.connect((HOST, PORT))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# send message
|
||||||
|
socket.sendall(message.encode())
|
||||||
|
|
||||||
|
# socket.recvmsg(1024)
|
||||||
|
|
||||||
|
print("Message sent")
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
21
period_2/01-sockets/801/server.py
Normal file
21
period_2/01-sockets/801/server.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("localhost")
|
||||||
|
PORT = 8080
|
||||||
|
|
||||||
|
# create and bind socket
|
||||||
|
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
socket.bind((HOST, PORT))
|
||||||
|
|
||||||
|
# become a server socket
|
||||||
|
socket.listen(2)
|
||||||
|
|
||||||
|
# accept connections
|
||||||
|
while True:
|
||||||
|
connection, address = socket.accept()
|
||||||
|
print("Connection from", address)
|
||||||
|
data = connection.recv(1024)
|
||||||
|
print("Received: ", data.decode())
|
||||||
|
connection.close()
|
||||||
|
break
|
||||||
|
|
28
period_2/01-sockets/802/client.py
Normal file
28
period_2/01-sockets/802/client.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("145.137.113.215")
|
||||||
|
PORT = 5055
|
||||||
|
|
||||||
|
# create a message input
|
||||||
|
message = "1001519"
|
||||||
|
|
||||||
|
# create and bind socket
|
||||||
|
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
socket.connect((HOST, PORT))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# send message
|
||||||
|
socket.sendall(bytes(message, "utf-8"))
|
||||||
|
data = socket.recv(1024)
|
||||||
|
|
||||||
|
# socket.recvmsg(1024)
|
||||||
|
|
||||||
|
print("Message sent")
|
||||||
|
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
31
period_2/01-sockets/803/client.py
Normal file
31
period_2/01-sockets/803/client.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("localhost")
|
||||||
|
PORT = 5052
|
||||||
|
|
||||||
|
def send(msg):
|
||||||
|
|
||||||
|
|
||||||
|
# create a message input
|
||||||
|
message = msg.encode("utf-8")
|
||||||
|
|
||||||
|
# create and bind socket
|
||||||
|
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
socket.connect((HOST, PORT))
|
||||||
|
|
||||||
|
# send message
|
||||||
|
socket.send(b'-' * (64 - len(str(len(message)).encode("utf-8"))))
|
||||||
|
socket.send(message)
|
||||||
|
|
||||||
|
socket.recv(1024)
|
||||||
|
|
||||||
|
print("Message sent")
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
message = input("Please enter a message: ")
|
||||||
|
|
||||||
|
if message == "":
|
||||||
|
send("!DISCONNECT")
|
||||||
|
|
||||||
|
else:
|
||||||
|
send(message)
|
34
period_2/01-sockets/803/server.py
Normal file
34
period_2/01-sockets/803/server.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import socket
|
||||||
|
# Get local machine name
|
||||||
|
HOST = socket.gethostname("localhost")
|
||||||
|
PORT = 5050
|
||||||
|
|
||||||
|
def handleClient(clientsocket):
|
||||||
|
while True:
|
||||||
|
# Receive no more than 1024 bytes
|
||||||
|
msg = clientsocket.recv(1024)
|
||||||
|
if not msg:
|
||||||
|
break
|
||||||
|
clientsocket.send(msg)
|
||||||
|
clientsocket.close()
|
||||||
|
|
||||||
|
def start():
|
||||||
|
# Create a socket object
|
||||||
|
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
|
||||||
|
# Bind to the port
|
||||||
|
serversocket.bind((HOST, PORT))
|
||||||
|
|
||||||
|
# Queue up to 5 requests
|
||||||
|
serversocket.listen(5)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# Establish a connection
|
||||||
|
clientsocket, addr = serversocket.accept()
|
||||||
|
|
||||||
|
print("Got a connection from %s" % str(addr))
|
||||||
|
|
||||||
|
msg = 'Thank you for connecting' + "\r\n"
|
||||||
|
clientsocket.send(msg.encode('ascii'))
|
||||||
|
clientsocket.close()
|
30
period_2/01-sockets/804/client.py
Normal file
30
period_2/01-sockets/804/client.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("localhost")
|
||||||
|
PORT = 5053
|
||||||
|
ADDR = (HOST, PORT)
|
||||||
|
HEADER = 64
|
||||||
|
FORMAT = "utf-8"
|
||||||
|
|
||||||
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server.connect(ADDR)
|
||||||
|
|
||||||
|
def send(message):
|
||||||
|
message = message.encode(FORMAT)
|
||||||
|
msg_length = len(message)
|
||||||
|
send_length = str(msg_length).encode(FORMAT)
|
||||||
|
send_length += b' ' * (HEADER - len(send_length))
|
||||||
|
server.send(send_length)
|
||||||
|
server.send(message)
|
||||||
|
print(server.recv(2048).decode(FORMAT))
|
||||||
|
|
||||||
|
def handleSend():
|
||||||
|
connected = True
|
||||||
|
while connected:
|
||||||
|
message = input("Please enter a message: ")
|
||||||
|
if message == "!DISCONNECT":
|
||||||
|
connected = False
|
||||||
|
else:
|
||||||
|
send(message)
|
||||||
|
|
||||||
|
handleSend()
|
44
period_2/01-sockets/804/server.py
Normal file
44
period_2/01-sockets/804/server.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
|
||||||
|
HOST = socket.gethostbyname("localhost")
|
||||||
|
PORT = 5053
|
||||||
|
ADDR = (HOST, PORT)
|
||||||
|
HEADER = 64
|
||||||
|
FORMAT = "utf-8"
|
||||||
|
|
||||||
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server.bind(ADDR)
|
||||||
|
|
||||||
|
def handleClient(conn, addr):
|
||||||
|
client_name = conn.recv(HEADER).decode(FORMAT)
|
||||||
|
print(f"[NEW CONNECTION] {client_name} connected.")
|
||||||
|
connected = True
|
||||||
|
while connected:
|
||||||
|
msg_length = conn.recv(HEADER).decode(FORMAT)
|
||||||
|
if msg_length:
|
||||||
|
msg_length = int(len(msg_length))
|
||||||
|
msg = conn.recv(msg_length).decode(FORMAT)
|
||||||
|
if msg == "!DISCONNECT":
|
||||||
|
connected = False
|
||||||
|
print(f"[{client_name}] {msg}")
|
||||||
|
conn.send("Msg received".encode(FORMAT))
|
||||||
|
|
||||||
|
conn.send("Bye bye".encode(FORMAT))
|
||||||
|
conn.close()
|
||||||
|
print(f"[DISCONNECTED] {client_name} disconnected.")
|
||||||
|
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 2}]")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
server.listen()
|
||||||
|
print(f"[LISTENING] Server is listening on {HOST}")
|
||||||
|
while True:
|
||||||
|
conn, addr = server.accept()
|
||||||
|
thread = threading.Thread(target=handleClient, args=(conn, addr))
|
||||||
|
thread.start()
|
||||||
|
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
|
||||||
|
|
||||||
|
print("[STARTING] server is starting...")
|
||||||
|
start()
|
@ -0,0 +1,25 @@
|
|||||||
|
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.blockHash = None
|
||||||
|
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()
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if self.previousBlock == None:
|
||||||
|
return True
|
||||||
|
return self.previousBlock.computeHash() == self.previousHash
|
@ -0,0 +1,41 @@
|
|||||||
|
from cryptography.exceptions import *
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
|
from cryptography.hazmat.primitives import serialization
|
||||||
|
|
||||||
|
def generate_keys():
|
||||||
|
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
|
||||||
|
pbc_ser = public_key.public_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PublicFormat.SubjectPublicKeyInfo)
|
||||||
|
return private_key, pbc_ser
|
||||||
|
|
||||||
|
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, pbc_ser):
|
||||||
|
message = bytes(str(message), 'utf-8')
|
||||||
|
public_key = serialization.load_pem_public_key(pbc_ser)
|
||||||
|
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,100 @@
|
|||||||
|
from gzip import READ
|
||||||
|
from operator import truediv
|
||||||
|
from optparse import AmbiguousOptionError
|
||||||
|
|
||||||
|
REWARD_VALUE = 25.0
|
||||||
|
NORMAL = 0
|
||||||
|
REWARD = 1
|
||||||
|
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
class Tx:
|
||||||
|
def __init__(self, type = NORMAL):
|
||||||
|
|
||||||
|
self.type = type
|
||||||
|
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):
|
||||||
|
|
||||||
|
if self.type == REWARD:
|
||||||
|
if len(self.inputs)!=0 and len(self.outputs)!=1:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
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
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
repr_str = "INPUTS:\n"
|
||||||
|
for addr, amt in self.inputs:
|
||||||
|
repr_str = repr_str + str(amt) + "from" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "OUTPUTS:\n"
|
||||||
|
for addr, amt in self.outputs:
|
||||||
|
repr_str = repr_str + str(amt) + "to" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "EXTRA REQUIRED SIGNATURES:\n"
|
||||||
|
for req_sig in self.reqd:
|
||||||
|
repr_str = repr_str + str(req_sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "SIGNATURES:\n"
|
||||||
|
for sig in self.sigs:
|
||||||
|
repr_str = repr_str + str(sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "END\n"
|
||||||
|
|
||||||
|
return repr_str
|
@ -0,0 +1,63 @@
|
|||||||
|
from BlockChain import CBlock
|
||||||
|
from Signature import generate_keys, sign, verify
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
REWARD_VALUE = 25.0
|
||||||
|
leading_zeros = 2
|
||||||
|
next_char_limit = 20
|
||||||
|
|
||||||
|
class TxBlock (CBlock):
|
||||||
|
|
||||||
|
def __init__(self, previousBlock):
|
||||||
|
self.nonce = "A random nonce"
|
||||||
|
super(TxBlock, self).__init__([], previousBlock)
|
||||||
|
|
||||||
|
def addTx(self, Tx_in):
|
||||||
|
self.data.append(Tx_in)
|
||||||
|
|
||||||
|
def __count_totals(self):
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
for tx in self.data:
|
||||||
|
for addr, amt in tx.inputs:
|
||||||
|
total_in = total_in + amt
|
||||||
|
for addr, amt in tx.outputs:
|
||||||
|
total_out = total_out + amt
|
||||||
|
return total_in, total_out
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if not super(TxBlock, self).is_valid():
|
||||||
|
return False
|
||||||
|
for tx in self.data:
|
||||||
|
if not tx.is_valid():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.nonce != "A random nonce":
|
||||||
|
if not self.good_nonce():
|
||||||
|
return False
|
||||||
|
|
||||||
|
total_in, total_out = self.__count_totals()
|
||||||
|
|
||||||
|
Tx_Balance = round(total_out - total_in, 10)
|
||||||
|
|
||||||
|
if Tx_Balance > REWARD_VALUE:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def good_nonce(self):
|
||||||
|
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||||
|
digest.update(bytes(str(self.data), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.previousHash), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.nonce), 'utf8'))
|
||||||
|
this_hash = digest.finalize()
|
||||||
|
return this_hash[:leading_zeros] == b'\x00'*leading_zeros
|
||||||
|
|
||||||
|
def find_nonce(self):
|
||||||
|
for i in range(10000000):
|
||||||
|
self.nonce = i
|
||||||
|
if self.good_nonce():
|
||||||
|
return self.nonce
|
||||||
|
return None
|
@ -0,0 +1,11 @@
|
|||||||
|
import pickle
|
||||||
|
import socket
|
||||||
|
|
||||||
|
PORT = 5005
|
||||||
|
|
||||||
|
def sendObj(ip_address, obj):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.connect((ip_address, PORT))
|
||||||
|
sock.send(pickle.dumps(obj))
|
||||||
|
sock.close()
|
||||||
|
return False
|
@ -0,0 +1,36 @@
|
|||||||
|
from TxBlock import *
|
||||||
|
from Transaction import *
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
from client import *
|
||||||
|
|
||||||
|
SERVER = 'localhost'
|
||||||
|
TCP_PORT = 5050
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
Tx1 = Tx()
|
||||||
|
Tx1.add_input(alex_pbc, 2.3)
|
||||||
|
Tx1.add_output(mike_pbc, 1.0)
|
||||||
|
Tx1.add_output(rose_pbc, 1.1)
|
||||||
|
Tx1.sign(alex_prv)
|
||||||
|
|
||||||
|
Tx2 = Tx()
|
||||||
|
Tx2.add_input(rose_pbc, 2.3)
|
||||||
|
Tx2.add_input(mike_pbc, 1.0)
|
||||||
|
Tx2.add_output(alex_pbc, 3.1)
|
||||||
|
Tx2.sign(mike_prv)
|
||||||
|
Tx2.sign(rose_prv)
|
||||||
|
|
||||||
|
B1 = TxBlock(None)
|
||||||
|
B1.addTx(Tx1)
|
||||||
|
B1.addTx(Tx2)
|
||||||
|
|
||||||
|
sendObj(SERVER, B1)
|
||||||
|
|
||||||
|
sendObj(SERVER, Tx2)
|
@ -0,0 +1,21 @@
|
|||||||
|
import socket
|
||||||
|
import pickle
|
||||||
|
import TxBlock
|
||||||
|
|
||||||
|
PORT = 5050
|
||||||
|
|
||||||
|
def newConnection(ip_address):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.bind((ip_address, PORT))
|
||||||
|
sock.listen(2)
|
||||||
|
return sock
|
||||||
|
|
||||||
|
def recvObj(socket):
|
||||||
|
new_sock, address = socket.accept()
|
||||||
|
data = new_sock.recv(1024)
|
||||||
|
print("Received: ", data)
|
||||||
|
data = pickle.loads(data)
|
||||||
|
new_sock.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
import TxBlock
|
||||||
|
import socket
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
from server import *
|
||||||
|
|
||||||
|
SERVER = 'localhost'
|
||||||
|
TCP_PORT = 5050
|
||||||
|
# BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
server = newConnection(SERVER)
|
||||||
|
|
||||||
|
newB = recvObj(server)
|
||||||
|
# print(newB.data[0])
|
||||||
|
# print(newB.data[1])
|
||||||
|
|
||||||
|
if (newB.is_valid()):
|
||||||
|
print("Success! Transaction is valid.")
|
||||||
|
else:
|
||||||
|
print("Error! Transaction invalid.")
|
||||||
|
|
||||||
|
if newB.data[0].inputs[0][1] == 2.3:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[0].outputs[1][1] == 1.1:
|
||||||
|
print("Success! Output value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong output value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].inputs[0][1] == 2.3:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].inputs[1][1] == 1.0:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].outputs[0][1] == 3.1:
|
||||||
|
print("Success! Output value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong output value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
newTx = recvObj(server)
|
||||||
|
# print(newTx)
|
@ -0,0 +1,36 @@
|
|||||||
|
from TxBlock import *
|
||||||
|
from Transaction import *
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
from client import *
|
||||||
|
|
||||||
|
SERVER = 'localhost'
|
||||||
|
TCP_PORT = 5005
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
Tx1 = Tx()
|
||||||
|
Tx1.add_input(alex_pbc, 2.3)
|
||||||
|
Tx1.add_output(mike_pbc, 1.0)
|
||||||
|
Tx1.add_output(rose_pbc, 1.1)
|
||||||
|
Tx1.sign(alex_prv)
|
||||||
|
|
||||||
|
Tx2 = Tx()
|
||||||
|
Tx2.add_input(rose_pbc, 2.3)
|
||||||
|
Tx2.add_input(mike_pbc, 1.0)
|
||||||
|
Tx2.add_output(alex_pbc, 3.1)
|
||||||
|
Tx2.sign(mike_prv)
|
||||||
|
Tx2.sign(rose_prv)
|
||||||
|
|
||||||
|
B1 = TxBlock.TxBlock(None)
|
||||||
|
B1.addTx(Tx1)
|
||||||
|
B1.addTx(Tx2)
|
||||||
|
|
||||||
|
sendObj(SERVER, B1)
|
||||||
|
|
||||||
|
sendObj(SERVER, Tx2)
|
@ -0,0 +1,57 @@
|
|||||||
|
import TxBlock
|
||||||
|
import socket
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
from server import *
|
||||||
|
|
||||||
|
|
||||||
|
local_hostname = socket.gethostname()
|
||||||
|
# local_ip = socket.gethostbyname(local_hostname)
|
||||||
|
local_ip = '192.168.1.103'
|
||||||
|
|
||||||
|
|
||||||
|
TCP_PORT = 5005
|
||||||
|
BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
server = newConnection(local_ip)
|
||||||
|
print(f"[LISTENING] Server is listening on {local_ip}")
|
||||||
|
|
||||||
|
|
||||||
|
newB = recvObj(server)
|
||||||
|
# print(newB.data[0])
|
||||||
|
# print(newB.data[1])
|
||||||
|
|
||||||
|
if (newB.is_valid()):
|
||||||
|
print("Success! Transaction is valid.")
|
||||||
|
else:
|
||||||
|
print("Error! Transaction invalid.")
|
||||||
|
|
||||||
|
if newB.data[0].inputs[0][1] == 2.3:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[0].outputs[1][1] == 1.1:
|
||||||
|
print("Success! Output value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong output value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].inputs[0][1] == 2.3:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].inputs[1][1] == 1.0:
|
||||||
|
print("Success! Input value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong input value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
if newB.data[1].outputs[0][1] == 3.1:
|
||||||
|
print("Success! Output value matches.")
|
||||||
|
else:
|
||||||
|
print("Error! Wrong output value for block 1, transaction 1.")
|
||||||
|
|
||||||
|
newTx = recvObj(server)
|
||||||
|
# print(newTx)
|
@ -0,0 +1,52 @@
|
|||||||
|
import socket
|
||||||
|
from threading import Timer
|
||||||
|
|
||||||
|
HEADER = 64
|
||||||
|
PORT = 5053
|
||||||
|
FORMAT = 'utf-8'
|
||||||
|
DISCONNECT_MESSAGE = "!DISCONNECT"
|
||||||
|
HOST_IP = 'localhost'
|
||||||
|
|
||||||
|
ADDR = (HOST_IP, PORT)
|
||||||
|
|
||||||
|
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
client.connect(ADDR)
|
||||||
|
client_name = input('please enter your name: ')
|
||||||
|
client.send(client_name.encode(FORMAT))
|
||||||
|
print(client.recv(2048).decode(FORMAT))
|
||||||
|
|
||||||
|
def send(msg):
|
||||||
|
message = msg.encode(FORMAT)
|
||||||
|
msg_length = len(message)
|
||||||
|
send_length = str(msg_length).encode(FORMAT)
|
||||||
|
send_length += b' ' * (HEADER - len(send_length))
|
||||||
|
client.send(send_length)
|
||||||
|
client.send(message)
|
||||||
|
print(client.recv(2048).decode(FORMAT))
|
||||||
|
|
||||||
|
def stop_the_client():
|
||||||
|
global cont_flag
|
||||||
|
mes = DISCONNECT_MESSAGE
|
||||||
|
send(mes)
|
||||||
|
cont_flag = False
|
||||||
|
|
||||||
|
cont_flag = True
|
||||||
|
while cont_flag:
|
||||||
|
timeout = 20
|
||||||
|
timeout_thread = Timer(timeout, send, args=(DISCONNECT_MESSAGE,))
|
||||||
|
timeout_thread.start()
|
||||||
|
|
||||||
|
if not cont_flag:
|
||||||
|
print("the connection is closed by the server")
|
||||||
|
break
|
||||||
|
print('--------------------------')
|
||||||
|
print('You can send a message to server')
|
||||||
|
print('to stop connection, press enter on a blank message')
|
||||||
|
mes = input('Your message: ')
|
||||||
|
if mes:
|
||||||
|
send(mes)
|
||||||
|
else:
|
||||||
|
send(DISCONNECT_MESSAGE)
|
||||||
|
cont_flag = False
|
||||||
|
|
||||||
|
timeout_thread.cancel()
|
@ -0,0 +1,65 @@
|
|||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
import select
|
||||||
|
|
||||||
|
HEADER = 64
|
||||||
|
PORT = 5053
|
||||||
|
local_ip = socket.gethostbyname('localhost')
|
||||||
|
ADDR = (local_ip, PORT)
|
||||||
|
FORMAT = 'utf-8'
|
||||||
|
DISCONNECT_MESSAGE = "!DISCONNECT"
|
||||||
|
|
||||||
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server.bind(ADDR)
|
||||||
|
|
||||||
|
def handle_client(conn, addr):
|
||||||
|
client_name = conn.recv(2048).decode(FORMAT)
|
||||||
|
|
||||||
|
print(f"\n[NEW CONNECTION] {client_name}@{addr} is connected.")
|
||||||
|
connection_message = f"...\nHi {client_name}! \nYou are successfully connected to the server {ADDR}"
|
||||||
|
conn.send(connection_message.encode(FORMAT))
|
||||||
|
connected = True
|
||||||
|
while connected:
|
||||||
|
ready_to_read, ready_to_write, in_error = select.select([conn], [], [conn], 20)
|
||||||
|
print(f"ready_to_read: {ready_to_read}")
|
||||||
|
if len(ready_to_read):
|
||||||
|
print(f"ready_to_read: {ready_to_read}")
|
||||||
|
msg_length = conn.recv(HEADER).decode(FORMAT)
|
||||||
|
print(f"msg_length: {msg_length}")
|
||||||
|
if msg_length:
|
||||||
|
|
||||||
|
msg_length = int(msg_length)
|
||||||
|
msg = conn.recv(msg_length).decode(FORMAT)
|
||||||
|
if msg == DISCONNECT_MESSAGE:
|
||||||
|
connected = False
|
||||||
|
|
||||||
|
print(f"[{client_name}@{addr}]>> {msg}")
|
||||||
|
return_message = f'Server received your message: "{msg}"'
|
||||||
|
conn.send(return_message.encode(FORMAT))
|
||||||
|
else:
|
||||||
|
connected = False
|
||||||
|
return_message = f"\nTimeout! {client_name} is disconnected from the server {ADDR}"
|
||||||
|
conn.send(return_message.encode(FORMAT))
|
||||||
|
|
||||||
|
bye_message = f"\nBye {client_name}!"
|
||||||
|
conn.send(bye_message.encode(FORMAT))
|
||||||
|
conn.close()
|
||||||
|
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}")
|
||||||
|
|
||||||
|
# bye_message = f"\nBye {client_name}!"
|
||||||
|
# conn.send(bye_message.encode(FORMAT))
|
||||||
|
conn.close()
|
||||||
|
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}")
|
||||||
|
|
||||||
|
def start():
|
||||||
|
server.listen()
|
||||||
|
print(f"[LISTENING] Server is listening on {local_ip}")
|
||||||
|
while True:
|
||||||
|
conn, addr = server.accept()
|
||||||
|
thread = threading.Thread(target=handle_client, args=(conn, addr))
|
||||||
|
thread.start()
|
||||||
|
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
|
||||||
|
|
||||||
|
|
||||||
|
print("[STARTING] server is starting...")
|
||||||
|
start()
|
24
period_2/02-sockets/902/BlockChain.py
Normal file
24
period_2/02-sockets/902/BlockChain.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if self.previousBlock == None:
|
||||||
|
return True
|
||||||
|
return self.previousBlock.computeHash() == self.previousHash
|
65
period_2/02-sockets/902/Client_test.py
Normal file
65
period_2/02-sockets/902/Client_test.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
from TxBlock import *
|
||||||
|
from Transaction import *
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
from SocketUtil import *
|
||||||
|
|
||||||
|
SERVER = 'localhost'
|
||||||
|
TCP_PORT = 5050
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
Tx1 = Tx()
|
||||||
|
Tx1.add_input(alex_pbc, 2.3)
|
||||||
|
Tx1.add_output(mike_pbc, 1.0)
|
||||||
|
Tx1.add_output(rose_pbc, 1.1)
|
||||||
|
Tx1.sign(alex_prv)
|
||||||
|
|
||||||
|
Tx2 = Tx()
|
||||||
|
Tx2.add_input(rose_pbc, 2.3)
|
||||||
|
Tx2.add_input(mike_pbc, 1.0)
|
||||||
|
Tx2.add_output(alex_pbc, 3.1)
|
||||||
|
Tx2.sign(mike_prv)
|
||||||
|
Tx2.sign(rose_prv)
|
||||||
|
|
||||||
|
B1 = TxBlock(None)
|
||||||
|
B1.addTx(Tx1)
|
||||||
|
B1.addTx(Tx2)
|
||||||
|
|
||||||
|
server = newServerSocket(SERVER)
|
||||||
|
|
||||||
|
print('A connection to the server is established.')
|
||||||
|
|
||||||
|
# -------------------------------------
|
||||||
|
sendObj(SERVER, Tx2)
|
||||||
|
print('Server is in Receiving mode ...')
|
||||||
|
Obj = recvObj(server)
|
||||||
|
if Obj:
|
||||||
|
print('Data: ', type(Obj),'\n')
|
||||||
|
else:
|
||||||
|
print('No object received')
|
||||||
|
|
||||||
|
# -------------------------------------
|
||||||
|
sendObj(SERVER, B1)
|
||||||
|
print('Server is in Receiving mode ...')
|
||||||
|
Obj = recvObj(server)
|
||||||
|
if Obj:
|
||||||
|
print('Data: ', type(Obj),'\n')
|
||||||
|
else:
|
||||||
|
print('No object received')
|
||||||
|
|
||||||
|
# -------------------------------------
|
||||||
|
print('Server is in Receiving mode ...')
|
||||||
|
Obj = recvObj(server)
|
||||||
|
if Obj:
|
||||||
|
print(Obj)
|
||||||
|
else:
|
||||||
|
print('No object received')
|
||||||
|
|
||||||
|
print("Success! The connection is released.") # If returns after time, then successful
|
||||||
|
server.close()
|
41
period_2/02-sockets/902/Signature.py
Normal file
41
period_2/02-sockets/902/Signature.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from cryptography.exceptions import *
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
|
from cryptography.hazmat.primitives import serialization
|
||||||
|
|
||||||
|
def generate_keys():
|
||||||
|
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
|
||||||
|
pbc_ser = public_key.public_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PublicFormat.SubjectPublicKeyInfo)
|
||||||
|
return private_key, pbc_ser
|
||||||
|
|
||||||
|
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, pbc_ser):
|
||||||
|
message = bytes(str(message), 'utf-8')
|
||||||
|
public_key = serialization.load_pem_public_key(pbc_ser)
|
||||||
|
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
|
38
period_2/02-sockets/902/SocketUtil.py
Normal file
38
period_2/02-sockets/902/SocketUtil.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import socket
|
||||||
|
import pickle
|
||||||
|
import select
|
||||||
|
|
||||||
|
TCP_PORT = 5050
|
||||||
|
BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
|
||||||
|
def newServerSocket(ip_addr):
|
||||||
|
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server_socket.bind((ip_addr, TCP_PORT))
|
||||||
|
server_socket.listen()
|
||||||
|
return server_socket
|
||||||
|
|
||||||
|
|
||||||
|
def recvObj(socket):
|
||||||
|
ready_to_read, ready_to_write, in_error = select.select([socket], [], [socket], 20)
|
||||||
|
if socket in ready_to_read:
|
||||||
|
print('Server is ready to receive data ...')
|
||||||
|
connected_socket, addr = socket.accept()
|
||||||
|
print('Server is receiving data ...')
|
||||||
|
all_data = b''
|
||||||
|
while True:
|
||||||
|
data = connected_socket.recv(BUFFER_SIZE)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
all_data = all_data + data
|
||||||
|
return pickle.loads(all_data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def sendObj(ip_addr, obj):
|
||||||
|
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
soc.connect((ip_addr, TCP_PORT))
|
||||||
|
data = pickle.dumps(obj)
|
||||||
|
soc.send(data)
|
||||||
|
soc.close()
|
||||||
|
return False
|
18
period_2/02-sockets/902/SocketUtil_t.py
Normal file
18
period_2/02-sockets/902/SocketUtil_t.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from TxBlock import *
|
||||||
|
from Transaction import *
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
from SocketUtil import *
|
||||||
|
|
||||||
|
TCP_PORT = 5050
|
||||||
|
BUFFER_SIZE = 1024
|
||||||
|
SERVER = 'localhost'
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
server = newServerSocket(SERVER)
|
||||||
|
print('A connection to the server is established.')
|
||||||
|
Obj = recvObj(server)
|
||||||
|
|
||||||
|
print("Success! The connection is released.") # If returns after time, then successful
|
||||||
|
server.close()
|
88
period_2/02-sockets/902/Transaction.py
Normal file
88
period_2/02-sockets/902/Transaction.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
repr_str = "INPUTS:\n"
|
||||||
|
for addr, amt in self.inputs:
|
||||||
|
repr_str = repr_str + str(amt) + "from" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "OUTPUTS:\n"
|
||||||
|
for addr, amt in self.outputs:
|
||||||
|
repr_str = repr_str + str(amt) + "to" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "EXTRA REQUIRED SIGNATURES:\n"
|
||||||
|
for req_sig in self.reqd:
|
||||||
|
repr_str = repr_str + str(req_sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "SIGNATURES:\n"
|
||||||
|
for sig in self.sigs:
|
||||||
|
repr_str = repr_str + str(sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "END\n"
|
||||||
|
|
||||||
|
return repr_str
|
60
period_2/02-sockets/902/TxBlock.py
Normal file
60
period_2/02-sockets/902/TxBlock.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from BlockChain import CBlock
|
||||||
|
from Signature import generate_keys, sign, verify
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
reward = 25.0
|
||||||
|
leading_zeros = 2
|
||||||
|
next_char_limit = 20
|
||||||
|
|
||||||
|
class TxBlock(CBlock):
|
||||||
|
|
||||||
|
nonce = "A random nonce"
|
||||||
|
|
||||||
|
def __init__(self, previousBlock):
|
||||||
|
super(TxBlock, self).__init__([], previousBlock)
|
||||||
|
|
||||||
|
def addTx(self, Tx_in):
|
||||||
|
self.data.append(Tx_in)
|
||||||
|
|
||||||
|
def __count_totals(self):
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
for tx in self.data:
|
||||||
|
for addr, amt in tx.inputs:
|
||||||
|
total_in = total_in + amt
|
||||||
|
for addr, amt in tx.outputs:
|
||||||
|
total_out = total_out + amt
|
||||||
|
return total_in, total_out
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if not super(TxBlock, self).is_valid():
|
||||||
|
return False
|
||||||
|
for tx in self.data:
|
||||||
|
if not tx.is_valid():
|
||||||
|
return False
|
||||||
|
total_in, total_out = self.__count_totals()
|
||||||
|
if total_out - total_in - reward > 0.000000000001:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def good_nonce(self):
|
||||||
|
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||||
|
digest.update(bytes(str(self.data), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.previousHash), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.nonce), 'utf8'))
|
||||||
|
this_hash = digest.finalize()
|
||||||
|
|
||||||
|
if this_hash[:leading_zeros] != bytes(''.join(['\x4f' for i in range(leading_zeros)]), 'utf8'):
|
||||||
|
return False
|
||||||
|
return int(this_hash[leading_zeros]) < next_char_limit
|
||||||
|
|
||||||
|
def find_nonce(self):
|
||||||
|
for i in range(1000000):
|
||||||
|
self.nonce = ''.join([
|
||||||
|
chr(random.randint(0, 255)) for i in range(10*leading_zeros)])
|
||||||
|
if self.good_nonce():
|
||||||
|
return self.nonce
|
||||||
|
return None
|
24
period_2/02-sockets/903/BlockChain.py
Normal file
24
period_2/02-sockets/903/BlockChain.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if self.previousBlock == None:
|
||||||
|
return True
|
||||||
|
return self.previousBlock.computeHash() == self.previousHash
|
86
period_2/02-sockets/903/Miner_a.py
Normal file
86
period_2/02-sockets/903/Miner_a.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
from SocketUtil import *
|
||||||
|
import TxBlock as Tx
|
||||||
|
# import Tx
|
||||||
|
|
||||||
|
SERVER = 'localhost'
|
||||||
|
|
||||||
|
wallet_list = [SERVER]
|
||||||
|
tx_list = []
|
||||||
|
|
||||||
|
def minerServer(my_ip, wallet_list):
|
||||||
|
miner_server_socket = newServerSocket(my_ip, 5050)
|
||||||
|
|
||||||
|
# receive 2 transactions
|
||||||
|
for i in range(10):
|
||||||
|
newTx = recvObj(miner_server_socket)
|
||||||
|
if isinstance(newTx, Tx):
|
||||||
|
tx_list.append(newTx)
|
||||||
|
print("Received Tx")
|
||||||
|
if len(tx_list) == 2:
|
||||||
|
break
|
||||||
|
|
||||||
|
if len(tx_list) < 2:
|
||||||
|
print("Error! Not enough transactions received.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# collect into block
|
||||||
|
newBlock = TxBlock(None)
|
||||||
|
for tx in tx_list:
|
||||||
|
newBlock.addTx(tx)
|
||||||
|
|
||||||
|
# find nonce
|
||||||
|
newBlock.find_nonce()
|
||||||
|
if newBlock.good_nonce():
|
||||||
|
print("Success! Nonce is valid.")
|
||||||
|
else:
|
||||||
|
print("Error! Nonce is invalid.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# send that block to each in wallet_list
|
||||||
|
for wallet in wallet_list:
|
||||||
|
sendObj(wallet, newBlock)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# Open Server Connection
|
||||||
|
# Rec'v 2 transactions
|
||||||
|
# Collect into block
|
||||||
|
# Find nonce
|
||||||
|
# Send that block to each in walle_list
|
||||||
|
# return
|
||||||
|
|
||||||
|
|
||||||
|
def minerServer(my_ip, wallet_list):
|
||||||
|
# open server connection for the miner
|
||||||
|
server_socket = newServerSocket(my_ip, 5050)
|
||||||
|
print('Server is ready to receive data ...')
|
||||||
|
|
||||||
|
# receive 2 transactions
|
||||||
|
data = recvObj(server_socket)
|
||||||
|
print('Server is receiving data ...')
|
||||||
|
if data:
|
||||||
|
print('Data: ', type(data), '\n')
|
||||||
|
else:
|
||||||
|
print('No object received')
|
||||||
|
|
||||||
|
# collect into block
|
||||||
|
if data:
|
||||||
|
block = TxBlock(None)
|
||||||
|
block.addTx(data)
|
||||||
|
data = recvObj(server_socket)
|
||||||
|
if data:
|
||||||
|
block.addTx(data)
|
||||||
|
server_socket.close()
|
||||||
|
|
||||||
|
# find nonce
|
||||||
|
block.find_nonce()
|
||||||
|
# send that block to each in wallet_list
|
||||||
|
for wallet in wallet_list:
|
||||||
|
sendObj(wallet, block)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
minerServer('localhost', wallet_list)
|
41
period_2/02-sockets/903/Signature.py
Normal file
41
period_2/02-sockets/903/Signature.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from cryptography.exceptions import *
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
|
from cryptography.hazmat.primitives import serialization
|
||||||
|
|
||||||
|
def generate_keys():
|
||||||
|
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
|
||||||
|
pbc_ser = public_key.public_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PublicFormat.SubjectPublicKeyInfo)
|
||||||
|
return private_key, pbc_ser
|
||||||
|
|
||||||
|
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, pbc_ser):
|
||||||
|
message = bytes(str(message), 'utf-8')
|
||||||
|
public_key = serialization.load_pem_public_key(pbc_ser)
|
||||||
|
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
|
41
period_2/02-sockets/903/SocketUtil.py
Normal file
41
period_2/02-sockets/903/SocketUtil.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import socket
|
||||||
|
import pickle
|
||||||
|
import select
|
||||||
|
|
||||||
|
BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
def newServerSocket(ip_addr, port):
|
||||||
|
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server_socket.bind((ip_addr, port))
|
||||||
|
server_socket.listen()
|
||||||
|
return server_socket
|
||||||
|
|
||||||
|
|
||||||
|
def recvObj(socket):
|
||||||
|
inputs, outputs, errs = select.select([socket], [], [socket], 6)
|
||||||
|
if socket in inputs:
|
||||||
|
connected_socket, addr = socket.accept()
|
||||||
|
all_data = b''
|
||||||
|
while True:
|
||||||
|
data = connected_socket.recv(BUFFER_SIZE)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
all_data = all_data + data
|
||||||
|
return pickle.loads(all_data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def sendObj(ip_addr, blk, port):
|
||||||
|
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
soc.connect((ip_addr, port))
|
||||||
|
data = pickle.dumps(blk)
|
||||||
|
soc.send(data)
|
||||||
|
soc.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# changes on newServerConnection
|
||||||
|
# We modified it to accept port number as a parameter, such that when
|
||||||
|
# we make a server we can specify on which port bind it
|
88
period_2/02-sockets/903/Transaction.py
Normal file
88
period_2/02-sockets/903/Transaction.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
repr_str = "INPUTS:\n"
|
||||||
|
for addr, amt in self.inputs:
|
||||||
|
repr_str = repr_str + str(amt) + "from" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "OUTPUTS:\n"
|
||||||
|
for addr, amt in self.outputs:
|
||||||
|
repr_str = repr_str + str(amt) + "to" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "EXTRA REQUIRED SIGNATURES:\n"
|
||||||
|
for req_sig in self.reqd:
|
||||||
|
repr_str = repr_str + str(req_sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "SIGNATURES:\n"
|
||||||
|
for sig in self.sigs:
|
||||||
|
repr_str = repr_str + str(sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "END\n"
|
||||||
|
|
||||||
|
return repr_str
|
64
period_2/02-sockets/903/TxBlock.py
Normal file
64
period_2/02-sockets/903/TxBlock.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from BlockChain import CBlock
|
||||||
|
from Signature import generate_keys, sign, verify
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
reward = 25.0
|
||||||
|
leading_zeros = 2
|
||||||
|
next_char_limit = 20
|
||||||
|
|
||||||
|
class TxBlock (CBlock):
|
||||||
|
|
||||||
|
nonce = "A random nonce"
|
||||||
|
|
||||||
|
def __init__(self, previousBlock):
|
||||||
|
super(TxBlock, self).__init__([], previousBlock)
|
||||||
|
|
||||||
|
def addTx(self, Tx_in):
|
||||||
|
self.data.append(Tx_in)
|
||||||
|
|
||||||
|
def count_totals(self):
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
for tx in self.data:
|
||||||
|
for addr, amt in tx.inputs:
|
||||||
|
total_in = total_in + amt
|
||||||
|
for addr, amt in tx.outputs:
|
||||||
|
total_out = total_out + amt
|
||||||
|
return total_in, total_out
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if not super(TxBlock, self).is_valid():
|
||||||
|
return False
|
||||||
|
for tx in self.data:
|
||||||
|
if not tx.is_valid():
|
||||||
|
return False
|
||||||
|
total_in, total_out = self.count_totals()
|
||||||
|
if total_out - total_in - reward > 0.000000000001:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def good_nonce(self):
|
||||||
|
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||||
|
digest.update(bytes(str(self.data), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.previousHash), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.nonce), 'utf8'))
|
||||||
|
this_hash = digest.finalize()
|
||||||
|
|
||||||
|
if this_hash[:leading_zeros] != bytes(''.join(['\x4f' for i in range(leading_zeros)]), 'utf8'):
|
||||||
|
return False
|
||||||
|
return int(this_hash[leading_zeros]) < next_char_limit
|
||||||
|
|
||||||
|
def find_nonce(self):
|
||||||
|
for i in range(1000000):
|
||||||
|
self.nonce = ''.join([
|
||||||
|
chr(random.randint(0, 255)) for i in range(10*leading_zeros)])
|
||||||
|
if self.good_nonce():
|
||||||
|
return self.nonce
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# count_total() needs to be public to be used in Miner
|
69
period_2/02-sockets/903/Wallet_t.py
Normal file
69
period_2/02-sockets/903/Wallet_t.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from SocketUtil import *
|
||||||
|
from Transaction import *
|
||||||
|
from Signature import *
|
||||||
|
|
||||||
|
M_SERVER_IP = 'localhost'
|
||||||
|
M_SERVER_PORT = 5005
|
||||||
|
|
||||||
|
W_SERVER_IP = 'localhost'
|
||||||
|
W_SERVER_PORT = 5006
|
||||||
|
|
||||||
|
alex_prv, alex_pbc = generate_keys()
|
||||||
|
mike_prv, mike_pbc = generate_keys()
|
||||||
|
rose_prv, rose_pbc = generate_keys()
|
||||||
|
mara_prv, mara_pbc = generate_keys()
|
||||||
|
|
||||||
|
Tx1 = Tx()
|
||||||
|
Tx1.add_input(alex_pbc, 4.0)
|
||||||
|
Tx1.add_input(mike_pbc, 1.0)
|
||||||
|
Tx1.add_output(rose_pbc, 4.8)
|
||||||
|
Tx1.sign(alex_prv)
|
||||||
|
Tx1.sign(mike_prv)
|
||||||
|
|
||||||
|
Tx2 = Tx()
|
||||||
|
Tx2.add_input(rose_pbc, 4.0)
|
||||||
|
Tx2.add_output(mike_pbc, 4.0)
|
||||||
|
Tx2.add_reqd(alex_pbc)
|
||||||
|
Tx2.sign(rose_prv)
|
||||||
|
Tx2.sign(alex_prv)
|
||||||
|
|
||||||
|
print(Tx1.is_valid())
|
||||||
|
print(Tx2.is_valid())
|
||||||
|
|
||||||
|
try:
|
||||||
|
sendObj(M_SERVER_IP, Tx1, M_SERVER_PORT)
|
||||||
|
print("Sent Tx1")
|
||||||
|
sendObj(M_SERVER_IP, Tx2, M_SERVER_PORT)
|
||||||
|
print("Sent Tx2")
|
||||||
|
|
||||||
|
except:
|
||||||
|
print("Error! Connection unsuccessful.")
|
||||||
|
|
||||||
|
wallet_server_socket = newServerSocket(W_SERVER_IP, W_SERVER_PORT)
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
newBlock = recvObj(wallet_server_socket)
|
||||||
|
if newBlock:
|
||||||
|
break
|
||||||
|
wallet_server_socket.close()
|
||||||
|
|
||||||
|
if newBlock.is_valid():
|
||||||
|
print("Success! Block is valid.")
|
||||||
|
|
||||||
|
if newBlock.good_nonce():
|
||||||
|
print("Success! Nonce is valid.")
|
||||||
|
|
||||||
|
tx1_found = tx2_found = False
|
||||||
|
for tx in newBlock.data:
|
||||||
|
try:
|
||||||
|
if tx.inputs[0][0] == alex_pbc and tx.inputs[0][1] == 4.0:
|
||||||
|
print("Tx1 is present.")
|
||||||
|
tx1_found = True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if tx.inputs[0][0] == rose_pbc and tx.inputs[0][1] == 4.0:
|
||||||
|
print("Tx2 is present.")
|
||||||
|
tx2_found = True
|
||||||
|
except:
|
||||||
|
pass
|
Loading…
x
Reference in New Issue
Block a user