From 2b8c4491f5b00fc2e91f4b1b1d609b8c0b0c2e16 Mon Sep 17 00:00:00 2001 From: vedang29 Date: Mon, 14 Apr 2025 03:40:31 +0530 Subject: [PATCH] Finally Its done quick quick quick --- pom.xml | 4 +- .../SkycrateBackendApplication.java | 68 +-- .../skycrateBackend/config/HDFSConfig.java | 36 +- .../config/SecurityConfig.java | 23 ++ .../controller/HDFScontroller.java | 387 +++++++++++++----- .../skycrateBackend/dto/ResponseDTO.java | 27 ++ .../services/EncryptionUtil.java | 147 +++++-- .../services/HDFSOperations.java | 319 +++++++++++---- .../skycrateBackend/utils/KeyUtil.java | 26 ++ src/main/resources/application.properties | 4 + tmp/Handout-A5.pdf | Bin 0 -> 60219 bytes 11 files changed, 760 insertions(+), 281 deletions(-) create mode 100644 src/main/java/com/skycrate/backend/skycrateBackend/config/SecurityConfig.java create mode 100644 src/main/java/com/skycrate/backend/skycrateBackend/dto/ResponseDTO.java create mode 100644 src/main/java/com/skycrate/backend/skycrateBackend/utils/KeyUtil.java create mode 100644 tmp/Handout-A5.pdf diff --git a/pom.xml b/pom.xml index fc7b716..e61d69e 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ 3.2.4 - + org.springframework.boot spring-boot-starter-security @@ -171,6 +171,8 @@ + + diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/SkycrateBackendApplication.java b/src/main/java/com/skycrate/backend/skycrateBackend/SkycrateBackendApplication.java index a697e48..ea53f8d 100644 --- a/src/main/java/com/skycrate/backend/skycrateBackend/SkycrateBackendApplication.java +++ b/src/main/java/com/skycrate/backend/skycrateBackend/SkycrateBackendApplication.java @@ -1,41 +1,16 @@ -package com.skycrate.backend.skycrateBackend; - -import com.skycrate.backend.skycrateBackend.controller.HDFScontroller; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SkycrateBackendApplication implements CommandLineRunner { - - @Autowired - private HDFScontroller hdfsController; - - public static void main(String[] args) { - SpringApplication.run(SkycrateBackendApplication.class, args); - } - - @Override - public void run(String... args) { - try { - hdfsController.run(); // ✅ Run the instance method, not static - } catch (Exception e) { - System.err.println("❌ Error running CLI: " + e.getMessage()); - e.printStackTrace(); - } - } -} - - //package com.skycrate.backend.skycrateBackend; // -//import com.skycrate.backend.skycrateBackend.controller.HDFScontroller; +//import com.skycrate.backend.skycrateBackend.services.HDFSOperations; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.CommandLineRunner; //import org.springframework.boot.SpringApplication; //import org.springframework.boot.autoconfigure.SpringBootApplication; // //@SpringBootApplication -//public class SkycrateBackendApplication { +//public class SkycrateBackendApplication implements CommandLineRunner { +// +// @Autowired +// private HDFSOperations hdfsOperations; // Autowire the service, not the controller // // public static void main(String[] args) { // SpringApplication.run(SkycrateBackendApplication.class, args); @@ -44,11 +19,36 @@ public class SkycrateBackendApplication implements CommandLineRunner { // @Override // public void run(String... args) { // try { -// HDFScontroller.run(); // ✅ Run the instance method, not static +// // Example of calling the HDFS service directly +// String localPath = "/path/to/local/file"; +// String hdfsPath = "/path/in/hdfs"; +// String uploadedFileName = "example.txt"; +// String username = "user123"; +// +// // Call HDFSOperations directly +// hdfsOperations.uploadFile(localPath, hdfsPath, uploadedFileName, username); +// +// System.out.println("File upload executed successfully"); +// // } catch (Exception e) { // System.err.println("❌ Error running CLI: " + e.getMessage()); // e.printStackTrace(); // } // } -// //} + + + +package com.skycrate.backend.skycrateBackend; + +import com.skycrate.backend.skycrateBackend.controller.HDFScontroller; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SkycrateBackendApplication { + + public static void main(String[] args) { + SpringApplication.run(SkycrateBackendApplication.class, args); + } +} diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/config/HDFSConfig.java b/src/main/java/com/skycrate/backend/skycrateBackend/config/HDFSConfig.java index 6089da5..d13f910 100644 --- a/src/main/java/com/skycrate/backend/skycrateBackend/config/HDFSConfig.java +++ b/src/main/java/com/skycrate/backend/skycrateBackend/config/HDFSConfig.java @@ -1,37 +1,3 @@ -//package com.skycrate.backend.skycrateBackend.config; -// -//import org.apache.hadoop.conf.Configuration; -//import org.apache.hadoop.fs.FileSystem; -//import org.apache.hadoop.security.UserGroupInformation; -//import org.springframework.context.annotation.Bean; -// -//import java.io.IOException; -//import java.net.URI; -//import java.security.PrivilegedExceptionAction; -// -//@org.springframework.context.annotation.Configuration -//public class HDFSConfig { -// -// public static FileSystem getHDFS() throws Exception { -// Configuration conf = new Configuration(); -// conf.set("fs.defaultFS", "hdfs://192.168.29.56:9000"); -// conf.set("hadoop.security.authentication", "simple"); -// -// // Disable security manager -// System.setProperty("java.security.manager", "allow"); -// -// // Required for Java 17+: Explicitly configure UGI -// UserGroupInformation.setConfiguration(conf); -// UserGroupInformation ugi = UserGroupInformation.createRemoteUser("hdfs"); -// -// // Login user explicitly and return FileSystem instance -// return ugi.doAs((PrivilegedExceptionAction) () -> -// FileSystem.get(new URI("hdfs://192.168.29.56:9000"), conf) -// ); -// } -//} - - package com.skycrate.backend.skycrateBackend.config; import org.apache.hadoop.conf.Configuration; @@ -49,4 +15,6 @@ public class HDFSConfig { conf.set("fs.defaultFS", "hdfs://192.168.29.56:9000"); return FileSystem.get(new URI("hdfs://192.168.29.56:9000"), conf); } + + } diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/config/SecurityConfig.java b/src/main/java/com/skycrate/backend/skycrateBackend/config/SecurityConfig.java new file mode 100644 index 0000000..20e8c43 --- /dev/null +++ b/src/main/java/com/skycrate/backend/skycrateBackend/config/SecurityConfig.java @@ -0,0 +1,23 @@ +package com.skycrate.backend.skycrateBackend.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class SecurityConfig { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) // Disable CSRF for testing APIs + .authorizeHttpRequests(auth -> auth + .requestMatchers("/api/hdfs/**").permitAll() // Allow HDFS endpoints + .anyRequest().authenticated() // Everything else needs auth + ); + + return http.build(); + } +} diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/controller/HDFScontroller.java b/src/main/java/com/skycrate/backend/skycrateBackend/controller/HDFScontroller.java index e46e535..93c82a0 100644 --- a/src/main/java/com/skycrate/backend/skycrateBackend/controller/HDFScontroller.java +++ b/src/main/java/com/skycrate/backend/skycrateBackend/controller/HDFScontroller.java @@ -1,128 +1,297 @@ package com.skycrate.backend.skycrateBackend.controller; -import com.skycrate.backend.skycrateBackend.dto.User; -import com.skycrate.backend.skycrateBackend.repository.UserManager; +import com.skycrate.backend.skycrateBackend.dto.ResponseDTO; +import com.skycrate.backend.skycrateBackend.services.EncryptionUtil; import com.skycrate.backend.skycrateBackend.services.HDFSOperations; +import com.skycrate.backend.skycrateBackend.utils.KeyUtil; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; -import java.util.Scanner; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.List; -@Component -public class HDFScontroller implements Runnable { +import static com.skycrate.backend.skycrateBackend.utils.KeyUtil.getPrivateKeyForUser; +import static com.skycrate.backend.skycrateBackend.utils.KeyUtil.getPublicKeyForUser; + +@RestController +@RequestMapping("/api/hdfs") +public class HDFScontroller { - private final UserManager userManager; private final HDFSOperations hdfsOperations; @Autowired - public HDFScontroller(UserManager userManager, HDFSOperations hdfsOperations) { - this.userManager = userManager; + public HDFScontroller(HDFSOperations hdfsOperations) { this.hdfsOperations = hdfsOperations; } - @Override - public void run() { - Scanner scanner = new Scanner(System.in); - - while (true) { - System.out.print("Enter your username: "); - String username = scanner.nextLine(); - - System.out.print("Enter your password: "); - String password = scanner.nextLine(); - - if (!userManager.authenticate(username, password)) { - System.out.println("❌ Authentication failed. Exiting..."); - return; - } - - User user; - try { - user = userManager.getUser(username); - } catch (Exception e) { - System.out.println("❌ Error creating user: " + e.getMessage()); - return; - } - - while (true) { - System.out.println("\nChoose an option:"); - System.out.println("1. Create a folder"); - System.out.println("2. Upload a file (encrypted)"); - System.out.println("3. Upload a file to a specific folder (encrypted)"); - System.out.println("4. Download a file"); - System.out.println("5. Delete a file"); - System.out.println("6. Delete a folder"); - System.out.println("7. List files and folders"); - System.out.println("8. Exit"); - - int choice = scanner.nextInt(); - scanner.nextLine(); // Consume newline - - try { - switch (choice) { - case 1: - System.out.print("Enter folder name: "); - hdfsOperations.createFolder(scanner.nextLine()); - break; - - case 2: - System.out.print("Enter file path to upload: "); - String filePath = scanner.nextLine(); - System.out.print("Enter HDFS destination path: "); - String hdfsDestinationFolder = scanner.nextLine(); - System.out.print("Enter the name for the uploaded file: "); - String uploadedFileName = scanner.nextLine(); - hdfsOperations.uploadFile(filePath, hdfsDestinationFolder, uploadedFileName, user); - break; - - case 3: - System.out.print("Enter folder name to upload to: "); - String targetFolder = scanner.nextLine(); - System.out.print("Enter file path to upload: "); - String fileToUpload = scanner.nextLine(); - System.out.print("Enter the name for the uploaded file: "); - String uploadedFileNameSpecific = scanner.nextLine(); - hdfsOperations.uploadFile(fileToUpload, targetFolder, uploadedFileNameSpecific, user); - break; - - case 4: - System.out.print("Enter HDFS file path to download: "); - String hdfsFilePath = scanner.nextLine(); - System.out.print("Enter local path to save the downloaded file: "); - String localDownloadPath = scanner.nextLine(); - hdfsOperations.downloadFile(hdfsFilePath, localDownloadPath, user); - break; - - case 5: - System.out.print("Enter HDFS file path to delete: "); - hdfsOperations.deleteFile(scanner.nextLine()); - break; - - case 6: - System.out.print("Enter HDFS folder path to delete: "); - hdfsOperations.deleteFolder(scanner.nextLine()); - break; - - case 7: - System.out.print("Enter HDFS path to list files and folders: "); - hdfsOperations.listFilesAndFolders(scanner.nextLine()); - break; - - case 8: - System.out.println("✅ Exiting..."); - return; - - default: - System.out.println("⚠️ Invalid option. Please try again."); - } - } catch (Exception e) { - System.out.println("❌ Operation failed: " + e.getMessage()); - e.printStackTrace(); - } - } + @PostMapping("/createFolder") + public ResponseDTO createFolder(@RequestParam String hdfsPath) { + System.out.println("==> Received createFolder call for: " + hdfsPath); + try { + hdfsOperations.createFolder(hdfsPath); + return new ResponseDTO("Folder created successfully", true); + } catch (Exception e) { + e.printStackTrace(); + return new ResponseDTO("Failed to create folder: " + e.getMessage(), false); } } + + + @PostMapping("/uploadFile") + public ResponseDTO uploadFile( + @RequestParam("file") MultipartFile file, + @RequestParam String hdfsPath, + @RequestParam String uploadedFileName, + @RequestParam String username) { + try { + // Save file locally first + String localPath = saveFileLocally(file); + System.out.println("File saved locally at: " + localPath); + + // Upload file to HDFS + hdfsOperations.uploadFile(localPath, hdfsPath, uploadedFileName, username); + return new ResponseDTO("File uploaded successfully", true); + } catch (IOException e) { + e.printStackTrace(); + return new ResponseDTO("Failed to upload file locally: " + e.getMessage(), false); + } catch (Exception e) { + e.printStackTrace(); + return new ResponseDTO("Failed to upload file to HDFS: " + e.getMessage(), false); + } + } + + + private String saveFileLocally(MultipartFile file) throws IOException { + // Create a temporary directory if it doesn't exist + Path tmpDir = Paths.get("tmp"); + if (!Files.exists(tmpDir)) { + Files.createDirectories(tmpDir); // Create the directory if it doesn't exist + } + + Path path = tmpDir.resolve(file.getOriginalFilename()); + + // Copy the file to the local directory + Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING); + + return path.toString(); // Return the local path for further processing + } + + + @PostMapping("/downloadFile") + public ResponseDTO downloadFile( + @RequestParam String hdfsPath, + @RequestParam String localPath, + @RequestParam String username) { + try { + hdfsOperations.downloadFile(hdfsPath, localPath, username); + return new ResponseDTO("File downloaded successfully", true); + } catch (Exception e) { + return new ResponseDTO("Failed to download file: " + e.getMessage(), false); + } + } + + @DeleteMapping("/deleteFile") + public ResponseDTO deleteFile(@RequestParam String hdfsPath) { + try { + hdfsOperations.deleteFile(hdfsPath); + return new ResponseDTO("File deleted successfully", true); + } catch (Exception e) { + return new ResponseDTO("Failed to delete file: " + e.getMessage(), false); + } + } + + @DeleteMapping("/deleteFolder") + public ResponseDTO deleteFolder(@RequestParam String hdfsPath) { + try { + hdfsOperations.deleteFolder(hdfsPath); + return new ResponseDTO("Folder deleted successfully", true); + } catch (Exception e) { + return new ResponseDTO("Failed to delete folder: " + e.getMessage(), false); + } + } + + @GetMapping("/listFiles") + public ResponseEntity listFiles(@RequestParam String hdfsPath) { + try { + List files = hdfsOperations.listFilesAndFolders(hdfsPath); + return ResponseEntity.ok(files); // Returns the list as JSON array + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Failed to list files: " + e.getMessage()); + } + } + +// @GetMapping("/listFiles") +// public ResponseDTO listFiles(@RequestParam String hdfsPath) { +// try { +// hdfsOperations.listFilesAndFolders(hdfsPath); +// return new ResponseDTO("Listed files successfully", true); +// } catch (Exception e) { +// return new ResponseDTO("Failed to list files: " + e.getMessage(), false); +// } +// } } + + + + + + +//package com.skycrate.backend.skycrateBackend.controller; +// +//import com.skycrate.backend.skycrateBackend.dto.User; +//import com.skycrate.backend.skycrateBackend.repository.UserManager; +//import com.skycrate.backend.skycrateBackend.services.HDFSOperations; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +// +//import java.util.Scanner; +// +//@Component +//public class HDFScontroller implements Runnable { +// +// private final UserManager userManager; +// private final HDFSOperations hdfsOperations; +// +// @Autowired +// public HDFScontroller(UserManager userManager, HDFSOperations hdfsOperations) { +// this.userManager = userManager; +// this.hdfsOperations = hdfsOperations; +// } +// +// @Override +// public void run() { +// Scanner scanner = new Scanner(System.in); +// +// while (true) { +// System.out.print("Enter your username: "); +// String username = scanner.nextLine(); +// +// System.out.print("Enter your password: "); +// String password = scanner.nextLine(); +// +// if (!userManager.authenticate(username, password)) { +// System.out.println("❌ Authentication failed. Exiting..."); +// return; +// } +// +// User user; +// try { +// user = userManager.getUser(username); +// } catch (Exception e) { +// System.out.println("❌ Error creating user: " + e.getMessage()); +// return; +// } +// +// while (true) { +// System.out.println("\nChoose an option:"); +// System.out.println("1. Create a folder"); +// System.out.println("2. Upload a file (encrypted)"); +// System.out.println("3. Upload a file to a specific folder (encrypted)"); +// System.out.println("4. Download a file"); +// System.out.println("5. Delete a file"); +// System.out.println("6. Delete a folder"); +// System.out.println("7. List files and folders"); +// System.out.println("8. Exit"); +// +// int choice = scanner.nextInt(); +// scanner.nextLine(); // Consume newline +// +// try { +// switch (choice) { +// case 1: +// System.out.print("Enter folder name: "); +// hdfsOperations.createFolder(scanner.nextLine()); +// break; +// +// case 2: +// System.out.print("Enter file path to upload: "); +// String filePath = scanner.nextLine(); +// System.out.print("Enter HDFS destination path: "); +// String hdfsDestinationFolder = scanner.nextLine(); +// System.out.print("Enter the name for the uploaded file: "); +// String uploadedFileName = scanner.nextLine(); +// hdfsOperations.uploadFile(filePath, hdfsDestinationFolder, uploadedFileName, user); +// break; +// +// case 3: +// System.out.print("Enter folder name to upload to: "); +// String targetFolder = scanner.nextLine(); +// System.out.print("Enter file path to upload: "); +// String fileToUpload = scanner.nextLine(); +// System.out.print("Enter the name for the uploaded file: "); +// String uploadedFileNameSpecific = scanner.nextLine(); +// hdfsOperations.uploadFile(fileToUpload, targetFolder, uploadedFileNameSpecific, user); +// break; +// +// case 4: +// System.out.print("Enter HDFS file path to download: "); +// String hdfsFilePath = scanner.nextLine(); +// System.out.print("Enter local path to save the downloaded file: "); +// String localDownloadPath = scanner.nextLine(); +// hdfsOperations.downloadFile(hdfsFilePath, localDownloadPath, user); +// break; +// +// case 5: +// System.out.print("Enter HDFS file path to delete: "); +// hdfsOperations.deleteFile(scanner.nextLine()); +// break; +// +// case 6: +// System.out.print("Enter HDFS folder path to delete: "); +// hdfsOperations.deleteFolder(scanner.nextLine()); +// break; +// +// case 7: +// System.out.print("Enter HDFS path to list files and folders: "); +// hdfsOperations.listFilesAndFolders(scanner.nextLine()); +// break; +// +// case 8: +// System.out.println("✅ Exiting..."); +// return; +// +// default: +// System.out.println("⚠️ Invalid option. Please try again."); +// } +// } catch (Exception e) { +// System.out.println("❌ Operation failed: " + e.getMessage()); +// e.printStackTrace(); +// } +// } +// } +// } +//} + + + + + + + + + + + + + + + + + + + + + //package com.skycrate.backend.skycrateBackend.controller; diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/dto/ResponseDTO.java b/src/main/java/com/skycrate/backend/skycrateBackend/dto/ResponseDTO.java new file mode 100644 index 0000000..2d9bc2c --- /dev/null +++ b/src/main/java/com/skycrate/backend/skycrateBackend/dto/ResponseDTO.java @@ -0,0 +1,27 @@ +package com.skycrate.backend.skycrateBackend.dto; + +public class ResponseDTO { + private String message; + private boolean success; + + public ResponseDTO(String message, boolean success) { + this.message = message; + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } +} diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/services/EncryptionUtil.java b/src/main/java/com/skycrate/backend/skycrateBackend/services/EncryptionUtil.java index 2fbe89b..dc09e89 100644 --- a/src/main/java/com/skycrate/backend/skycrateBackend/services/EncryptionUtil.java +++ b/src/main/java/com/skycrate/backend/skycrateBackend/services/EncryptionUtil.java @@ -1,11 +1,9 @@ package com.skycrate.backend.skycrateBackend.services; - -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; +import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.security.*; +import java.util.Arrays; public class EncryptionUtil { private static final String RSA_ALGORITHM = "RSA"; @@ -13,63 +11,148 @@ public class EncryptionUtil { private static final int RSA_KEY_SIZE = 2048; private static final int AES_KEY_SIZE = 256; + // Generate RSA Key Pair (Public & Private) public static KeyPair generateKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA_ALGORITHM); keyGen.initialize(RSA_KEY_SIZE); return keyGen.generateKeyPair(); } + // Encrypt data using AES (AES Key is encrypted using RSA) public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception { - // Generate a random AES key - KeyGenerator keyGen = KeyGenerator.getInstance(AES_ALGORITHM); - keyGen.init(AES_KEY_SIZE); - SecretKey aesKey = keyGen.generateKey(); + // Step 1: Generate AES Key + SecretKey aesKey = generateAESKey(); - // Encrypt the data with the AES key + // Step 2: Encrypt data using AES Cipher aesCipher = Cipher.getInstance(AES_ALGORITHM); aesCipher.init(Cipher.ENCRYPT_MODE, aesKey); byte[] encryptedData = aesCipher.doFinal(data); - // Encrypt the AES key with the RSA public key + // Step 3: Encrypt the AES key with RSA Cipher rsaCipher = Cipher.getInstance(RSA_ALGORITHM); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded()); - // Combine the encrypted AES key and the encrypted data - byte[] combined = new byte[encryptedAesKey.length + encryptedData.length + 4]; - System.arraycopy(encryptedAesKey, 0, combined, 0, encryptedAesKey.length); - System.arraycopy(encryptedData, 0, combined, encryptedAesKey.length, encryptedData.length); - // Store the length of the encrypted AES key at the beginning - combined[encryptedAesKey.length + encryptedData.length] = (byte) (encryptedAesKey.length >> 24); - combined[encryptedAesKey.length + encryptedData.length + 1] = (byte) (encryptedAesKey.length >> 16); - combined[encryptedAesKey.length + encryptedData.length + 2] = (byte) (encryptedAesKey.length >> 8); - combined[encryptedAesKey.length + encryptedData.length + 3] = (byte) (encryptedAesKey.length); + // Step 4: Combine encrypted AES key and encrypted data into one array + byte[] combined = new byte[4 + encryptedAesKey.length + encryptedData.length]; + + // First 4 bytes indicate the length of the AES encrypted key + combined[0] = (byte) (encryptedAesKey.length >> 24); + combined[1] = (byte) (encryptedAesKey.length >> 16); + combined[2] = (byte) (encryptedAesKey.length >> 8); + combined[3] = (byte) encryptedAesKey.length; + + // Copy AES Key and Encrypted Data into the combined array + System.arraycopy(encryptedAesKey, 0, combined, 4, encryptedAesKey.length); + System.arraycopy(encryptedData, 0, combined, 4 + encryptedAesKey.length, encryptedData.length); return combined; } - public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception { - // Read the length of the encrypted AES key - int aesKeyLength = ((encryptedData[encryptedData.length - 4] & 0xFF) << 24) | - ((encryptedData[encryptedData.length - 3] & 0xFF) << 16) | - ((encryptedData[encryptedData.length - 2] & 0xFF) << 8) | - (encryptedData[encryptedData.length - 1] & 0xFF); + // Decrypt data using RSA (AES Key is decrypted using RSA, then used for AES decryption) + public static byte[] decrypt(byte[] encryptedCombined, PrivateKey privateKey) throws Exception { + // Step 1: Extract AES Key length from the combined data + int aesKeyLength = ((encryptedCombined[0] & 0xFF) << 24) | + ((encryptedCombined[1] & 0xFF) << 16) | + ((encryptedCombined[2] & 0xFF) << 8) | + (encryptedCombined[3] & 0xFF); - // Extract the encrypted AES key and the encrypted data + // Step 2: Extract the encrypted AES key and encrypted data byte[] encryptedAesKey = new byte[aesKeyLength]; - byte[] encryptedDataBytes = new byte[encryptedData.length - aesKeyLength - 4]; - System.arraycopy(encryptedData, 0, encryptedAesKey, 0, aesKeyLength); - System.arraycopy(encryptedData, aesKeyLength, encryptedDataBytes, 0, encryptedDataBytes.length); + byte[] encryptedData = new byte[encryptedCombined.length - 4 - aesKeyLength]; - // Decrypt the AES key with the RSA private key + System.arraycopy(encryptedCombined, 4, encryptedAesKey, 0, aesKeyLength); + System.arraycopy(encryptedCombined, 4 + aesKeyLength, encryptedData, 0, encryptedData.length); + + // Step 3: Decrypt the AES key using RSA Cipher rsaCipher = Cipher.getInstance(RSA_ALGORITHM); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] aesKeyBytes = rsaCipher.doFinal(encryptedAesKey); SecretKey aesKey = new SecretKeySpec(aesKeyBytes, AES_ALGORITHM); - // Decrypt the data with the AES key + // Step 4: Decrypt the data using AES Cipher aesCipher = Cipher.getInstance(AES_ALGORITHM); aesCipher.init(Cipher.DECRYPT_MODE, aesKey); - return aesCipher.doFinal(encryptedDataBytes); + return aesCipher.doFinal(encryptedData); + } + + // Generate a random AES key + private static SecretKey generateAESKey() throws NoSuchAlgorithmException { + KeyGenerator keyGen = KeyGenerator.getInstance(AES_ALGORITHM); + keyGen.init(AES_KEY_SIZE); + return keyGen.generateKey(); } } +// +//import javax.crypto.Cipher; +//import javax.crypto.KeyGenerator; +//import javax.crypto.SecretKey; +//import javax.crypto.spec.SecretKeySpec; +//import java.security.*; +// +//public class EncryptionUtil { +// private static final String RSA_ALGORITHM = "RSA"; +// private static final String AES_ALGORITHM = "AES"; +// private static final int RSA_KEY_SIZE = 2048; +// private static final int AES_KEY_SIZE = 256; +// +// public static KeyPair generateKeyPair() throws NoSuchAlgorithmException { +// KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA_ALGORITHM); +// keyGen.initialize(RSA_KEY_SIZE); +// return keyGen.generateKeyPair(); +// } +// +// public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception { +// // Generate a random AES key +// KeyGenerator keyGen = KeyGenerator.getInstance(AES_ALGORITHM); +// keyGen.init(AES_KEY_SIZE); +// SecretKey aesKey = keyGen.generateKey(); +// +// // Encrypt the data with the AES key +// Cipher aesCipher = Cipher.getInstance(AES_ALGORITHM); +// aesCipher.init(Cipher.ENCRYPT_MODE, aesKey); +// byte[] encryptedData = aesCipher.doFinal(data); +// +// // Encrypt the AES key with the RSA public key +// Cipher rsaCipher = Cipher.getInstance(RSA_ALGORITHM); +// rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); +// byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded()); +// +// // Combine the encrypted AES key and the encrypted data +// byte[] combined = new byte[encryptedAesKey.length + encryptedData.length + 4]; +// System.arraycopy(encryptedAesKey, 0, combined, 0, encryptedAesKey.length); +// System.arraycopy(encryptedData, 0, combined, encryptedAesKey.length, encryptedData.length); +// // Store the length of the encrypted AES key at the beginning +// combined[encryptedAesKey.length + encryptedData.length] = (byte) (encryptedAesKey.length >> 24); +// combined[encryptedAesKey.length + encryptedData.length + 1] = (byte) (encryptedAesKey.length >> 16); +// combined[encryptedAesKey.length + encryptedData.length + 2] = (byte) (encryptedAesKey.length >> 8); +// combined[encryptedAesKey.length + encryptedData.length + 3] = (byte) (encryptedAesKey.length); +// +// return combined; +// } +// +// public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception { +// // Read the length of the encrypted AES key +// int aesKeyLength = ((encryptedData[encryptedData.length - 4] & 0xFF) << 24) | +// ((encryptedData[encryptedData.length - 3] & 0xFF) << 16) | +// ((encryptedData[encryptedData.length - 2] & 0xFF) << 8) | +// (encryptedData[encryptedData.length - 1] & 0xFF); +// +// // Extract the encrypted AES key and the encrypted data +// byte[] encryptedAesKey = new byte[aesKeyLength]; +// byte[] encryptedDataBytes = new byte[encryptedData.length - aesKeyLength - 4]; +// System.arraycopy(encryptedData, 0, encryptedAesKey, 0, aesKeyLength); +// System.arraycopy(encryptedData, aesKeyLength, encryptedDataBytes, 0, encryptedDataBytes.length); +// +// // Decrypt the AES key with the RSA private key +// Cipher rsaCipher = Cipher.getInstance(RSA_ALGORITHM); +// rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); +// byte[] aesKeyBytes = rsaCipher.doFinal(encryptedAesKey); +// SecretKey aesKey = new SecretKeySpec(aesKeyBytes, AES_ALGORITHM); +// +// // Decrypt the data with the AES key +// Cipher aesCipher = Cipher.getInstance(AES_ALGORITHM); +// aesCipher.init(Cipher.DECRYPT_MODE, aesKey); +// return aesCipher.doFinal(encryptedDataBytes); +// } +//} diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/services/HDFSOperations.java b/src/main/java/com/skycrate/backend/skycrateBackend/services/HDFSOperations.java index 7fe58f5..bd82cc9 100644 --- a/src/main/java/com/skycrate/backend/skycrateBackend/services/HDFSOperations.java +++ b/src/main/java/com/skycrate/backend/skycrateBackend/services/HDFSOperations.java @@ -1,106 +1,283 @@ package com.skycrate.backend.skycrateBackend.services; - import com.skycrate.backend.skycrateBackend.config.HDFSConfig; -import com.skycrate.backend.skycrateBackend.dto.User; -import org.apache.hadoop.fs.*; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.ArrayList; +import java.util.List; @Service public class HDFSOperations { - public static void uploadFile(String localPath, String hdfsPath, String uploadedFileName, User user) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - byte[] data = Files.readAllBytes(Paths.get(localPath)); // Read file as bytes - byte[] encryptedData = EncryptionUtil.encrypt(data, user.getKeyPair().getPublic()); - // Save encryptedData to a temporary file and upload it - String tempFilePath = localPath + ".enc"; - Files.write(Paths.get(tempFilePath), encryptedData); // Write bytes to temp file + public void uploadFile(String localPath, String hdfsPath, String uploadedFileName, String username) { + try { + FileSystem fs = HDFSConfig.getHDFS(); + byte[] data = Files.readAllBytes(Paths.get(localPath)); // Read file as bytes - // Construct the final HDFS path using the provided uploaded file name - String finalHdfsPath = hdfsPath.endsWith("/") ? hdfsPath + uploadedFileName : hdfsPath + "/" + uploadedFileName; + // Encrypt file (consider adding encryption here as needed) + byte[] encryptedData = data; - fs.copyFromLocalFile(new Path(tempFilePath), new Path(finalHdfsPath)); - System.out.println("✅ File uploaded: " + finalHdfsPath); + String tempFilePath = localPath + ".enc"; + Files.write(Paths.get(tempFilePath), encryptedData); - // Clean up temporary file - Files.delete(Paths.get(tempFilePath)); - } + String finalHdfsPath = hdfsPath.endsWith("/") ? hdfsPath + uploadedFileName : hdfsPath + "/" + uploadedFileName; + fs.copyFromLocalFile(new Path(tempFilePath), new Path(finalHdfsPath)); - public static void downloadFile(String hdfsPath, String localPath, User user) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - String tempFilePath = localPath + ".enc"; - - fs.copyToLocalFile(new Path(hdfsPath), new Path(tempFilePath)); - - // Read the encrypted file as bytes - byte[] encryptedData = Files.readAllBytes(Paths.get(tempFilePath)); - byte[] decryptedData = EncryptionUtil.decrypt(encryptedData, user.getKeyPair().getPrivate()); - - Files.write(Paths.get(localPath), decryptedData); // Write decrypted bytes to local file - System.out.println("✅ File downloaded: " + localPath); - - // Clean up temporary file - Files.delete(Paths.get(tempFilePath)); - } - - public static void createFolder(String hdfsPath) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - Path path = new Path(hdfsPath); - if (!fs.exists(path)) { - fs.mkdirs(path); - System.out.println("✅ Folder created: " + hdfsPath); - } else { - System.out.println("⚠️ Folder already exists: " + hdfsPath); + Files.delete(Paths.get(tempFilePath)); + } catch (IOException e) { + // Handle I/O exception and log the error + throw new RuntimeException("Failed to upload file due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + // Catch any other exceptions + throw new RuntimeException("Failed to upload file: " + e.getMessage(), e); } } - public static void deleteFile(String hdfsFilePath) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - Path path = new Path(hdfsFilePath); - if (fs.exists(path)) { - fs.delete(path, false); // false means do not recursively delete - System.out.println("✅ File deleted: " + hdfsFilePath); - } else { - System.out.println("⚠️ File does not exist: " + hdfsFilePath); + public void downloadFile(String hdfsPath, String localPath, String username) { + try { + FileSystem fs = HDFSConfig.getHDFS(); + String tempFilePath = localPath + ".enc"; + + fs.copyToLocalFile(new Path(hdfsPath), new Path(tempFilePath)); + + byte[] encryptedData = Files.readAllBytes(Paths.get(tempFilePath)); + byte[] decryptedData = encryptedData; // Decrypt if needed + + Files.write(Paths.get(localPath), decryptedData); + Files.delete(Paths.get(tempFilePath)); + } catch (IOException e) { + // Handle I/O exception and log the error + throw new RuntimeException("Failed to download file due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + // Catch any other exceptions + throw new RuntimeException("Failed to download file: " + e.getMessage(), e); } } - public static void deleteFolder(String hdfsFolderPath) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - Path path = new Path(hdfsFolderPath); - if (fs.exists(path)) { - fs.delete(path, true); // true means recursively delete - System.out.println("✅ Folder deleted: " + hdfsFolderPath); - } else { - System.out.println("⚠️ Folder does not exist: " + hdfsFolderPath); + public void createFolder(String hdfsPath) { + try { + FileSystem fs = HDFSConfig.getHDFS(); + Path path = new Path(hdfsPath); + if (!fs.exists(path)) { + fs.mkdirs(path); + } + } catch (IOException e) { + // Handle I/O exception and log the error + throw new RuntimeException("Failed to create folder in HDFS due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + // Catch any other exceptions + throw new RuntimeException("Failed to create folder: " + e.getMessage(), e); } } - public static void listFilesAndFolders(String hdfsPath) throws Exception { - FileSystem fs = HDFSConfig.getHDFS(); - Path path = new Path(hdfsPath); - - if (!fs.exists(path)) { - System.out.println("⚠️ Path does not exist: " + hdfsPath); - return; + public void deleteFile(String hdfsFilePath) { + try { + FileSystem fs = HDFSConfig.getHDFS(); + Path path = new Path(hdfsFilePath); + if (fs.exists(path)) { + fs.delete(path, false); + } + } catch (IOException e) { + // Handle I/O exception and log the error + throw new RuntimeException("Failed to delete file due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + // Catch any other exceptions + throw new RuntimeException("Failed to delete file: " + e.getMessage(), e); } - - System.out.println("Listing files and folders in: " + hdfsPath); - listFilesAndFoldersRecursively(fs, path, ""); } - private static void listFilesAndFoldersRecursively(FileSystem fs, Path path, String indent) throws IOException { + public void deleteFolder(String hdfsFolderPath) { + try { + FileSystem fs = HDFSConfig.getHDFS(); + Path path = new Path(hdfsFolderPath); + if (fs.exists(path)) { + fs.delete(path, true); + } + } catch (IOException e) { + // Handle I/O exception and log the error + throw new RuntimeException("Failed to delete folder due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + // Catch any other exceptions + throw new RuntimeException("Failed to delete folder: " + e.getMessage(), e); + } + } + + public List listFilesAndFolders(String hdfsPath) { + List results = new ArrayList<>(); + try { + FileSystem fs = HDFSConfig.getHDFS(); + Path path = new Path(hdfsPath); + + if (fs.exists(path)) { + listFilesAndFoldersRecursively(fs, path, "", results); + } else { + throw new RuntimeException("HDFS path does not exist: " + hdfsPath); + } + } catch (IOException e) { + throw new RuntimeException("Failed to list files and folders due to I/O issue: " + e.getMessage(), e); + } catch (Exception e) { + throw new RuntimeException("Failed to list files and folders: " + e.getMessage(), e); + } + + return results; + } + + private void listFilesAndFoldersRecursively(FileSystem fs, Path path, String indent, List results) throws IOException { FileStatus[] fileStatuses = fs.listStatus(path); for (FileStatus fileStatus : fileStatuses) { - System.out.println(indent + (fileStatus.isDirectory() ? "📁 " : "📄 ") + fileStatus.getPath().getName()); + String entry = indent + (fileStatus.isDirectory() ? "📁 " : "📄 ") + fileStatus.getPath().getName(); + results.add(entry); + if (fileStatus.isDirectory()) { - listFilesAndFoldersRecursively(fs, fileStatus.getPath(), indent + " "); // Indent for subdirectories + listFilesAndFoldersRecursively(fs, fileStatus.getPath(), indent + " ", results); } } } + + +// public void listFilesAndFolders(String hdfsPath) { +// try { +// FileSystem fs = HDFSConfig.getHDFS(); +// Path path = new Path(hdfsPath); +// +// if (fs.exists(path)) { +// listFilesAndFoldersRecursively(fs, path, ""); +// } +// } catch (IOException e) { +// // Handle I/O exception and log the error +// throw new RuntimeException("Failed to list files and folders due to I/O issue: " + e.getMessage(), e); +// } catch (Exception e) { +// // Catch any other exceptions +// throw new RuntimeException("Failed to list files and folders: " + e.getMessage(), e); +// } +// } +// +// private void listFilesAndFoldersRecursively(FileSystem fs, Path path, String indent) throws IOException { +// FileStatus[] fileStatuses = fs.listStatus(path); +// for (FileStatus fileStatus : fileStatuses) { +// System.out.println(indent + (fileStatus.isDirectory() ? "📁 " : "📄 ") + fileStatus.getPath().getName()); +// if (fileStatus.isDirectory()) { +// listFilesAndFoldersRecursively(fs, fileStatus.getPath(), indent + " "); +// } +// } +// } } + + + + +//package com.skycrate.backend.skycrateBackend.services; +// +// +//import com.skycrate.backend.skycrateBackend.config.HDFSConfig; +//import com.skycrate.backend.skycrateBackend.dto.User; +//import org.apache.hadoop.fs.*; +//import org.springframework.stereotype.Service; +// +//import java.io.IOException; +//import java.nio.file.Files; +//import java.nio.file.Paths; +// +//@Service +//public class HDFSOperations { +// public static void uploadFile(String localPath, String hdfsPath, String uploadedFileName, User user) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// byte[] data = Files.readAllBytes(Paths.get(localPath)); // Read file as bytes +// byte[] encryptedData = EncryptionUtil.encrypt(data, user.getKeyPair().getPublic()); +// +// // Save encryptedData to a temporary file and upload it +// String tempFilePath = localPath + ".enc"; +// Files.write(Paths.get(tempFilePath), encryptedData); // Write bytes to temp file +// +// // Construct the final HDFS path using the provided uploaded file name +// String finalHdfsPath = hdfsPath.endsWith("/") ? hdfsPath + uploadedFileName : hdfsPath + "/" + uploadedFileName; +// +// fs.copyFromLocalFile(new Path(tempFilePath), new Path(finalHdfsPath)); +// System.out.println("✅ File uploaded: " + finalHdfsPath); +// +// // Clean up temporary file +// Files.delete(Paths.get(tempFilePath)); +// } +// +// public static void downloadFile(String hdfsPath, String localPath, User user) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// String tempFilePath = localPath + ".enc"; +// +// fs.copyToLocalFile(new Path(hdfsPath), new Path(tempFilePath)); +// +// // Read the encrypted file as bytes +// byte[] encryptedData = Files.readAllBytes(Paths.get(tempFilePath)); +// byte[] decryptedData = EncryptionUtil.decrypt(encryptedData, user.getKeyPair().getPrivate()); +// +// Files.write(Paths.get(localPath), decryptedData); // Write decrypted bytes to local file +// System.out.println("✅ File downloaded: " + localPath); +// +// // Clean up temporary file +// Files.delete(Paths.get(tempFilePath)); +// } +// +// public static void createFolder(String hdfsPath) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// Path path = new Path(hdfsPath); +// if (!fs.exists(path)) { +// fs.mkdirs(path); +// System.out.println("✅ Folder created: " + hdfsPath); +// } else { +// System.out.println("⚠️ Folder already exists: " + hdfsPath); +// } +// } +// +// public static void deleteFile(String hdfsFilePath) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// Path path = new Path(hdfsFilePath); +// if (fs.exists(path)) { +// fs.delete(path, false); // false means do not recursively delete +// System.out.println("✅ File deleted: " + hdfsFilePath); +// } else { +// System.out.println("⚠️ File does not exist: " + hdfsFilePath); +// } +// } +// +// public static void deleteFolder(String hdfsFolderPath) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// Path path = new Path(hdfsFolderPath); +// if (fs.exists(path)) { +// fs.delete(path, true); // true means recursively delete +// System.out.println("✅ Folder deleted: " + hdfsFolderPath); +// } else { +// System.out.println("⚠️ Folder does not exist: " + hdfsFolderPath); +// } +// } +// +// public static void listFilesAndFolders(String hdfsPath) throws Exception { +// FileSystem fs = HDFSConfig.getHDFS(); +// Path path = new Path(hdfsPath); +// +// if (!fs.exists(path)) { +// System.out.println("⚠️ Path does not exist: " + hdfsPath); +// return; +// } +// +// System.out.println("Listing files and folders in: " + hdfsPath); +// listFilesAndFoldersRecursively(fs, path, ""); +// } +// +// private static void listFilesAndFoldersRecursively(FileSystem fs, Path path, String indent) throws IOException { +// FileStatus[] fileStatuses = fs.listStatus(path); +// for (FileStatus fileStatus : fileStatuses) { +// System.out.println(indent + (fileStatus.isDirectory() ? "📁 " : "📄 ") + fileStatus.getPath().getName()); +// if (fileStatus.isDirectory()) { +// listFilesAndFoldersRecursively(fs, fileStatus.getPath(), indent + " "); // Indent for subdirectories +// } +// } +// } +//} diff --git a/src/main/java/com/skycrate/backend/skycrateBackend/utils/KeyUtil.java b/src/main/java/com/skycrate/backend/skycrateBackend/utils/KeyUtil.java new file mode 100644 index 0000000..c4bef78 --- /dev/null +++ b/src/main/java/com/skycrate/backend/skycrateBackend/utils/KeyUtil.java @@ -0,0 +1,26 @@ +package com.skycrate.backend.skycrateBackend.utils; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +public class KeyUtil { + public static PrivateKey getPrivateKeyForUser(String username) throws Exception { + Path path = Paths.get("keys", username + "_private.key"); + byte[] bytes = Files.readAllBytes(path); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes); + return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + } + + public static PublicKey getPublicKeyForUser(String username) throws Exception { + Path path = Paths.get("keys", username + "_public.key"); + byte[] bytes = Files.readAllBytes(path); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); + return KeyFactory.getInstance("RSA").generatePublic(keySpec); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 70b807c..5418dd0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,9 @@ spring.application.name=skycrateBackend +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB + + spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.datasource.username=kshitij spring.datasource.password=loa_dngLLA8729 diff --git a/tmp/Handout-A5.pdf b/tmp/Handout-A5.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1660c1f30a50ce3a4fab76b5912604e09b0c8547 GIT binary patch literal 60219 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 literal 0 HcmV?d00001