Skip to content

Commit

Permalink
added cryptography
Browse files Browse the repository at this point in the history
  • Loading branch information
Tanguyvans committed Dec 12, 2023
1 parent 33c4a66 commit c08c2b8
Showing 4 changed files with 142 additions and 26 deletions.
48 changes: 48 additions & 0 deletions pbft/crypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding, utils
from cryptography.hazmat.primitives import hashes

import base64

# Création d'une paire de clés privée/publique
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()

print(public_key)

# Message à signer
message = b"Hello, world!"

# Signature du message avec la clé privée
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)

signature_base64 = base64.b64encode(signature).decode()

# Revenir en binaire à partir de la chaîne base64
signature_binary = base64.b64decode(signature_base64)

# Vérification de la signature avec la clé publique
try:
public_key.verify(
signature_binary,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("La signature est valide.")
except utils.InvalidSignature:
print("La signature n'est pas valide.")
61 changes: 57 additions & 4 deletions pbft/node.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,15 @@
import threading
import json

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding

import base64

from pbft_protocol import PBFTProtocol
from consensus_protocol import ConsensusProtocol
from blockchain import Blockchain
@@ -19,6 +28,42 @@ def __init__(self, node_id, host, port, consensus_protocol):
if consensus_protocol == "pbft":
self.consensus_protocol = PBFTProtocol(node=self, blockchain=self.blockchain)

self.private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
self.public_key = self.private_key.public_key()

def sign_message(self, message):
signature = self.private_key.sign(
json.dumps(message).encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return base64.b64encode(signature).decode()

def verify_signature(self, signature, message, public_key):
try:
signature_binary = base64.b64decode(signature)

public_key.verify(
signature_binary,
json.dumps(message).encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return True
except Exception as e:
print(f"Signature verification error: {e}")
return False

def start_server(self):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((self.host, self.port))
@@ -37,18 +82,26 @@ def handle_message(self, client_socket):
client_socket.close()

def broadcast_message(self, message):

for peer_id in self.peers:
self.send_message(peer_id, message)

def send_message(self, peer_id, message):
if peer_id in self.peers:
peer_address = self.peers[peer_id]
peer_info = self.peers[peer_id]
peer_address = peer_info["address"]

signed_message = message.copy()
signed_message["signature"] = self.sign_message(signed_message)
signed_message["id"] = self.node_id

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(peer_address)
client_socket.send(json.dumps(message).encode())
client_socket.send(json.dumps(signed_message).encode())
client_socket.close()
else:
print(f"Peer {peer_id} not found.")

def add_peer(self, peer_id, peer_address):
self.peers[peer_id] = peer_address
def add_peer(self, peer_id, peer_address, public_key):
self.peers[peer_id] = {"address": peer_address, "public_key": public_key}

42 changes: 29 additions & 13 deletions pbft/pbft_protocol.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import time

from block import Block
from consensus_protocol import ConsensusProtocol

@@ -14,26 +16,40 @@ def __init__(self, node, blockchain):
def handle_message(self, message):
message_type = message.get("type")

print("message", message)

if message["id"] not in self.node.peers:
return

public_key = self.node.peers[message["id"]]["public_key"]
msg = {"type": message["type"], "content": message["content"]}
is_valid_signature = self.node.verify_signature(message["signature"], msg, public_key)

if not is_valid_signature:
print(f"Not valid signature {message}")
return

print(f"Is valid signature: {is_valid_signature}")

if message_type == "request":
self.request(message["message"])
time.sleep(3)
self.request(message["content"])
elif message_type == "pre-prepare":
self.pre_prepare(message["block"])
time.sleep(3)
self.pre_prepare(message["content"])
elif message_type == "prepare":
self.prepare(message["block"])
time.sleep(3)
self.prepare(message["content"])
elif message_type == "commit":
self.commit(message["block"])
time.sleep(3)
self.commit(message["content"])
else:
print(f"Unknown message type: {message_type}")

def request(self, content):
# Implémentez la logique de la phase request pour PBFT
print(f"Node {self.node_id} received request with content: {content}")
# Créez un bloc à partir de la demande et déclenchez la phase pre-prepare
block = self.create_block_from_request(content)

message = {"type": "pre-prepare", "block": block.to_dict()}
message = {"type": "pre-prepare", "content": block.to_dict()}
self.node.broadcast_message(message)
self.handle_message(message)

def pre_prepare(self, message):
print(f"Node {self.node_id} received pre-prepare for block: \n{message}")
@@ -42,7 +58,7 @@ def pre_prepare(self, message):

self.prepare_counts[message["current_hash"]] = 0

message = {"type": "prepare", "block": block.to_dict()}
message = {"type": "prepare", "content": block.to_dict()}
self.node.broadcast_message(message)

def prepare(self, message):
@@ -53,7 +69,7 @@ def prepare(self, message):
self.prepare_counts[block_hash] += 1

if self.is_prepared(block_hash):
commit_message = {"type": "commit", "block": message}
commit_message = {"type": "commit", "content": message}
self.node.broadcast_message(commit_message)
print(f"Node {self.node_id} prepared block to {self.node.peers}")
else:
@@ -116,7 +132,7 @@ def create_block_from_request(self, content):
return new_block

def is_prepared(self, id):
return self.prepare_counts[id] >= 2
return self.prepare_counts[id] >= 1

def can_commit(self, id):
return self.commit_counts[id] >= 2
17 changes: 8 additions & 9 deletions pbft/test.py
Original file line number Diff line number Diff line change
@@ -12,14 +12,14 @@
node2 = Node(node_id="N1", host="localhost", port=port_node_2, consensus_protocol="pbft")
node3 = Node(node_id="N2", host="localhost", port=port_node_3, consensus_protocol="pbft")

node1.add_peer(peer_id="N1", peer_address=("localhost", port_node_2))
node1.add_peer(peer_id="N2", peer_address=("localhost", port_node_3))
node1.add_peer(peer_id="N1", peer_address=("localhost", port_node_2), public_key=node2.public_key)
node1.add_peer(peer_id="N2", peer_address=("localhost", port_node_3), public_key=node3.public_key)

node2.add_peer(peer_id="N0", peer_address=("localhost", port_node_1))
node2.add_peer(peer_id="N2", peer_address=("localhost", port_node_3))
node2.add_peer(peer_id="N0", peer_address=("localhost", port_node_1), public_key=node1.public_key)
node2.add_peer(peer_id="N2", peer_address=("localhost", port_node_3), public_key=node3.public_key)

node3.add_peer(peer_id="N0", peer_address=("localhost", port_node_1))
node3.add_peer(peer_id="N1", peer_address=("localhost", port_node_2))
node3.add_peer(peer_id="N0", peer_address=("localhost", port_node_1), public_key=node1.public_key)
node3.add_peer(peer_id="N1", peer_address=("localhost", port_node_2), public_key=node2.public_key)

threading.Thread(target=node1.start_server).start()
threading.Thread(target=node2.start_server).start()
@@ -28,12 +28,11 @@
while True:
msg = input()
if msg != "q":
message_from_node1 = {"type": "request", "message": msg}
message_from_node1 = {"type": "request", "content": msg}
node2.send_message(peer_id="N0", message=message_from_node1)
else:
break

node1.blockchain.print_blockchain()
node2.blockchain.print_blockchain()
node3.blockchain.print_blockchain()

node3.blockchain.print_blockchain()

0 comments on commit c08c2b8

Please sign in to comment.