Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions src/Main/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,26 @@ public static void main(String[] args) throws IOException {
switch (command.toLowerCase()) {
case "upload":
// Start a new thread for upload
FileData fileupload = new FileData(argument);
System.out.println("The Hash of the File is " + fileupload.getFileHash());
Handshake.registerFile(fileupload , argument);
break;
String filePath = argument;
FileData fileupload = new FileData(filePath);

System.out.print("Set password for this file? (leave empty for no password): ");
String password = scanner.nextLine().trim();

if (!password.isEmpty()) {
fileupload.setPasswordHash(FileData.hashPassword(password));
System.out.println("Password protection enabled");
}

System.out.println("The Hash of the File is " + fileupload.getFileHash());
Handshake.registerFile(fileupload , filePath);
break;
case "download":
// Start a new thread for download
FileReciever.downloadFile(argument, central);

// Start a new thread for download
System.out.print("File password (leave empty if none): ");
String downloadPassword = scanner.nextLine().trim();
FileReciever.downloadFile(argument, central, downloadPassword);

break;
case "broadcastfile":
FileData f = new FileData(argument);
Expand Down
27 changes: 27 additions & 0 deletions src/discovery/FileData.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class FileData implements Serializable{
private long fileSize; // Size in bytes
private String fileType; // MIME type or file extension
private String fileHash; // Checksum or hash for integrity verification
private String passwordHash; //SHA-256 hash of Password

// Constructors
public FileData() {
Expand Down Expand Up @@ -77,6 +78,14 @@ public void setFileHash(String fileHash) {
this.fileHash = fileHash;
}

public String getPasswordHash() {
return passwordHash;
}

public void setPasswordHash(String passwordHash) {
this.passwordHash = passwordHash;
}

// Helper method to extract the file extension
private String getFileExtension(String fileName) {
int lastDotIndex = fileName.lastIndexOf('.');
Expand Down Expand Up @@ -107,6 +116,24 @@ private String calculateFileHash(File file) throws IOException {
throw new RuntimeException("MD5 algorithm not found.", e);
}
}

//Helper method to Hash Password
public static String hashPassword(String password) {
if (password == null || password.isEmpty()) {
return null;
}
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = md.digest(password.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-256 algorithm not found.", e);
}
}

// toString method for easy debugging
@Override
Expand Down
71 changes: 52 additions & 19 deletions src/discovery/Handshake.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,54 @@ public static void start(int port, Node c) {
FileResponse res;

if (HashtoFD.containsKey(req.FileData.getFileHash())) {
res = new FileResponse(req.RequestingNode, client, true, Handshake.HashtoFD.get(req.FileData.getFileHash()));
FileData storedFile = Handshake.HashtoFD.get(req.FileData.getFileHash());

UserExperience.printStatus("File found, sending response...");
ObjectTransfer.sendObject(socket, res);
// Password Verification
boolean passwordValid = true;
if (storedFile.getPasswordHash() != null) {
// File is password protected
String attemptHash = FileData.hashPassword(req.passwordAttempt);
passwordValid = storedFile.getPasswordHash().equals(attemptHash);

if (passwordValid) {
UserExperience.printSuccess("Password verified");
} else {
UserExperience.printWarning("Invalid password");
}
}

obj = ObjectTransfer.receiveObject(socket);
TransferRequest treq = (TransferRequest)obj;

TransferResponse tres = new TransferResponse(treq.RequestingNode, client, treq.Port, true);
ObjectTransfer.sendObject(socket, tres);

socket.close();

UserExperience.printSeparator();
UserExperience.printStatus("Starting file transfer to " + req.RequestingNode.getPeerIP());

ConnectionHandlerSequential.sendFile(
tres.RequestingNode.getPeerIP(),
tres.Port,
Handshake.HashtoPath.get(treq.Fd.getFileHash()),
req.pub
);
if (passwordValid) {
// Password is correct or no password required - proceed with transfer
res = new FileResponse(req.RequestingNode, client, true, storedFile);

UserExperience.printStatus("File found, sending response...");
ObjectTransfer.sendObject(socket, res);

obj = ObjectTransfer.receiveObject(socket);
TransferRequest treq = (TransferRequest)obj;

TransferResponse tres = new TransferResponse(treq.RequestingNode, client, treq.Port, true);
ObjectTransfer.sendObject(socket, tres);

socket.close();

UserExperience.printSeparator();
UserExperience.printStatus("Starting file transfer to " + req.RequestingNode.getPeerIP());

ConnectionHandlerSequential.sendFile(
tres.RequestingNode.getPeerIP(),
tres.Port,
Handshake.HashtoPath.get(treq.Fd.getFileHash()),
req.pub
);
} else {
// PASSWORD INCORRECT
res = new FileResponse(req.RequestingNode, client, false, storedFile);
ObjectTransfer.sendObject(socket, res);
socket.close();
UserExperience.printSeparator();
}
}

} catch (IOException | ClassNotFoundException e) {
Expand All @@ -79,6 +105,13 @@ public static void registerFile(FileData f, String path) {
UserExperience.printStatus("Hash: " + f.getFileHash());
UserExperience.printStatus("Size: " + UserExperience.formatBytes(f.getFileSize()));

//SHOW PASSWORD PROTECTION STATUS
if (f.getPasswordHash() != null) {
UserExperience.printStatus("Security: Password protected");
} else {
UserExperience.printStatus("Security: Public (no password)");
}

try {
Socket socket = new Socket(central.getPeerIP(), central.getPeerPort());
ObjectTransfer.sendObject(socket, req);
Expand Down
9 changes: 6 additions & 3 deletions src/discovery/messages/FileRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ public class FileRequest implements Serializable{
public FileData FileData;
public Node RequestingNode;
public PublicKey pub;
public FileRequest(FileData f , Node n){
this.FileData = f;
this.RequestingNode = n;
public String passwordAttempt;

public FileRequest(FileData f , Node n , String password) {
this.FileData = f;
this.RequestingNode = n;
this.passwordAttempt = password;
}
}
22 changes: 17 additions & 5 deletions src/p2p/FileReciever.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

public class FileReciever {

public static void downloadFile(String fileHash, Node CentralRegistry) {
// Added password parameter
public static void downloadFile(String fileHash, Node CentralRegistry, String password) {

UserExperience.printSeparator();
UserExperience.printStage(TransferStage.CONNECTING);
Expand Down Expand Up @@ -48,7 +49,8 @@ public static void downloadFile(String fileHash, Node CentralRegistry) {
UserExperience.printStatus("Attempting download from peer " + (i+1) + "/" + res.peers.length);
UserExperience.printStatus("Peer: " + potentialPeer.getPeerIP() + ":" + potentialPeer.getPeerPort());

if (FileReciever.downloadFromPeer(potentialPeer, file)) {
// Pass password to downloadFromPeer
if (FileReciever.downloadFromPeer(potentialPeer, file, password)) {
UserExperience.printSuccess("Download completed successfully!");
downloaded = true;
break;
Expand All @@ -73,9 +75,11 @@ public static void downloadFile(String fileHash, Node CentralRegistry) {
}
}

public static boolean downloadFromPeer(Node peer, FileData f) {
Node two = Handshake.getClient();
FileRequest req = new FileRequest(f, two);
// Added password parameter
public static boolean downloadFromPeer(Node peer, FileData f, String password) {
Node two = Handshake.getClient();
// Pass password in FileRequest constructor
FileRequest req = new FileRequest(f, two, password);

try {
UserExperience.printStage(TransferStage.NEGOTIATING);
Expand All @@ -93,6 +97,14 @@ public static boolean downloadFromPeer(Node peer, FileData f) {

Object obj = ObjectTransfer.receiveObject(socket);
FileResponse res = (FileResponse)obj;

// Check if rejected due to wrong password
if (!res.response) {
UserExperience.printWarning("Access denied - Invalid password");
socket.close();
return false;
}

String fileName = res.file.getFileName();

UserExperience.printSuccess("Peer accepted request for: " + fileName);
Expand Down
24 changes: 20 additions & 4 deletions src/testing/FileTesting.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public static void senderThread(String []files , Thread recieverThread) {
t.start(); //this thread line will be started for each of the peer
for(String filePath : files) {
FileData f = new FileData(filePath);
// Explicitly set no password
f.setPasswordHash(null); // No password for tests
Handshake.registerFile(f , filePath);
}
recieverThread.start();
Expand All @@ -97,16 +99,30 @@ public static void senderThread(String []files , Thread recieverThread) {

public static void recieverThread(String []hashes) {
Node client = new Node();
client.setPeerIP(SenderIP);
client.setPeerPort(SenderPort);
client.setPeerIP(RecieverIP); // FIXED: Was SenderIP, should be RecieverIP ***
client.setPeerPort(RecieverPort); // FIXED: Was SenderPort, should be RecieverPort ***

Node central = new Node();
central.setPeerIP(CentralIP);
central.setPeerPort(CentralPort);

// Initialize Handshake for receiver
Handshake.setClient(client);
Handshake.setCentralRegistry(central);
Thread t = new Thread(() -> Handshake.start(client.getPeerPort() , client));
t.start();

// Small delay to ensure receiver is ready
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

for(String hash : hashes) {
FileReciever.downloadFile(hash, central);
// Pass null password for test downloads
FileReciever.downloadFile(hash, central, null);
}

}
}
}