From d647ecb8a148b936bc16ab2202c499bdb08d9d89 Mon Sep 17 00:00:00 2001 From: lorenzhohermuth Date: Fri, 16 May 2025 10:41:50 +0200 Subject: [PATCH] added encryption to app --- .../controller/SecretController.java | 6 +- .../pr/tresorbackend/util/EncryptUtil.java | 124 ++++++++++++++++-- 2 files changed, 114 insertions(+), 16 deletions(-) diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java index 124b556..184e16a 100644 --- a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java @@ -36,7 +36,7 @@ public class SecretController { // create secret REST API @CrossOrigin(origins = "${CROSS_ORIGIN}") @PostMapping - public ResponseEntity createSecret2(@Valid @RequestBody NewSecret newSecret, BindingResult bindingResult) { + public ResponseEntity createSecret(@Valid @RequestBody NewSecret newSecret, BindingResult bindingResult) { //input validation if (bindingResult.hasErrors()) { List errors = bindingResult.getFieldErrors().stream() @@ -61,7 +61,7 @@ public class SecretController { Secret secret = new Secret( null, user.getId(), - new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent().toString()) + new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent()) ); //save secret in db secretService.createSecret(secret); @@ -195,7 +195,7 @@ public class SecretController { Secret secret = new Secret( secretId, user.getId(), - new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent().toString()) + new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent()) ); Secret updatedSecret = secretService.updateSecret(secret); //save secret in db diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java index dc37ad9..f1f461d 100644 --- a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java @@ -1,28 +1,126 @@ package ch.bbw.pr.tresorbackend.util; -import org.jasypt.util.text.AES256TextEncryptor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; +import java.util.function.Function; /** * EncryptUtil * Used to encrypt content. * Not implemented yet. + * * @author Peter Rutschmann */ public class EncryptUtil { + private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; + private SecretKey secretKey; - //todo ergänzen! + public EncryptUtil(String secretKey) { + System.out.println(secretKey); + this.secretKey = generateKey(secretKey); + } - public EncryptUtil(String secretKey) { - //todo ergänzen! - } + public String encrypt(JsonNode content) { + return changeRelevantValues(content, str -> encryptString(str, secretKey)); + } - public String encrypt(String data) { - //todo anpassen! - return data; - } + public String decrypt(String data) { - public String decrypt(String data) { - //todo anpassen! - return data; - } + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = mapper.readTree(data); + return changeRelevantValues(jsonNode, str -> decryptString(str, secretKey)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private String changeRelevantValues(JsonNode content, Function encryptOrDecrypt) { + if (!content.isObject()) return null; + ObjectNode objContent = (ObjectNode) content; + + String passwordTextValue = objContent.get("password").textValue(); + objContent.put("password", encryptOrDecrypt.apply(passwordTextValue)); + + String userNameTextValue = objContent.get("userName").textValue(); + objContent.put("userName", encryptOrDecrypt.apply(userNameTextValue)); + + String urlTextValue = objContent.get("url").textValue(); + objContent.put("url", encryptOrDecrypt.apply(urlTextValue)); + + return objContent.toPrettyString(); + } + + + public static String encryptString(String plainText, SecretKey key) { + try { + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + + // Generate a random IV for CBC mode + byte[] iv = new byte[16]; + SecureRandom.getInstanceStrong().nextBytes(iv); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + + cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); + byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8")); + + // Prepend the IV to the ciphertext (IV doesn't need to be secret) + byte[] combined = new byte[iv.length + encryptedBytes.length]; + System.arraycopy(iv, 0, combined, 0, iv.length); + System.arraycopy(encryptedBytes, 0, combined, iv.length, encryptedBytes.length); + + return Base64.getEncoder().encodeToString(combined); + } catch (Exception e) { + throw new RuntimeException("Encryption failed", e); + } + } + + public static String decryptString(String encryptedText, SecretKey key) { + try { + byte[] combined = Base64.getDecoder().decode(encryptedText); + + if (combined.length <= 16) { + throw new IllegalArgumentException("Invalid ciphertext (too short)"); + } + + // Extract IV (first 16 bytes) + byte[] iv = new byte[16]; + System.arraycopy(combined, 0, iv, 0, iv.length); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + + // Extract ciphertext (remaining bytes) + byte[] ciphertext = new byte[combined.length - iv.length]; + System.arraycopy(combined, iv.length, ciphertext, 0, ciphertext.length); + + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); + byte[] decryptedBytes = cipher.doFinal(ciphertext); + + return new String(decryptedBytes, "UTF-8"); + } catch (Exception e) { + throw new RuntimeException("Decryption failed", e); + } + } + + public static SecretKey generateKey(String seed) { + try { + byte[] keyBytes = new byte[16]; + byte[] seedBytes = seed.getBytes(StandardCharsets.UTF_8); + System.arraycopy(seedBytes, 0, keyBytes, 0, Math.min(seedBytes.length, keyBytes.length)); + return new SecretKeySpec(keyBytes, "AES"); + } catch (Exception e) { + throw new RuntimeException("Key generation error.", e); + } + } }