121 lines
5.2 KiB
Java
121 lines
5.2 KiB
Java
package com.skycrate.backend.skycrateBackend.services;
|
|
|
|
import com.skycrate.backend.skycrateBackend.config.HDFSConfig;
|
|
import com.skycrate.backend.skycrateBackend.dto.LoginUserDto;
|
|
import com.skycrate.backend.skycrateBackend.dto.RegisterUserDto;
|
|
import com.skycrate.backend.skycrateBackend.entity.User;
|
|
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
|
|
import com.skycrate.backend.skycrateBackend.utils.EncryptionUtil;
|
|
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
|
|
import org.apache.hadoop.fs.FileSystem;
|
|
import org.apache.hadoop.fs.Path;
|
|
import org.springframework.cache.annotation.CacheEvict;
|
|
import org.springframework.cache.annotation.Cacheable;
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import javax.crypto.SecretKey;
|
|
import java.security.KeyPair;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
@Service
|
|
public class AuthenticationService {
|
|
|
|
private final UserRepository userRepository;
|
|
private final PasswordEncoder passwordEncoder;
|
|
private final AuthenticationManager authenticationManager;
|
|
private final KeyCacheService keyCacheService;
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(AuthenticationService.class);
|
|
|
|
public AuthenticationService(UserRepository userRepository,
|
|
AuthenticationManager authenticationManager,
|
|
PasswordEncoder passwordEncoder,
|
|
KeyCacheService keyCacheService) {
|
|
this.userRepository = userRepository;
|
|
this.passwordEncoder = passwordEncoder;
|
|
this.authenticationManager = authenticationManager;
|
|
this.keyCacheService = keyCacheService;
|
|
}
|
|
|
|
public User signUp(RegisterUserDto inputUser) {
|
|
// Generate RSA key pair
|
|
KeyPair keyPair;
|
|
try {
|
|
keyPair = RSAKeyUtil.generateKeyPair();
|
|
} catch (NoSuchAlgorithmException e) {
|
|
throw new RuntimeException("Failed to generate RSA key pair", e);
|
|
}
|
|
|
|
// Encrypt private key using password-derived AES key
|
|
byte[] salt = EncryptionUtil.generateSalt();
|
|
byte[] iv = EncryptionUtil.generateIv();
|
|
byte[] encryptedPrivateKey;
|
|
try {
|
|
SecretKey aesKey = EncryptionUtil.deriveKey(inputUser.getPassword().toCharArray(), salt);
|
|
encryptedPrivateKey = EncryptionUtil.encrypt(keyPair.getPrivate().getEncoded(), aesKey, iv);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("Failed to encrypt private key", e);
|
|
}
|
|
|
|
// Create user entity with encrypted private key, salt, and iv
|
|
User user = User.builder()
|
|
.fullname(inputUser.getFirstname() + " " + inputUser.getLastname())
|
|
.username(inputUser.getUsername())
|
|
.email(inputUser.getEmail())
|
|
.password(passwordEncoder.encode(inputUser.getPassword()))
|
|
.publicKey(keyPair.getPublic().getEncoded())
|
|
.privateKey(encryptedPrivateKey)
|
|
.privateKeySalt(salt)
|
|
.privateKeyIv(iv)
|
|
.build();
|
|
|
|
// Save user
|
|
User savedUser = userRepository.save(user);
|
|
|
|
// Create HDFS directory in root with username
|
|
try {
|
|
FileSystem fs = HDFSConfig.getHDFS();
|
|
Path userDir = new Path("/" + savedUser.getUsername());
|
|
if (!fs.exists(userDir)) {
|
|
fs.mkdirs(userDir);
|
|
}
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("Failed to create HDFS directory for user: " + savedUser.getUsername(), e);
|
|
}
|
|
|
|
return savedUser;
|
|
}
|
|
|
|
public User authenticate(LoginUserDto inputUser) {
|
|
authenticationManager.authenticate(
|
|
new UsernamePasswordAuthenticationToken(inputUser.getEmail(), inputUser.getPassword())
|
|
);
|
|
|
|
return userRepository.findByEmail(inputUser.getEmail())
|
|
.orElseThrow(() -> new RuntimeException("User not found"));
|
|
}
|
|
|
|
@Cacheable(value = "decryptedPrivateKeys", key = "#userId")
|
|
public byte[] getDecryptedPrivateKey(String userId, String password) throws Exception {
|
|
User user = userRepository.findById(Integer.valueOf(userId))
|
|
.orElseThrow(() -> new RuntimeException("User not found: " + userId));
|
|
|
|
log.info("Caching decrypted private key for userId: {}", userId);
|
|
|
|
SecretKey derivedKey = EncryptionUtil.deriveKey(password.toCharArray(), user.getPrivateKeySalt());
|
|
byte[] decryptedPrivateKeyBytes = EncryptionUtil.decrypt(user.getPrivateKey(), derivedKey, user.getPrivateKeyIv());
|
|
return decryptedPrivateKeyBytes;
|
|
}
|
|
|
|
@CacheEvict(value = "decryptedPrivateKeys", key = "#userId")
|
|
public void clearDecryptedPrivateKeyCache(String userId) {
|
|
// This method will clear the cached decrypted private key for the given userId
|
|
log.info("Clearing Caching decrypted private key for userId: {}", userId);
|
|
keyCacheService.clearKey(Long.valueOf(userId));
|
|
}
|
|
} |