package me.zacharias.bank; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; public class Utils { public static final Gson gson; static { GsonBuilder gsonBuilder = new GsonBuilder(); //gsonBuilder.registerTypeAdapter(Account.class, new AccountAdapter()); gson = gsonBuilder.create(); File users = new File("./users"); if(!users.exists()) { users.mkdir(); } } public static String SHA256(String input) { MessageDigest sha256 = null; try { sha256 = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } byte[] hash = sha256.digest(input.getBytes(StandardCharsets.UTF_8)); StringBuilder hexString = new StringBuilder(); for (byte b : hash) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexString.append('0'); hexString.append(hex); } return hexString.toString(); } private static final int KEY_SIZE = 256; private static final int ITERATIONS = 65536; private static final int SALT_LENGTH = 16; private static final int IV_LENGTH = 12; public static String Encrypt(String data, String username) throws Exception { SecureRandom random = new SecureRandom(); byte[] salt = new byte[SALT_LENGTH]; random.nextBytes(salt); byte[] iv = new byte[IV_LENGTH]; random.nextBytes(iv); SecretKey key = deriveKey(username, salt); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec); byte[] encryptedData = cipher.doFinal(data.getBytes()); byte[] combined = new byte[salt.length + iv.length + encryptedData.length]; System.arraycopy(salt, 0, combined, 0, salt.length); System.arraycopy(iv, 0, combined, salt.length, iv.length); System.arraycopy(encryptedData, 0, combined, salt.length + iv.length, encryptedData.length); return Base64.getEncoder().encodeToString(combined); } public static String Decrypt(String data, String username) throws Exception { byte[] combined = Base64.getDecoder().decode(data); // Extract salt, IV, and encrypted data byte[] salt = new byte[SALT_LENGTH]; byte[] iv = new byte[IV_LENGTH]; byte[] cipherText = new byte[combined.length - SALT_LENGTH - IV_LENGTH]; System.arraycopy(combined, 0, salt, 0, salt.length); System.arraycopy(combined, salt.length, iv, 0, iv.length); System.arraycopy(combined, salt.length + iv.length, cipherText, 0, cipherText.length); SecretKey key = deriveKey(username, salt); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec); byte[] decrptedData = cipher.doFinal(cipherText); return new String(decrptedData); } private static SecretKey deriveKey(String password, byte[] salt) throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_SIZE); return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); } public static String ReadFile(File file) { if(!file.exists()) { throw new RuntimeException(new FileNotFoundException(file.getPath()+" not found")); } try { BufferedReader br = new BufferedReader(new FileReader(file)); StringBuilder sb = new StringBuilder(); String line; while((line = br.readLine()) != null) { sb.append(line); } return sb.toString(); } catch (IOException e) { throw new RuntimeException(e); } } public static void WriteFile(File file, String data) { if(file.exists()) { file.delete(); } try { file.createNewFile(); BufferedWriter bw = new BufferedWriter(new FileWriter(file)); bw.write(data); bw.close(); }catch (IOException e) { throw new RuntimeException(e); } } }