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 0000000..1660c1f Binary files /dev/null and b/tmp/Handout-A5.pdf differ