package net.tim;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
public class EncryptionService {
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static void CipherFile(boolean encrypt,IvParameterSpec iv , SecretKey key,
File inputFile, File outputFile)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException,
IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(ALGORITHM);
if (encrypt) {
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
} else {
cipher.init(Cipher.DECRYPT_MODE, key, iv);
}
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
inputStream.close();
outputStream.close();
}
public static void CipherFile(boolean encrypt, File inputFile, File outputFile, User user, String password) {
try {
SecretKey key = getKeyFromPassword(password, new String(user.getSalt()));
IvParameterSpec iv = new IvParameterSpec(user.getIv());
CipherFile(encrypt, iv, key, inputFile, outputFile);
} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
e.printStackTrace();
}
}
public static IvParameterSpec generateIv() {
SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[16];
randomSecureRandom.nextBytes(iv);
return new IvParameterSpec(iv);
}
public static SecretKey getKeyFromPassword(String password, String salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
}
//Method to generate a random salt
public static String getSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
return new String(salt);
}
//Generate a Hash from a password
public static String getHash(String password, String salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
byte[] hash = factory.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(hash);
}
}