diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java index 570d216c..8e6fbb44 100644 --- a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java @@ -1,9 +1,13 @@ package com.example.cs25service.domain.quiz.controller; import com.example.cs25common.global.dto.ApiResponse; +import com.example.cs25service.domain.quiz.dto.TodayQuizResponseDto; import com.example.cs25service.domain.quiz.service.QuizAccuracyCalculateService; +import com.example.cs25service.domain.quiz.service.QuizPageService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -11,6 +15,7 @@ public class QuizTestController { private final QuizAccuracyCalculateService accuracyService; + private final QuizPageService quizPageService; @GetMapping("/accuracyTest") public ApiResponse accuracyTest() { @@ -27,6 +32,17 @@ public ApiResponse accuracyTest() { // return new ApiResponse<>(200); // } +// @GetMapping("/test/todayQuiz") +// public ApiResponse showTodayQuizPage( +// @RequestParam("quizId") String quizId +// ) { +// +// return new ApiResponse<>( +// 200, +// quizPageService.showTodayQuizPage(quizId) +// ); +// } + // @GetMapping("/test/sse") // public void testSse(HttpServletResponse response) throws IOException { // response.setContentType("text/event-stream"); diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java index 948077c7..4491a7f1 100644 --- a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java @@ -8,6 +8,8 @@ import com.example.cs25service.domain.quiz.dto.TodayQuizResponseDto; import java.util.Arrays; import java.util.List; + +import com.example.cs25service.domain.quiz.util.AesUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,7 +20,7 @@ public class QuizPageService { private final QuizRepository quizRepository; - + private final AesUtil aesUtil; /** * 오늘의 문제를 반환해주는 메서드 * @param quizId 문제 id @@ -56,8 +58,8 @@ private TodayQuizResponseDto getMultipleQuiz(Quiz quiz) { .choice2(choices.get(1)) .choice3(choices.get(2)) .choice4(choices.get(3)) - .answerNumber(answerNumber) - .commentary(quiz.getCommentary()) + .answerNumber(aesUtil.encrypt(answerNumber)) + .commentary(aesUtil.encrypt(quiz.getCommentary())) .quizType(quiz.getType().name()) .quizLevel(quiz.getLevel().name()) .category(getQuizCategory(quiz)) @@ -74,8 +76,8 @@ private TodayQuizResponseDto getDescriptiveQuiz(Quiz quiz) { return TodayQuizResponseDto.builder() .question(quiz.getQuestion()) .quizType(quiz.getQuestion()) - .answer(quiz.getAnswer()) - .commentary(quiz.getCommentary()) + .answer(aesUtil.encrypt(quiz.getAnswer())) + .commentary(aesUtil.encrypt(quiz.getCommentary())) .quizType(quiz.getType().name()) .quizLevel(quiz.getLevel().name()) .category(getQuizCategory(quiz)) diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java new file mode 100644 index 00000000..911cc953 --- /dev/null +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java @@ -0,0 +1,72 @@ +package com.example.cs25service.domain.quiz.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; + +@Component +public class AesUtil { + + private final String secretKey; + + public AesUtil(@Value("${aes.secret.key}") String secretKey) { + this.secretKey = secretKey; + } + + private final String ALGORITHM = "AES/CBC/PKCS5Padding"; + + private SecretKey getKey() { + return new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"); + } + + /** 암호화 */ + public String encrypt(String plainText) { + if (plainText == null) return null; + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + byte[] iv = new byte[16]; + new SecureRandom().nextBytes(iv); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + + cipher.init(Cipher.ENCRYPT_MODE, getKey(), ivSpec); + byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); + + // IV와 암호문을 Base64로 함께 인코딩 + byte[] combined = new byte[iv.length + encrypted.length]; + System.arraycopy(iv, 0, combined, 0, iv.length); + System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length); + + return Base64.getEncoder().encodeToString(combined); + } catch (Exception e) { + throw new RuntimeException("AES encryption error", e); + } + } + + /** 복호화 */ + public String decrypt(String cipherText) { + if (cipherText == null) return null; + try { + byte[] decoded = Base64.getDecoder().decode(cipherText); + + byte[] iv = new byte[16]; + byte[] encrypted = new byte[decoded.length - 16]; + System.arraycopy(decoded, 0, iv, 0, iv.length); + System.arraycopy(decoded, iv.length, encrypted, 0, encrypted.length); + + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv)); + byte[] original = cipher.doFinal(encrypted); + + return new String(original, StandardCharsets.UTF_8); + } catch (Exception e) { + throw new RuntimeException("AES decryption error", e); + } + } +} diff --git a/cs25-service/src/main/resources/application.properties b/cs25-service/src/main/resources/application.properties index 39649f39..12d8568c 100644 --- a/cs25-service/src/main/resources/application.properties +++ b/cs25-service/src/main/resources/application.properties @@ -137,4 +137,6 @@ server.servlet.session.cookie.secure=true FRONT_END_URI=https://cs25.co.kr ## JSESSIONID Secure - ?? #server.servlet.session.cookie.secure=true -#FRONT_END_URI=http://localhost:5173 \ No newline at end of file +#FRONT_END_URI=http://localhost:5173 +#AES SECRET KEY +aes.secret.key=${AES_KEY} \ No newline at end of file