6 Commits

Author SHA1 Message Date
Kshitij c20b33a305 Deleted tmp folder. This branch is now on hold. tmp folders are no longer being produced. All APIs hopefully work in this one, didn't test tho 🤞 2025-04-17 23:30:52 +05:30
vedang29 a1dc9a840e Removed tmp folder while downloading 2025-04-15 22:47:28 +05:30
vedang29 508405077d Removed tmp folder while uploading 2025-04-15 22:35:44 +05:30
vedang29 36acd75eb3 Merge pull request #2 from kshitij-ka/main 2025-04-15 21:44:05 +05:30
Kshitij 5225174d51 Changed port from 8081 to 8080. 2025-04-15 21:24:17 +05:30
Kshitij 471d03d0b6 Deleted empty test file. 2025-04-15 21:24:02 +05:30
12 changed files with 244 additions and 439 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+10
View File
@@ -144,6 +144,16 @@
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- NEWLY ADDED DEPENDENCY FOR DOWNLOAD ENDPOINT-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
@@ -1,15 +1,11 @@
package com.skycrate.backend.skycrateBackend.controller;
import com.skycrate.backend.skycrateBackend.config.HDFSConfig;
import com.skycrate.backend.skycrateBackend.dto.ResponseDTO;
import com.skycrate.backend.skycrateBackend.models.User;
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
import com.skycrate.backend.skycrateBackend.services.EncryptionUtil;
import com.skycrate.backend.skycrateBackend.services.HDFSOperations;
import com.skycrate.backend.skycrateBackend.utils.KeyUtil;
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
import org.apache.hadoop.fs.FileSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -21,7 +17,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;
@@ -29,11 +24,6 @@ import java.util.List;
import org.springframework.core.io.FileSystemResource; // For FileSystemResource
import org.springframework.core.io.Resource; // For Resource
import org.springframework.http.HttpHeaders; // For HttpHeaders
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.File; // For java.io.File
import static com.skycrate.backend.skycrateBackend.utils.KeyUtil.getPrivateKeyForUser;
@@ -45,10 +35,6 @@ public class HDFScontroller {
private final HDFSOperations hdfsOperations;
@Autowired
private UserRepository userRepository;
@Autowired
public HDFScontroller(HDFSOperations hdfsOperations) {
this.hdfsOperations = hdfsOperations;
@@ -65,186 +51,107 @@ public class HDFScontroller {
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 {
// Retrieve the user from the database using the username
User user = userRepository.findByUsername(username).orElseThrow(() -> new RuntimeException("User not found"));
// Get the public key from the user entity
byte[] publicKeyBytes = user.getPublicKey();
PublicKey publicKey = RSAKeyUtil.getPublicKeyFromBytes(publicKeyBytes);
// Encrypt the file content using the public key
byte[] encryptedData = encryptFile(file, publicKey);
// Upload the encrypted file to HDFS
hdfsOperations.uploadFile(encryptedData, 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);
}
//
// @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);
// }
// }
@PostMapping("/uploadFile")
public ResponseDTO uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam String hdfsPath,
@RequestParam String uploadedFileName,
@RequestParam String username) {
try {
// Upload file directly to HDFS without saving locally
hdfsOperations.uploadFile(file, hdfsPath, uploadedFileName, username);
return new ResponseDTO("File uploaded successfully", true);
} catch (Exception e) {
e.printStackTrace();
return new ResponseDTO("Failed to upload file to HDFS: " + e.getMessage(), false);
}
}
// Helper method to encrypt the file content using RSA encryption
private byte[] encryptFile(MultipartFile file, PublicKey publicKey) throws Exception {
// Step 1: Generate a random AES key
SecretKey aesKey = generateAESKey();
// Step 2: Encrypt the file data using AES
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] fileData = file.getBytes();
byte[] encryptedData = aesCipher.doFinal(fileData);
//
// 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
// }
// Step 3: Encrypt the AES key with RSA
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded());
// Step 4: Combine the encrypted AES key and the encrypted data
byte[] combined = new byte[4 + encryptedAesKey.length + encryptedData.length];
combined[0] = (byte) (encryptedAesKey.length >> 24);
combined[1] = (byte) (encryptedAesKey.length >> 16);
combined[2] = (byte) (encryptedAesKey.length >> 8);
combined[3] = (byte) encryptedAesKey.length;
System.arraycopy(encryptedAesKey, 0, combined, 4, encryptedAesKey.length);
System.arraycopy(encryptedData, 0, combined, 4 + encryptedAesKey.length, encryptedData.length);
return combined;
}
// Generate a random AES key
private SecretKey generateAESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // Use 256 bits for AES
return keyGen.generateKey();
}
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 ResponseEntity<?> downloadFile(
// @RequestParam String hdfsPath,
// @RequestParam String username) {
// try {
// // Define a temporary local path to download the file
// String localPath = "/app/tmp/downloaded/" + new File(hdfsPath).getName(); // Adjust the path as needed
//
// // Download the file from HDFS to the local path
// hdfsOperations.downloadFile(hdfsPath, localPath, username);
//
// // Create a File object for the downloaded file
// File file = new File(localPath);
// if (!file.exists()) {
// return ResponseEntity.status(HttpStatus.NOT_FOUND)
// .body(new ResponseDTO("File not found", false));
// }
//
// // Create a Resource from the file
// Resource resource = new FileSystemResource(file);
// return ResponseEntity.ok()
// .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
// .body(resource);
// } catch (Exception e) {
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(new ResponseDTO("Failed to download file: " + e.getMessage(), false));
// }
// }
@PostMapping("/downloadFile")
public ResponseEntity<Resource> downloadFile(
@RequestParam String hdfsEncPath,
public ResponseEntity<?> downloadFile(
@RequestParam String hdfsPath,
@RequestParam String username) {
try {
// Extract the file name and extension
String encFileName = new File(hdfsEncPath).getName();
String originalFileName = encFileName.replace(".enc", "");
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
String fileName = new File(hdfsPath).getName();
InputStreamResource resource = hdfsOperations.downloadFile(hdfsPath, username);
// Define local decrypted file path
String localDecryptedPath = "/SkyCrate/downloaded/" + originalFileName;
// Define HDFS paths for encrypted file
String encFilePath = "/SkyCrate/downloaded/" + encFileName;
FileSystem fs = HDFSConfig.getHDFS();
// Download encrypted file from HDFS
fs.copyToLocalFile(new org.apache.hadoop.fs.Path(hdfsEncPath), new org.apache.hadoop.fs.Path(encFilePath));
// Retrieve the RSA private key for the user
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("User not found"));
PrivateKey privateKey = RSAKeyUtil.getPrivateKeyFromBytes(user.getPrivateKey());
// Read the encrypted file content
byte[] encryptedFileContent = Files.readAllBytes(Paths.get(encFilePath));
// Step 1: Extract the AES key length from the combined data
int aesKeyLength = ((encryptedFileContent[0] & 0xFF) << 24) |
((encryptedFileContent[1] & 0xFF) << 16) |
((encryptedFileContent[2] & 0xFF) << 8) |
(encryptedFileContent[3] & 0xFF);
// Step 2: Extract the encrypted AES key and encrypted data
byte[] encryptedAesKey = new byte[aesKeyLength];
byte[] encryptedData = new byte[encryptedFileContent.length - 4 - aesKeyLength];
System.arraycopy(encryptedFileContent, 4, encryptedAesKey, 0, aesKeyLength);
System.arraycopy(encryptedFileContent, 4 + aesKeyLength, encryptedData, 0, encryptedData.length);
// Step 3: Decrypt the AES key using RSA
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = rsaCipher.doFinal(encryptedAesKey);
// Create the AES key
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");
// Step 4: Decrypt the data using AES
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
// Decrypt the file content using the provided decrypt method
// byte[] decryptedFileContent = RSAKeyUtil.decrypt(encryptedFileContent, privateKey);
byte[] decryptedFileContent = aesCipher.doFinal(encryptedData);
// Write the decrypted content to the original file
Files.write(Paths.get(localDecryptedPath + "." + fileExtension), decryptedFileContent);
// Log the file creation
if (Files.exists(Paths.get(localDecryptedPath + "." + fileExtension))) {
System.out.println("File created successfully at: " + localDecryptedPath + "." + fileExtension);
} else {
System.out.println("Failed to create file at: " + localDecryptedPath + "." + fileExtension);
}
// Create the decrypted file resource
File decryptedFile = new File(localDecryptedPath + "." + fileExtension);
Resource resource = new FileSystemResource(decryptedFile);
// Return the file as a response
return ResponseEntity.ok()
.contentLength(decryptedFile.length())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + decryptedFile.getName() + "\"")
.body(resource);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(null);
}
}
public void initializeKeysForUser(String username) {
try {
// Check if the public key file exists
Path publicKeyPath = Paths.get("C:\\Users\\sonal\\OneDrive\\Desktop\\SkyCrate\\Skycrate\\keys", username + "_public.key");
if (!Files.exists(publicKeyPath)) {
// Generate and store keys if they do not exist
KeyUtil.generateAndStoreKeyPair(username);
}
} catch (Exception e) {
e.printStackTrace();
.body(new ResponseDTO("Failed to download file: " + e.getMessage(), false));
}
}
@@ -1,4 +1,4 @@
package com.skycrate.backend.skycrateBackend.models;
package com.skycrate.backend.skycrateBackend.models;
import java.time.LocalDateTime;
import java.util.Collection;
@@ -6,6 +6,7 @@ import java.util.Date;
import java.util.List;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -14,7 +15,7 @@ import jakarta.persistence.*;
@Table(name = "users")
@Entity
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
@@ -23,38 +24,49 @@ public class User implements UserDetails {
@Column(nullable = false)
private String username;
/*
//Optional feature might add later
@Column(name = "verification_code")
private String verificationCode;
@Column(name ="verification_expiry")
private LocalDateTime verificationExpiry;
*/
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
// ✅ Add RSA key fields
@Lob
@Column(name = "public_key", columnDefinition = "BLOB")
private byte[] publicKey;
public User(){
}
@Lob
@Column(name = "private_key", columnDefinition = "BLOB")
private byte[] privateKey;
public User(String firstname,String lastname,String email,String password){
this.username=firstname+lastname;
this.email=email;
this.password=password;
}
@CreationTimestamp
@Column(updatable = false, name = "created_at")
private Date createdAt;
public User() {}
public User(String firstname, String lastname, String email, String password) {
this.username = firstname + lastname;
this.email = email;
this.password = password;
@Override
public Collection<? extends GrantedAuthority> getAuthorities(){
return List.of();
}
// ⬇️ Required by Spring Security
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
public String getPassword() {
return password;
}
@Override
@@ -62,11 +74,6 @@ public class User implements UserDetails {
return email;
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean isAccountNonExpired() {
return true;
@@ -86,8 +93,6 @@ public class User implements UserDetails {
public boolean isEnabled() {
return true;
}
// ⬇️ Getters and Setters
public Integer getId() {
return id;
}
@@ -96,11 +101,13 @@ public class User implements UserDetails {
this.id = id;
}
public void setFullname(String firstname, String lastname) {
this.username = firstname + lastname;
public void setFullname(String firstname,String lastname) {
this.username=firstname+lastname;
}
public String getFullname() {
public String getFullname(String firstname,String lastname){
return this.username;
}
@@ -119,21 +126,4 @@ public class User implements UserDetails {
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
// ✅ Getters and setters for RSA keys
public byte[] getPublicKey() {
return publicKey;
}
public void setPublicKey(byte[] publicKey) {
this.publicKey = publicKey;
}
public byte[] getPrivateKey() {
return privateKey;
}
public void setPrivateKey(byte[] privateKey) {
this.privateKey = privateKey;
}
}
@@ -5,8 +5,6 @@ import org.springframework.data.repository.CrudRepository;
import com.skycrate.backend.skycrateBackend.models.User;
public interface UserRepository extends CrudRepository<User,Integer> {
Optional<User> findByEmail(String email);
// Custom query method to find user by username
Optional<User> findByUsername(String username);
/*
// might use later
Optional<User> findByVerificationCode(String verificationCode);
@@ -9,49 +9,37 @@ import com.skycrate.backend.skycrateBackend.dto.LoginUserDto;
import com.skycrate.backend.skycrateBackend.dto.RegisterUserDto;
import com.skycrate.backend.skycrateBackend.models.User;
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
@Service
public class AuthenticationService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
public AuthenticationService(UserRepository userRepository, AuthenticationManager authenticationManager, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager;
public AuthenticationService( UserRepository userRepository, AuthenticationManager authenticationManager , PasswordEncoder passwordEncoder){
this.userRepository=userRepository;
this.passwordEncoder=passwordEncoder;
this.authenticationManager=authenticationManager;
}
public User signUp(RegisterUserDto inputUser) {
User user = new User(
inputUser.getFirstname(),
inputUser.getLastname(),
inputUser.getEmail(),
passwordEncoder.encode(inputUser.getPassword())
);
public User signUp(RegisterUserDto inputuser){
User user=new User(inputuser.getFirstname(),inputuser.getLastname(),inputuser.getEmail(),passwordEncoder.encode(inputuser.getPassword()));
/*
User user = new User()
.setFullname(inputuser.getFirstname(),inputuser.getLastname())
.setEmail(inputuser.getEmail())
.setPassword(passwordEncoder.encode(inputuser.getPassword()));
*/
try {
KeyPair keyPair = RSAKeyUtil.generateKeyPair();
user.setPublicKey(keyPair.getPublic().getEncoded());
user.setPrivateKey(keyPair.getPrivate().getEncoded());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Failed to generate RSA key pair", e);
}
return userRepository.save(user);
return userRepository.save(user) ;
}
public User authenticate(LoginUserDto inputUser) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(inputUser.getEmail(), inputUser.getPassword())
);
public User authenticate(LoginUserDto inputuser){
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(inputuser.getEmail()
, inputuser.getPassword()));
return userRepository.findByEmail(inputuser.getEmail()).orElseThrow();
return userRepository.findByEmail(inputUser.getEmail())
.orElseThrow(() -> new RuntimeException("User not found"));
}
}
}
@@ -23,13 +23,13 @@ public class EncryptionUtil {
// Step 1: Generate AES Key
SecretKey aesKey = generateAESKey();
// Encrypt data using AES
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 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 RSA
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// 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());
@@ -65,15 +65,13 @@ public class EncryptionUtil {
System.arraycopy(encryptedCombined, 4 + aesKeyLength, encryptedData, 0, encryptedData.length);
// Step 3: Decrypt the AES key using RSA
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Cipher rsaCipher = Cipher.getInstance(RSA_ALGORITHM);
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = rsaCipher.doFinal(encryptedAesKey);
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, AES_ALGORITHM);
// Create AES key
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");
// Decrypt the data using AES
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// Step 4: Decrypt the data using AES
Cipher aesCipher = Cipher.getInstance(AES_ALGORITHM);
aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
return aesCipher.doFinal(encryptedData);
}
@@ -1,16 +1,12 @@
package com.skycrate.backend.skycrateBackend.services;
import com.skycrate.backend.skycrateBackend.config.HDFSConfig;
import com.skycrate.backend.skycrateBackend.models.User;
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.skycrate.backend.skycrateBackend.utils.KeyUtil;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.fs.*;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
@@ -18,7 +14,6 @@ import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -32,94 +27,98 @@ import java.util.List;
@Service
public class HDFSOperations {
private final UserRepository userRepository;
@Autowired
public HDFSOperations(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 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
//
// // Encrypt file (consider adding encryption here as needed)
// byte[] encryptedData = data;
//
// String tempFilePath = localPath + ".enc";
// Files.write(Paths.get(tempFilePath), encryptedData);
//
// String finalHdfsPath = hdfsPath.endsWith("/") ? hdfsPath + uploadedFileName : hdfsPath + "/" + uploadedFileName;
// fs.copyFromLocalFile(new Path(tempFilePath), new Path(finalHdfsPath));
//
// 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 void uploadFile(byte[] fileData, String hdfsPath, String uploadedFileName, String username) {
public void uploadFile(MultipartFile file, String hdfsPath, String uploadedFileName, String username) {
try {
FileSystem fs = HDFSConfig.getHDFS();
// Create an InputStream from the byte array
ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
// Encrypt file data if needed (currently direct pass-through)
byte[] fileBytes = file.getBytes(); // directly get bytes from MultipartFile
byte[] encryptedData = fileBytes;
// Prepare the path for HDFS
// Define final HDFS file path
String finalHdfsPath = hdfsPath.endsWith("/") ? hdfsPath + uploadedFileName : hdfsPath + "/" + uploadedFileName;
// Upload the file directly to HDFS from the InputStream
Path hdfsFilePath = new Path(finalHdfsPath);
FSDataOutputStream outputStream = fs.create(hdfsFilePath);
IOUtils.copyBytes(inputStream, outputStream, 4096, true);
// Write encrypted bytes directly to HDFS
Path hdfsDestPath = new Path(finalHdfsPath);
try (FSDataOutputStream outputStream = fs.create(hdfsDestPath, true)) {
outputStream.write(encryptedData);
}
} catch (IOException e) {
// Handle I/O exception and log the error
throw new RuntimeException("Failed to upload file to HDFS: " + e.getMessage(), e);
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 to HDFS: " + e.getMessage(), e);
throw new RuntimeException("Failed to upload file: " + e.getMessage(), e);
}
}
public void downloadFile(String hdfsEncPath, String localPathWithoutExt, String username) {
// 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 InputStreamResource downloadFile(String hdfsPath, String username) {
try {
FileSystem fs = HDFSConfig.getHDFS();
// Extract file name and extension
String encFileName = new File(hdfsEncPath).getName();
String originalFileName = encFileName.replace(".enc", "");
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
// Read encrypted file directly from HDFS
FSDataInputStream hdfsInputStream = fs.open(new Path(hdfsPath));
String fullDecryptedPath = localPathWithoutExt + "/" + originalFileName;
String encFilePath = fullDecryptedPath + ".enc";
String keyFilePath = fullDecryptedPath + ".key";
// Optional: If decryption is needed, read bytes, decrypt, and wrap in ByteArrayInputStream
byte[] encryptedData = IOUtils.toByteArray(hdfsInputStream);
byte[] decryptedData = encryptedData; // Apply decryption if needed
// Download encrypted file and AES key from HDFS
fs.copyToLocalFile(new Path(hdfsEncPath), new Path(encFilePath));
fs.copyToLocalFile(new Path(hdfsEncPath.replace(".enc", ".key")), new Path(keyFilePath));
// Read the encrypted AES key
byte[] encryptedAesKey = Files.readAllBytes(Paths.get(keyFilePath));
System.out.println("Length of encrypted AES key: " + encryptedAesKey.length);
// Retrieve the RSA private key for the user
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("User not found"));
PrivateKey privateKey = RSAKeyUtil.getPrivateKeyFromBytes(user.getPrivateKey());
Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = rsaCipher.doFinal(encryptedAesKey);
// Ensure valid AES key length
if (aesKeyBytes.length != 16 && aesKeyBytes.length != 24 && aesKeyBytes.length != 32) {
throw new RuntimeException("Invalid AES key length: " + aesKeyBytes.length + " bytes");
}
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, 0, aesKeyBytes.length, "AES");
// Read the encrypted file content
byte[] encryptedFileContent = Files.readAllBytes(Paths.get(encFilePath));
// Decrypt the file content using AES
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // Specify padding
aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] decryptedFileContent = aesCipher.doFinal(encryptedFileContent);
// Write the decrypted content to the original file
Files.write(Paths.get(fullDecryptedPath + "." + fileExtension), decryptedFileContent);
// Cleanup temporary files
Files.deleteIfExists(Paths.get(encFilePath));
Files.deleteIfExists(Paths.get(keyFilePath));
return new InputStreamResource(new ByteArrayInputStream(decryptedData));
} catch (IOException e) {
throw new RuntimeException("Failed to stream file due to I/O issue: " + e.getMessage(), e);
} catch (Exception e) {
throw new RuntimeException("Failed to download or decrypt file: " + e.getMessage(), e);
throw new RuntimeException("Failed to stream file: " + e.getMessage(), e);
}
}
public void createFolder(String hdfsPath) {
try {
FileSystem fs = HDFSConfig.getHDFS();
@@ -3,37 +3,24 @@ package com.skycrate.backend.skycrateBackend.utils;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.*;
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 void generateAndStoreKeyPair(String username) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // Key size
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// Store the public key
Path publicKeyPath = Paths.get("C:\\Users\\sonal\\OneDrive\\Desktop\\SkyCrate\\Skycrate\\keys", username + "_public.key");
Files.write(publicKeyPath, keyPair.getPublic().getEncoded());
// Store the private key
Path privateKeyPath = Paths.get("C:\\Users\\sonal\\OneDrive\\Desktop\\SkyCrate\\Skycrate\\keys", username + "_private.key");
Files.write(privateKeyPath, keyPair.getPrivate().getEncoded());
}
public static PublicKey getPublicKeyForUser(String username) throws Exception {
Path path = Paths.get("C:\\Users\\sonal\\OneDrive\\Desktop\\SkyCrate\\Skycrate\\keys", username + "_public.key");
byte[] bytes = Files.readAllBytes(path);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
}
public static PrivateKey getPrivateKeyForUser(String username) throws Exception {
Path path = Paths.get("C:\\Users\\sonal\\OneDrive\\Desktop\\SkyCrate\\Skycrate\\keys", username + "_private.key");
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);
}
}
@@ -1,70 +0,0 @@
package com.skycrate.backend.skycrateBackend.utils;
import javax.crypto.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class RSAKeyUtil {
// Generate RSA Key Pair
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048); // Key size
return generator.generateKeyPair();
}
// Convert byte array to PublicKey
public static PublicKey getPublicKeyFromBytes(byte[] publicKeyBytes) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(spec);
}
// Convert byte array to PrivateKey
public static PrivateKey getPrivateKeyFromBytes(byte[] privateKeyBytes) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(spec);
}
// Encrypt data using RSA (with padding)
public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // Specify padding
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
// Decrypt data using RSA (with padding)
public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // Specify padding
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedData);
}
// Generate AES Key (128, 192, or 256 bits)
public static SecretKey generateAESKey(int keySize) throws NoSuchAlgorithmException {
if (keySize != 128 && keySize != 192 && keySize != 256) {
throw new IllegalArgumentException("Invalid AES key size. Must be 128, 192, or 256 bits.");
}
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keySize); // Specify the key size
return keyGenerator.generateKey();
}
// Encrypt AES Key using RSA
public static byte[] encryptAESKey(SecretKey aesKey, PublicKey publicKey) throws Exception {
return encrypt(aesKey.getEncoded(), publicKey); // Encrypt the AES key using RSA
}
// Decrypt AES Key using RSA
public static SecretKey decryptAESKey(byte[] encryptedAESKey, PrivateKey privateKey, int keySize) throws Exception {
byte[] decryptedKey = decrypt(encryptedAESKey, privateKey); // Decrypt with RSA
// Ensure that the decrypted key length matches the expected AES key size
if (decryptedKey.length != keySize / 8) {
throw new IllegalArgumentException("Decrypted key size does not match expected AES key size.");
}
return new SecretKeySpec(decryptedKey, 0, decryptedKey.length, "AES"); // Convert to AES Key
}
}
@@ -3,8 +3,6 @@ spring.application.name=skycrateBackend
spring.servlet.multipart.max-file-size=1000MB
spring.servlet.multipart.max-request-size=1000MB
spring.servlet.multipart.enabled=true
security.jwt.secret-key=3cfa76ef14937c1c0ea519f8fc057a80fcd04a7420f8e8bcd0a7567c272e007b
security.jwt.expiration-time=3600000